From cfbolz at codespeak.net Tue Apr 1 00:28:30 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 1 Apr 2008 00:28:30 +0200 (CEST) Subject: [pypy-svn] r53221 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080331222830.8DE1816844B@codespeak.net> Author: cfbolz Date: Tue Apr 1 00:28:29 2008 New Revision: 53221 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py Log: fix a bug in the fallback interp Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Tue Apr 1 00:28:29 2008 @@ -36,6 +36,25 @@ jitstate.residual_ll_exception(ll_exc) +def make_colororder(graph, hannotator): + # if the graph takes both red and green arguments, we need + # a way for the fallback interp to rezip the two lists + # 'greenargs' and 'redargs' into a single one + colororder = "" + in_order = True # "in order" means allgreens+allreds + for v in graph.getargs(): + if v.concretetype is lltype.Void: + continue + if hannotator.binding(v).is_green(): + if "r" in colororder: + in_order = False + colororder += "g" + else: + colororder += "r" + if in_order: + colororder = None + return colororder + class CallDesc: __metaclass__ = cachedtype @@ -131,6 +150,9 @@ fnptr = codewriter.rtyper.getcallable(graph) keys.append(llmemory.cast_ptr_to_adr(fnptr)) values.append(codewriter.get_jitcode(tsgraph)) + # arbitrarily use the last graph to make the colororder - + # normalization should ensure that all colors are the same + colororder = make_colororder(tsgraph, codewriter.hannotator) def bytecode_for_address(fnaddress): # XXX optimize @@ -143,7 +165,7 @@ self.graphs = [graph for (graph, tsgraph) in graph2tsgraph] self.jitcodes = values self.calldesc = CallDesc(codewriter.RGenOp, codewriter.exceptiondesc, - lltype.typeOf(fnptr)) + lltype.typeOf(fnptr), colororder) class BytecodeWriter(object): @@ -301,22 +323,7 @@ RESULT = graph.getreturnvar().concretetype FUNCTYPE = lltype.FuncType(ARGS, RESULT) - # if the graph takes both red and green arguments, we need - # a way for the fallback interp to rezip the two lists - # 'greenargs' and 'redargs' into a single one - colororder = "" - in_order = True # "in order" means allgreens+allreds - for v in graph.getargs(): - if v.concretetype is lltype.Void: - continue - if self.hannotator.binding(v).is_green(): - if "r" in colororder: - in_order = False - colororder += "g" - else: - colororder += "r" - if in_order: - colororder = None + colororder = make_colororder(graph, self.hannotator) owncalldesc = CallDesc(self.RGenOp, self.exceptiondesc, lltype.Ptr(FUNCTYPE), colororder) # detect the special ts_stub or ts_metacall graphs and replace Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py Tue Apr 1 00:28:29 2008 @@ -3,7 +3,8 @@ from pypy.rlib.jit import JitDriver, hint, JitHintError from pypy.jit.rainbow.test import test_interpreter from pypy.jit.rainbow.hotpath import HotRunnerDesc -from pypy.jit.hintannotator.policy import HintAnnotatorPolicy +from pypy.jit.hintannotator.policy import HintAnnotatorPolicy, \ + StopAtXPolicy from pypy.rpython.llinterp import LLInterpreter from pypy import conftest @@ -587,3 +588,33 @@ res = self.run(ll_function, [40], threshold=2) assert "".join(res.chars) == " ".join([str(i) for i in range(1, 80)]) self.check_insns(malloc=1) + + def test_indirect_call_fallback_color_order(self): + class A(object): + def g(self, green, red): + return red + green + + class B(A): + def g(self, green, red): + return red - green + + myjitdriver = JitDriver(greens = ['x'], + reds = ['a', 'i', 'tot']) + def g(isnotnone): + if isnotnone: + return A() + return B() + def f(isnotnone, x): + a = g(isnotnone) + i = 1024 * 1024 + tot = 0 + while i > 0: + i >>= 1 + tot += a.g(x, i) + hint(x, concrete=True) + myjitdriver.jit_merge_point(tot=tot, i=i, a=a, x=x) + myjitdriver.can_enter_jit(tot=tot, i=i, a=a, x=x) + return tot + res = self.run(f, [False, 5], threshold=4, policy=StopAtXPolicy(g)) + assert res == f(False, 5) + From fijal at codespeak.net Tue Apr 1 01:26:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 01:26:22 +0200 (CEST) Subject: [pypy-svn] r53222 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080331232622.E9EF216845C@codespeak.net> Author: fijal Date: Tue Apr 1 01:26:21 2008 New Revision: 53222 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py Log: some general progress in area of assignments. Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Tue Apr 1 01:26:21 2008 @@ -40,16 +40,10 @@ #'!': operations.Not, '+': operations.UPlus, '-': operations.UMinus, - '++': operations.PreIncrement, - '--': operations.PreDecrement, #'typeof': operations.Typeof, #'void': operations.Void, #'delete': operations.Delete, } - POSTFIX_TO_CLS = { - '++': operations.PostIncrement, - '--': operations.PostDecrement, - } LISTOP_TO_CLS = { '[': operations.Array, '{': operations.ObjectInit, @@ -161,14 +155,35 @@ op = node.children[0] pos = self.get_pos(op) child = self.dispatch(node.children[1]) + if op.additional_info in ['++', '--']: + return self._dispatch_assignment(pos, child, op.additional_info, + 'pre') return self.UNOP_TO_CLS[op.additional_info](pos, child) + def _dispatch_assignment(self, pos, left, atype, prepost): + from pypy.lang.js.operations import Identifier, Member, MemberDot,\ + VariableIdentifier + + if isinstance(left, Identifier): + return operations.SimpleAssignment(pos, left, None, atype, prepost) + elif isinstance(left, VariableIdentifier): + return operations.VariableAssignment(pos, left, None, atype, + prepost) + elif isinstance(left, Member): + return operations.MemberAssignment(pos, left.left, left.expr, + None, atype, prepost) + elif isinstance(left, MemberDot): + return operations.MemberDotAssignment(pos, left.left, left.name, + None, atype, prepost) + else: + return operations.SimpleIncrement(pos, left, atype) + def visit_postfixexpression(self, node): op = node.children[1] pos = self.get_pos(op) child = self.dispatch(node.children[0]) - return self.POSTFIX_TO_CLS[op.additional_info](pos, child) - + # all postfix expressions are assignments + return self._dispatch_assignment(pos, child, op.additional_info, 'post') def listop(self, node): op = node.children[0] Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Tue Apr 1 01:26:21 2008 @@ -241,21 +241,46 @@ def __repr__(self): return 'LOAD_FUNCTION' # XXX -class STORE_MEMBER(Opcode): +class BaseStoreMember(Opcode): pass #def eval(self, ctx, ): # XXX -class STORE(Opcode): +class STORE_MEMBER(Opcode): + pass + +class STORE_MEMBER_POSTINCR(Opcode): + pass + +class STORE_MEMBER_PREINCR(Opcode): + pass + +class STORE_MEMBER_SUB(Opcode): + pass + +class BaseStore(Opcode): def __init__(self, name): self.name = name def eval(self, ctx, stack): value = stack[-1] + value = self.process(ctx, self.name, value) ctx.assign(self.name, value) def __repr__(self): - return 'STORE "%s"' % self.name + return '%s "%s"' % (self.__class__.__name__, self.name) + +class STORE(BaseStore): + def process(self, ctx, name, value): + return value + +class STORE_ADD(BaseStore): + def process(self, ctx, name, value): + xxx + +class STORE_POSTINCR(BaseStore): + def process(self, ctx, name, value): + xxx class STORE_VAR(Opcode): def __init__(self, depth, name): @@ -338,17 +363,11 @@ class UMINUS(BaseUnaryOperation): pass -#class PREINCR(BaseUnaryOperation): -# pass - -#class POSTINCR(BaseUnaryOperation): -# pass - -#class PREDECR(BaseUnaryOperation): -# pass +class INCR(BaseUnaryOperation): + pass -#class POSTDECR(BaseUnaryOperation): -# pass +class DECR(BaseUnaryOperation): + pass class GT(BaseBinaryComparison): def decision(self, ctx, op1, op2): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Tue Apr 1 01:26:21 2008 @@ -121,18 +121,48 @@ bytecode.emit('LOAD_ARRAY', len(self.nodes)) class Assignment(Expression): - pass + def _get_name(self): + addoper = OPERANDS[self.operand] + if addoper: + addoper = '_' + self.prefix.upper() + addoper + return addoper + +OPERANDS = { + '=' : '', + '+=' : 'ADD', + '-=' : 'SUB', + '*=' : 'MUL', + '/=' : 'DIV', + '++' : 'INCR', + '--' : 'DECR', + } + +class SimpleIncrement(Expression): + def __init__(self, pos, left, atype): + self.pos = pos + self.left = left + self.atype = atype + + def emit(self, bytecode): + self.left.emit(bytecode) + if self.atype == '++': + bytecode.emit('INCR') + elif self.atype == '--': + bytecode.emit('DECR') class SimpleAssignment(Assignment): - def __init__(self, pos, left, right, operand): + def __init__(self, pos, left, right, operand, prefix=''): self.identifier = left.get_literal() self.right = right self.pos = pos self.operand = operand + self.prefix = prefix def emit(self, bytecode): - self.right.emit(bytecode) - bytecode.emit('STORE', self.identifier) + if self.right is not None: + self.right.emit(bytecode) + bytecode_name = 'STORE' + self._get_name() + bytecode.emit(bytecode_name, self.identifier) class VariableAssignment(Assignment): def __init__(self, pos, left, right, operand): @@ -147,7 +177,7 @@ bytecode.emit('STORE_VAR', self.depth, self.identifier) class MemberAssignment(Assignment): - def __init__(self, pos, what, item, right, operand): + def __init__(self, pos, what, item, right, operand, prefix=''): # XXX we can optimise here what happens if what is identifier, # but let's leave it alone for now self.pos = pos @@ -155,26 +185,30 @@ self.item = item self.right = right self.operand = operand + self.prefix = prefix def emit(self, bytecode): - self.right.emit(bytecode) + if self.right is not None: + self.right.emit(bytecode) self.item.emit(bytecode) self.what.emit(bytecode) - bytecode.emit('STORE_MEMBER') + bytecode.emit('STORE_MEMBER' + self._get_name()) class MemberDotAssignment(Assignment): - def __init__(self, pos, what, name, right, operand): + def __init__(self, pos, what, name, right, operand, prefix=''): self.pos = pos self.what = what self.itemname = name self.right = right self.operand = operand + self.prefix = prefix def emit(self, bytecode): - self.right.emit(bytecode) + if self.right is not None: + self.right.emit(bytecode) bytecode.emit('LOAD_STRINGCONSTANT', self.itemname) self.what.emit(bytecode) - bytecode.emit('STORE_MEMBER') + bytecode.emit('STORE_MEMBER' + self._get_name()) class StuffAssignment(Expression): def __init__(self, pos, left, right, operand): @@ -507,11 +541,6 @@ # r4 = r1.GetPropertyName() # return W_Boolean(r3.Delete(r4)) -PreIncrement = create_unary_op('PREINCR') -PostIncrement = create_unary_op('POSTINCR') -PreDecrement = create_unary_op('PREDECRE') -PostDecrement = create_unary_op('POSTDECR') - #class Index(BinaryOp): # def eval(self, ctx): # w_obj = self.left.eval(ctx).GetValue().ToObject(ctx) Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py Tue Apr 1 01:26:21 2008 @@ -360,10 +360,10 @@ 'SUB']) self.check('++5', [ 'LOAD_INTCONSTANT 5', - 'PREINCR']) + 'INCR']) self.check('5--', [ 'LOAD_INTCONSTANT 5', - 'POSTDECR']) + 'DECR']) self.check('"hello " + \'world\'', ['LOAD_STRINGCONSTANT "hello "', 'LOAD_STRINGCONSTANT "world"', @@ -478,6 +478,25 @@ 'STORE_MEMBER', 'POP']) + def test_different_assignments(self): + self.check('x += y', [ + 'LOAD_VARIABLE "y"', + 'STORE_ADD "x"', + 'POP']) + self.check('x++', ['STORE_POSTINCR "x"', + 'POP']) + self.check('++x[2]', [ + 'LOAD_INTCONSTANT 2', + 'LOAD_VARIABLE "x"', + 'STORE_MEMBER_PREINCR', + 'POP']) + self.check('x.y -= 2', + ['LOAD_INTCONSTANT 2', + 'LOAD_STRINGCONSTANT "y"', + 'LOAD_VARIABLE "x"', + 'STORE_MEMBER_SUB', + 'POP']) + from pypy.lang.js.jsparser import parse def test_simplesemicolon(): From fijal at codespeak.net Tue Apr 1 04:39:44 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 04:39:44 +0200 (CEST) Subject: [pypy-svn] r53223 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080401023944.5523E168439@codespeak.net> Author: fijal Date: Tue Apr 1 04:39:42 2008 New Revision: 53223 Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: * Fix reprs * First assignments work Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Tue Apr 1 04:39:42 2008 @@ -24,6 +24,12 @@ fright = nright.ToNumber() return W_FloatNumber(fleft + fright) +def increment(ctx, nleft, constval=1): + if isinstance(nleft, W_IntNumber): + return W_IntNumber(nleft.intval + constval) + else: + return plus(ctx, nleft, W_IntNumber(constval)) + def sub(ctx, nleft, nright): if isinstance(nleft, W_IntNumber) and isinstance(nright, W_IntNumber): ileft = nleft.ToInt32() Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Tue Apr 1 04:39:42 2008 @@ -6,7 +6,7 @@ from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException from pypy.rlib.unroll import unrolling_iterable from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ - compare_e + compare_e, increment from pypy.rlib.jit import hint class AlreadyRun(Exception): @@ -28,6 +28,10 @@ if check_stack: assert not stack +class T(list): + def append(self, element): + assert element is not None + super(T, self).append(element) class JsCode(object): """ That object stands for code of a single javascript function @@ -36,7 +40,7 @@ self.opcodes = [] self.label_count = 0 self.has_labels = True - self.stack = [] + self.stack = T() def emit_label(self): num = self.prealocate_label() @@ -121,8 +125,8 @@ class BaseBinaryComparison(Opcode): def eval(self, ctx, stack): - s4 = stack.pop()#.GetValue() - s2 = stack.pop()#.GetValue() + s4 = stack.pop() + s2 = stack.pop() stack.append(self.decision(ctx, s2, s4)) def decision(self, ctx, op1, op2): @@ -130,8 +134,8 @@ class BaseBinaryBitwiseOp(Opcode): def eval(self, ctx, stack): - s5 = stack.pop().ToInt32()#.GetValue().ToInt32() - s6 = stack.pop().ToInt32()#.GetValue().ToInt32() + s5 = stack.pop().ToInt32() + s6 = stack.pop().ToInt32() stack.append(self.operation(ctx, s5, s6)) def operation(self, ctx, op1, op2): @@ -139,8 +143,8 @@ class BaseBinaryOperation(Opcode): def eval(self, ctx, stack): - right = stack.pop()#.GetValue() - left = stack.pop()#.GetValue() + right = stack.pop() + left = stack.pop() stack.append(self.operation(ctx, left, right)) class BaseUnaryOperation(Opcode): @@ -218,7 +222,7 @@ proto = ctx.get_global().Get('Array').Get('prototype') array = W_Array(ctx, Prototype=proto, Class = proto.Class) for i in range(self.counter): - array.Put(str(self.counter - i - 1), stack.pop())#.GetValue()) + array.Put(str(self.counter - i - 1), stack.pop()) stack.append(array) def __repr__(self): @@ -263,24 +267,26 @@ self.name = name def eval(self, ctx, stack): - value = stack[-1] - value = self.process(ctx, self.name, value) + value = self.process(ctx, self.name, stack) ctx.assign(self.name, value) def __repr__(self): return '%s "%s"' % (self.__class__.__name__, self.name) class STORE(BaseStore): - def process(self, ctx, name, value): - return value + def process(self, ctx, name, stack): + return stack[-1] class STORE_ADD(BaseStore): - def process(self, ctx, name, value): + def process(self, ctx, name, stack): xxx class STORE_POSTINCR(BaseStore): - def process(self, ctx, name, value): - xxx + def process(self, ctx, name, stack): + value = ctx.resolve_identifier(name) + newval = increment(ctx, value) + stack.append(newval) + return newval class STORE_VAR(Opcode): def __init__(self, depth, name): @@ -301,8 +307,8 @@ def eval(self, ctx, stack): w_obj = create_object(ctx, 'Object') for _ in range(self.counter): - name = stack.pop().ToString(ctx)#.GetValue().ToString(ctx) - w_elem = stack.pop()#.GetValue() + name = stack.pop().ToString(ctx) + w_elem = stack.pop() w_obj.Put(name, w_elem) stack.append(w_obj) @@ -314,7 +320,7 @@ self.name = name def eval(self, ctx, stack): - w_obj = stack.pop().ToObject(ctx)#GetValue().ToObject(ctx) + w_obj = stack.pop().ToObject(ctx) stack.append(w_obj.Get(self.name)) #stack.append(W_Reference(self.name, w_obj)) @@ -323,8 +329,8 @@ class LOAD_ELEMENT(Opcode): def eval(self, ctx, stack): - name = stack.pop().ToString(ctx)#GetValue().ToString(ctx) - w_obj = stack.pop().ToObject(ctx)#GetValue().ToObject(ctx) + name = stack.pop().ToString(ctx) + w_obj = stack.pop().ToObject(ctx) stack.append(w_obj.Get(name)) #stack.append(W_Reference(name, w_obj)) @@ -508,8 +514,7 @@ def eval(self, ctx, stack): r1 = stack.pop() args = stack.pop() - r3 = r1#.GetValue() - if not isinstance(r3, W_PrimitiveObject): + if not isinstance(r1, W_PrimitiveObject): raise ThrowException(W_String("it is not a callable")) if isinstance(r1, W_Reference): @@ -521,7 +526,7 @@ else: r7 = r6 try: - res = r3.Call(ctx=ctx, args=args.tolist(), this=r7) + res = r1.Call(ctx=ctx, args=args.tolist(), this=r7) except JsTypeError: raise ThrowException(W_String('it is not a function')) stack.append(res) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Tue Apr 1 04:39:42 2008 @@ -413,9 +413,6 @@ def __init__(self, intval): self.intval = intmask(intval) - def __str__(self): - return str(self.intval)+"W" - def ToString(self, ctx=None): return str(self.intval) @@ -435,14 +432,14 @@ def GetPropertyName(self): return self.ToString() + def __repr__(self): + return 'W_IntNumber(%s)' % (self.intval,) + class W_FloatNumber(W_BaseNumber): """ Number known to be a float """ def __init__(self, floatval): self.floatval = floatval - - def __str__(self): - return str(self.floatval)+"W" def ToString(self, ctx = None): if isnan(self.floatval): @@ -474,6 +471,9 @@ if isnan(self.floatval) or isinf(self.floatval): return r_uint(0) return r_uint(self.floatval) + + def __repr__(self): + return 'W_FloatNumber(%s)' % (self.floatval,) class W_List(W_Root): def __init__(self, list_w): @@ -487,10 +487,10 @@ def get_args(self): return self.list_w - - def __str__(self): - return str(self.list_w) + def __repr__(self): + return 'W_List(%s)' % (self.list_w,) + class ExecutionContext(object): def __init__(self, scope, this=None, variable=None, debug=False, jsproperty=None): From fijal at codespeak.net Tue Apr 1 04:53:14 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 04:53:14 +0200 (CEST) Subject: [pypy-svn] r53224 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080401025314.58EE516843A@codespeak.net> Author: fijal Date: Tue Apr 1 04:53:13 2008 New Revision: 53224 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: * disable variable assignment, it's not working anyway * make more operations pass Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Tue Apr 1 04:53:13 2008 @@ -167,7 +167,8 @@ if isinstance(left, Identifier): return operations.SimpleAssignment(pos, left, None, atype, prepost) elif isinstance(left, VariableIdentifier): - return operations.VariableAssignment(pos, left, None, atype, + # XXX exchange to VariableAssignment + return operations.SimpleAssignment(pos, left, None, atype, prepost) elif isinstance(left, Member): return operations.MemberAssignment(pos, left.left, left.expr, @@ -326,7 +327,8 @@ if isinstance(left, Identifier): return operations.SimpleAssignment(pos, left, right, atype) elif isinstance(left, VariableIdentifier): - return operations.VariableAssignment(pos, left, right, atype) + # XXX exchange to VariableAssignment + return operations.SimpleAssignment(pos, left, right, atype) elif isinstance(left, Member): return operations.MemberAssignment(pos, left.left, left.expr, right, atype) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Tue Apr 1 04:53:13 2008 @@ -245,60 +245,17 @@ def __repr__(self): return 'LOAD_FUNCTION' # XXX -class BaseStoreMember(Opcode): - pass - #def eval(self, ctx, ): - # XXX - -class STORE_MEMBER(Opcode): - pass - -class STORE_MEMBER_POSTINCR(Opcode): - pass - -class STORE_MEMBER_PREINCR(Opcode): - pass - -class STORE_MEMBER_SUB(Opcode): - pass - -class BaseStore(Opcode): - def __init__(self, name): - self.name = name - - def eval(self, ctx, stack): - value = self.process(ctx, self.name, stack) - ctx.assign(self.name, value) - - def __repr__(self): - return '%s "%s"' % (self.__class__.__name__, self.name) - -class STORE(BaseStore): - def process(self, ctx, name, stack): - return stack[-1] - -class STORE_ADD(BaseStore): - def process(self, ctx, name, stack): - xxx - -class STORE_POSTINCR(BaseStore): - def process(self, ctx, name, stack): - value = ctx.resolve_identifier(name) - newval = increment(ctx, value) - stack.append(newval) - return newval - -class STORE_VAR(Opcode): - def __init__(self, depth, name): - self.name = name - self.depth = depth - - def eval(self, ctx, stack): - value = stack[-1] - ctx.scope[self.depth].Put(self.name, value) +# class STORE_VAR(Opcode): +# def __init__(self, depth, name): +# self.name = name +# self.depth = depth + +# def eval(self, ctx, stack): +# value = stack[-1] +# ctx.scope[self.depth].Put(self.name, value) - def __repr__(self): - return 'STORE "%s"' % self.name +# def __repr__(self): +# return 'STORE_VAR "%s"' % self.name class LOAD_OBJECT(Opcode): def __init__(self, counter): @@ -342,15 +299,18 @@ # XXX class SUB(BaseBinaryOperation): - def operation(self, ctx, left, right): + @staticmethod + def operation(ctx, left, right): return sub(ctx, left, right) class ADD(BaseBinaryOperation): - def operation(self, ctx, left, right): + @staticmethod + def operation(ctx, left, right): return plus(ctx, left, right) class BITAND(BaseBinaryBitwiseOp): - def operation(self, ctx, op1, op2): + @staticmethod + def operation(ctx, op1, op2): return W_IntNumber(op1&op2) @@ -407,6 +367,60 @@ def decision(self, ctx, op1, op2): return newbool(not StrictEC(ctx, op1, op2)) + +class BaseStoreMember(Opcode): + pass + #def eval(self, ctx, ): + # XXX + +class STORE_MEMBER(Opcode): + pass + +class STORE_MEMBER_POSTINCR(Opcode): + pass + +class STORE_MEMBER_PREINCR(Opcode): + pass + +class STORE_MEMBER_SUB(Opcode): + pass + +class BaseStore(Opcode): + def __init__(self, name): + self.name = name + + def eval(self, ctx, stack): + value = self.process(ctx, self.name, stack) + ctx.assign(self.name, value) + + def __repr__(self): + return '%s "%s"' % (self.__class__.__name__, self.name) + +class STORE(BaseStore): + def process(self, ctx, name, stack): + return stack[-1] + +class BaseAssignOper(BaseStore): + def process(self, ctx, name, stack): + right = stack.pop() + left = ctx.resolve_identifier(name) + result = self.operation(ctx, left, right) + stack.append(result) + return result + +class STORE_ADD(BaseAssignOper): + operation = staticmethod(ADD.operation) + +class STORE_SUB(BaseAssignOper): + operation = staticmethod(SUB.operation) + +class STORE_POSTINCR(BaseStore): + def process(self, ctx, name, stack): + value = ctx.resolve_identifier(name) + newval = increment(ctx, value) + stack.append(newval) + return newval + class LABEL(Opcode): def __init__(self, num): self.num = num Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Tue Apr 1 04:53:13 2008 @@ -166,6 +166,7 @@ class VariableAssignment(Assignment): def __init__(self, pos, left, right, operand): + xxx # shall never land here for now self.identifier = left.identifier self.right = right self.pos = pos Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Tue Apr 1 04:53:13 2008 @@ -266,6 +266,10 @@ print(i); """, ["0","1","2","3"]) +def test_assignments(): + yield assertv, "var x = 3; x += 4; x;", 7 + yield assertv, "x = 8; x -= 3; x;", 5 + def test_object_creation(): yield assertv, """ o = new Object(); From fijal at codespeak.net Tue Apr 1 06:41:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 06:41:53 +0200 (CEST) Subject: [pypy-svn] r53225 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080401044153.A26551684D3@codespeak.net> Author: fijal Date: Tue Apr 1 06:41:51 2008 New Revision: 53225 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: implement exceptions. They're not that great, but I think better than before (catching of finally blocks works better) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Tue Apr 1 06:41:51 2008 @@ -19,7 +19,8 @@ opcode = opcodes[i] opcode = hint(opcode, deepfreeze=True) if isinstance(opcode, op): - opcode.eval(ctx, stack) + result = opcode.eval(ctx, stack) + assert result is None break if isinstance(opcode, BaseJump): i = opcode.do_jump(stack, i) @@ -549,6 +550,45 @@ def eval(self, ctx, stack): stack.append(stack[-1]) +class THROW(Opcode): + def eval(self, ctx, stack): + val = stack.pop() + raise ThrowException(val) + +class TRYCATCHBLOCK(Opcode): + def __init__(self, trycode, catchparam, catchcode, finallycode): + self.trycode = trycode + self.catchcode = catchcode + self.catchparam = catchparam + self.finallycode = finallycode + + def eval(self, ctx, stack): + try: + try: + self.trycode.run(ctx) + except ThrowException, e: + if self.catchcode is not None: + # XXX just copied, I don't know if it's right + obj = W_Object() + obj.Put(self.catchparam, e.exception) + ctx.push_object(obj) + try: + self.catchcode.run(ctx) + finally: + ctx.pop_object() + if self.finallycode is not None: + self.finallycode.run(ctx) + if not self.catchcode: + raise + except ReturnException: + # we run finally block here and re-raise the exception + if self.finallycode is not None: + self.finallycode.run(ctx) + raise + + def __repr__(self): + return "TRYCATCHBLOCK" # XXX shall we add stuff here??? + OpcodeMap = {} for name, value in locals().items(): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Tue Apr 1 06:41:51 2008 @@ -725,9 +725,10 @@ def __init__(self, pos, exp): self.pos = pos self.exp = exp - - def execute(self, ctx): - raise ThrowException(self.exp.eval(ctx).GetValue()) + + def emit(self, bytecode): + self.exp.emit(bytecode) + bytecode.emit('THROW') class Try(Statement): def __init__(self, pos, tryblock, catchparam, catchblock, finallyblock): @@ -736,30 +737,23 @@ self.catchparam = catchparam self.catchblock = catchblock self.finallyblock = finallyblock - - def execute(self, ctx): - e = None - tryresult = w_Undefined - try: - tryresult = self.tryblock.execute(ctx) - except ThrowException, excpt: - e = excpt - if self.catchblock is not None: - obj = W_Object() - obj.Put(self.catchparam.get_literal(), e.exception) - ctx.push_object(obj) - tryresult = self.catchblock.execute(ctx) - ctx.pop_object() - - if self.finallyblock is not None: - tryresult = self.finallyblock.execute(ctx) - - #if there is no catchblock reraise the exception - if (e is not None) and (self.catchblock is None): - raise e - - return tryresult - + + def emit(self, bytecode): + # a bit naive operator for now + trycode = JsCode() + self.tryblock.emit(trycode) + if self.catchblock: + catchcode = JsCode() + self.catchblock.emit(catchcode) + else: + catchcode = None + if self.finallyblock: + finallycode = JsCode() + self.finallyblock.emit(finallycode) + else: + finallycode = None + bytecode.emit('TRYCATCHBLOCK', trycode, self.catchparam.get_literal(), + catchcode, finallycode) #class Typeof(UnaryOp): # def eval(self, ctx): Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Tue Apr 1 06:41:51 2008 @@ -175,7 +175,6 @@ """, ['', '0']) def test_throw(): - py.test.skip("Not implemented") assertp("throw(3);", "uncaught exception: 3") def test_group(): @@ -189,7 +188,6 @@ yield assertp, "{3; print(5);}", '5' def test_try_catch_finally(): - py.test.skip("Not implemented") yield assertp, """ try { throw(3); From antocuni at codespeak.net Tue Apr 1 10:15:25 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 1 Apr 2008 10:15:25 +0200 (CEST) Subject: [pypy-svn] r53226 - in pypy/branch/jit-hotpath/pypy/rpython/ootypesystem: . test Message-ID: <20080401081525.8B7C616847A@codespeak.net> Author: antocuni Date: Tue Apr 1 10:15:23 2008 New Revision: 53226 Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py Log: attach the name of the method to the _bound_meth object (only for builtin types so far) Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Tue Apr 1 10:15:23 2008 @@ -1163,7 +1163,9 @@ TYPE = object.__getattribute__(self, "_TYPE") _, meth = TYPE._lookup(name) if meth is not None: - return meth._bound(TYPE, self) + res = meth._bound(TYPE, self) + res._name = name + return res return object.__getattribute__(self, name) Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py Tue Apr 1 10:15:23 2008 @@ -213,6 +213,12 @@ METH = typeOf(meth) assert METH.SELFTYPE is LIST +def test_bound_method_name(): + LIST = List(Signed) + lst = new(LIST) + meth = lst.ll_getitem_fast + assert meth._name == 'll_getitem_fast' + def test_explicit_name_clash(): C = Instance("test", ROOT, {}) From cfbolz at codespeak.net Tue Apr 1 10:51:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 1 Apr 2008 10:51:17 +0200 (CEST) Subject: [pypy-svn] r53227 - in pypy/branch/jit-merging-logic/pypy/jit/timeshifter: . test Message-ID: <20080401085117.33971168436@codespeak.net> Author: cfbolz Date: Tue Apr 1 10:51:16 2008 New Revision: 53227 Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/support.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Log: (arigo, cfbolz yesterday) Intermediate check-in breaking everything, I'd like to expriment a bit differently from there. Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py Tue Apr 1 10:51:16 2008 @@ -165,7 +165,11 @@ except rcontainer.SegfaultException: pass else: - return fielddesc.makebox(jitstate, resgv) + result = fielddesc.makebox(jitstate, resgv) + if argbox.future_usage is not None: + future_usage = argbox.future_usage.retrieve_child_usage(fielddesc) + result.future_usage = future_usage + return result return argbox.op_getfield(jitstate, fielddesc) def gensetfield(jitstate, fielddesc, destbox, valuebox): Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py Tue Apr 1 10:51:16 2008 @@ -47,12 +47,22 @@ return gv.revealconst(ootype.Object) class FutureUsage(object): - promote_timestamp = 0 + def __init__(self): + self.promote_timestamp = 0 + self.children = {} def see_promote(self, timestamp): if timestamp > self.promote_timestamp: self.promote_timestamp = timestamp + def retrieve_child_usage(self, fielddesc): + try: + return self.children[fielddesc] + except KeyError: + future_usage = FutureUsage() + self.children[fielddesc] = future_usage + return future_usage + class RedBox(object): _attrs_ = ['genvar', 'future_usage'] @@ -350,23 +360,25 @@ try: return boxmemo[self] except KeyError: + future_usage = self.retrieve_future_usage() content = self.content if not self.genvar: from pypy.jit.timeshifter import rcontainer assert isinstance(content, rcontainer.VirtualContainer) - result = self.FrozenPtrVirtual() + result = self.FrozenPtrVirtual(future_usage) boxmemo[self] = result result.fz_content = content.freeze(memo) return result elif self.genvar.is_const: - result = self.FrozenPtrConst(self.genvar) + result = self.FrozenPtrConst(future_usage, self.genvar) elif content is None: - result = self.FrozenPtrVar(self.known_nonzero) + result = self.FrozenPtrVar(future_usage, self.known_nonzero) else: # if self.content is not None, it's a PartialDataStruct from pypy.jit.timeshifter import rcontainer assert isinstance(content, rcontainer.PartialDataStruct) - result = self.FrozenPtrVarWithPartialData(known_nonzero=True) + result = self.FrozenPtrVarWithPartialData(future_usage, + known_nonzero=True) boxmemo[self] = result result.fz_partialcontent = content.partialfreeze(memo) return result @@ -473,9 +485,20 @@ return False def check_timestamp(self, box, memo): - if (box.is_constant() and - self.future_usage.promote_timestamp > memo.frozen_timestamp): - raise DontMerge + fu = self.future_usage + if fu is not None: + if (box.is_constant() and + fu.promote_timestamp > memo.frozen_timestamp): + raise DontMerge + if fu.children: + assert isinstance(box, AbstractPtrRedBox) + for fielddesc, fuchild in fu.children.items(): + frozenchild = self.maybe_get_child_box(fielddesc) + boxchild = box.maybe_get_child_box(fielddesc) + if frozenchild is not None and boxchild is not None: + assert frozenchild.future_usage is fuchild + frozenchild.check_timestamp(boxchild, memo) + # XXX use the memo here too! class FrozenConst(FrozenValue): @@ -589,7 +612,8 @@ class FrozenAbstractPtrConst(FrozenConst): - def __init__(self, gv_const): + def __init__(self, future_usage, gv_const): + FrozenConst.__init__(self, future_usage) self.gv_const = gv_const def is_constant_equal(self, box): @@ -606,15 +630,19 @@ if self.is_constant_nullptr(): memo.forget_nonzeroness[box] = None match = FrozenConst.exactmatch(self, box, outgoingvarboxes, memo) - if not memo.force_merge and not match: - from pypy.jit.timeshifter.rcontainer import VirtualContainer - if isinstance(box.content, VirtualContainer): - raise DontMerge # XXX recursive data structures? + #if not memo.force_merge and not match: + # from pypy.jit.timeshifter.rcontainer import VirtualContainer + # if isinstance(box.content, VirtualContainer): + # raise DontMerge # XXX recursive data structures? return match def unfreeze(self, incomingvarboxes, memo): return self.PtrRedBox(self.gv_const) + def maybe_get_child_box(self, fielddesc): + XXX # pfpfpfpfpf no fun at all! we make a non-frozen box and freeze it? uh how do we make the non-frozen box? + fielddesc.makebox(fielddesc.perform_getfield(rgenop:-(, self.gv_const)) # in theory + # :-( :-( :-( class FrozenPtrConst(FrozenAbstractPtrConst, LLTypeMixin): PtrRedBox = PtrRedBox @@ -625,7 +653,8 @@ class AbstractFrozenPtrVar(FrozenVar): - def __init__(self, known_nonzero): + def __init__(self, future_usage, known_nonzero): + FrozenVar.__init__(self, future_usage) self.known_nonzero = known_nonzero def exactmatch(self, box, outgoingvarboxes, memo): Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/support.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/support.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/support.py Tue Apr 1 10:51:16 2008 @@ -33,6 +33,9 @@ def constPrebuiltGlobal(value): return FakeGenConst(value) + def genconst(self, value): + return FakeGenConst(value) + class FakeBuilder(object): ops_with_no_retval = set(['setfield']) Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Tue Apr 1 10:51:16 2008 @@ -1,20 +1,17 @@ -""" [merge point including x] - promote(x) - then the frozen x has a futureusage - yes - isn't this example too easy? - I mean, in which case would we want to prevent a merge? - it's a start - no, it shows the essential bit - if x was initially a constant(5), then we don't want to merge with any other value - if x was initially a variable, then we don't want to merge with any constant at all +""" + so, we have a frozen _variable_ s + and do promote(s.x) + and try to merge it with a virtual s + it looks a bit strange but I suppose that 's.x' should also create {'x': FutureUsage()} in the FutureUsage() of s + yes, I fear so + so, we get a virtual s to merge... """ import py from pypy.rpython.lltypesystem import lltype -from pypy.jit.timeshifter import rvalue, rcontainer +from pypy.jit.timeshifter import rvalue, rcontainer, rtimeshift from pypy.jit.timeshifter.test.support import FakeJITState, FakeGenVar -from pypy.jit.timeshifter.test.support import FakeGenConst +from pypy.jit.timeshifter.test.support import FakeGenConst, FakeRGenOp from pypy.jit.timeshifter.test.support import signed_kind from pypy.jit.timeshifter.test.support import vmalloc, makebox from pypy.jit.timeshifter.test.support import getfielddesc @@ -23,7 +20,8 @@ class TestMerging: def setup_class(cls): - cls.STRUCT = lltype.GcStruct("S", ("x", lltype.Signed)) + cls.STRUCT = lltype.GcStruct("S", ("x", lltype.Signed), + hints={'immutable': True}) cls.fielddesc = getfielddesc(cls.STRUCT, "x") FORWARD = lltype.GcForwardReference() cls.NESTEDSTRUCT = lltype.GcStruct('dummy', ("foo", lltype.Signed), @@ -31,6 +29,9 @@ FORWARD.become(cls.NESTEDSTRUCT) def test_promote_const(self): + """We have a frozen constant 42 which gets a (no-op) promotion after + it is frozen. Then it should fail to merge with a live constant 43. + """ gc = FakeGenConst(42) box = rvalue.IntRedBox(gc) frozen = box.freeze(rvalue.freeze_memo()) @@ -49,6 +50,9 @@ py.test.raises(rvalue.DontMerge, frozen.exactmatch, newbox, [], memo) def test_promote_var(self): + """We have a frozen variable which gets promoted after + it is frozen. Then it should fail to merge with any live constant. + """ gv = FakeGenVar() box = rvalue.IntRedBox(gv) frozen = box.freeze(rvalue.freeze_memo()) @@ -67,6 +71,9 @@ py.test.raises(rvalue.DontMerge, frozen.exactmatch, newbox, [], memo) def test_promotebefore_freeze_const(self): + """In the merging logic, frozen boxes ignore promotions that + occurred before the freezing. + """ gc = FakeGenConst(42) box = rvalue.IntRedBox(gc) box.freeze(rvalue.freeze_memo()) @@ -85,3 +92,40 @@ gc2 = FakeGenConst(43) newbox = rvalue.IntRedBox(gc2) assert not frozen.exactmatch(newbox, [], memo) + + def test_promote_field_of_constant_immutable(self): + """We freeze s then promote s.x. This should prevent a merge where + there is an incoming live s2 for which we already know the value of + s2.x, and for which the merge would loose that information. + """ + prebuilt_s = lltype.malloc(self.STRUCT) + prebuilt_s.x = 42 + + gc = FakeGenConst(prebuilt_s) + box = rvalue.PtrRedBox(gc) + frozen = box.freeze(rvalue.freeze_memo()) + assert box.future_usage is not None # attached by freeze + frozen_timestamp = 0 + + jitstate = FakeJITState() + + x_box = rtimeshift.gengetfield(jitstate, False, self.fielddesc, box) + assert x_box.genvar.revealconst(lltype.Signed) == 42 + assert x_box.future_usage is not None # attached by gengetfield() + x_box.future_usage.see_promote(timestamp=1) + + memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + assert frozen.exactmatch(box, [], memo) + + prebuilt_s2 = lltype.malloc(self.STRUCT) + prebuilt_s2.x = 42 + box2 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s2)) + memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + assert not frozen.exactmatch(box2, [], memo) + # ^^^no DontMerge because box2.x is equal, so we don't loose its value + + prebuilt_s3 = lltype.malloc(self.STRUCT) + prebuilt_s3.x = 43 + box3 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s3)) + memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + py.test.raises(rvalue.DontMerge, frozen.exactmatch, box3, [], memo) From arigo at codespeak.net Tue Apr 1 11:01:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Apr 2008 11:01:33 +0200 (CEST) Subject: [pypy-svn] r53228 - in pypy/branch/jit-merging-logic/pypy/jit/timeshifter: . test Message-ID: <20080401090133.027A61684D9@codespeak.net> Author: arigo Date: Tue Apr 1 11:01:32 2008 New Revision: 53228 Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Log: Trying a simpler approach: remembering the most recent frozen copy of a box and attaching a flag to the frozen copy when the box gets promoted. Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py Tue Apr 1 11:01:32 2008 @@ -14,9 +14,8 @@ def freeze_memo(): return Memo() -def exactmatch_memo(frozen_timestamp, force_merge=False): +def exactmatch_memo(force_merge=False): memo = Memo() - memo.frozen_timestamp = frozen_timestamp memo.partialdatamatch = {} memo.forget_nonzeroness = {} memo.force_merge=force_merge @@ -46,27 +45,10 @@ def _revealconst(self, gv): return gv.revealconst(ootype.Object) -class FutureUsage(object): - def __init__(self): - self.promote_timestamp = 0 - self.children = {} - - def see_promote(self, timestamp): - if timestamp > self.promote_timestamp: - self.promote_timestamp = timestamp - - def retrieve_child_usage(self, fielddesc): - try: - return self.children[fielddesc] - except KeyError: - future_usage = FutureUsage() - self.children[fielddesc] = future_usage - return future_usage - class RedBox(object): - _attrs_ = ['genvar', 'future_usage'] - future_usage = None + _attrs_ = ['genvar', 'most_recent_frozen'] + most_recent_frozen = None def __init__(self, genvar=None): self.genvar = genvar # None or a genvar @@ -115,10 +97,10 @@ memo = memo.boxes return memo.setdefault(self, self) - def retrieve_future_usage(self): - if self.future_usage is None: - self.future_usage = FutureUsage() - return self.future_usage + def see_promote(self): + if self.most_recent_frozen is not None: + self.most_recent_frozen.will_be_promoted = True + self.most_recent_frozen = None def ll_redboxcls(TYPE): @@ -194,11 +176,13 @@ try: return memo[self] except KeyError: - future_usage = self.retrieve_future_usage() - if self.is_constant(): - result = FrozenIntConst(future_usage, self.genvar) - else: - result = FrozenIntVar(future_usage) + result = self.most_recent_frozen + if result is None: + if self.is_constant(): + result = FrozenIntConst(self.genvar) + else: + result = FrozenIntVar() + self.most_recent_frozen = result memo[self] = result return result @@ -475,8 +459,7 @@ class FrozenValue(object): """An abstract value frozen in a saved state. """ - def __init__(self, future_usage): - self.future_usage = future_usage + will_be_promoted = False def is_constant_equal(self, box): return False @@ -484,22 +467,6 @@ def is_constant_nullptr(self): return False - def check_timestamp(self, box, memo): - fu = self.future_usage - if fu is not None: - if (box.is_constant() and - fu.promote_timestamp > memo.frozen_timestamp): - raise DontMerge - if fu.children: - assert isinstance(box, AbstractPtrRedBox) - for fielddesc, fuchild in fu.children.items(): - frozenchild = self.maybe_get_child_box(fielddesc) - boxchild = box.maybe_get_child_box(fielddesc) - if frozenchild is not None and boxchild is not None: - assert frozenchild.future_usage is fuchild - frozenchild.check_timestamp(boxchild, memo) - # XXX use the memo here too! - class FrozenConst(FrozenValue): @@ -507,7 +474,8 @@ if self.is_constant_equal(box): return True else: - self.check_timestamp(box, memo) + if self.will_be_promoted and box.is_constant(): + raise DontMerge outgoingvarboxes.append(box) return False @@ -515,7 +483,8 @@ class FrozenVar(FrozenValue): def exactmatch(self, box, outgoingvarboxes, memo): - self.check_timestamp(box, memo) + if self.will_be_promoted and box.is_constant(): + raise DontMerge memo = memo.boxes if self not in memo: memo[self] = box @@ -530,8 +499,7 @@ class FrozenIntConst(FrozenConst): - def __init__(self, future_usage, gv_const): - FrozenConst.__init__(self, future_usage) + def __init__(self, gv_const): self.gv_const = gv_const def is_constant_equal(self, box): @@ -639,10 +607,6 @@ def unfreeze(self, incomingvarboxes, memo): return self.PtrRedBox(self.gv_const) - def maybe_get_child_box(self, fielddesc): - XXX # pfpfpfpfpf no fun at all! we make a non-frozen box and freeze it? uh how do we make the non-frozen box? - fielddesc.makebox(fielddesc.perform_getfield(rgenop:-(, self.gv_const)) # in theory - # :-( :-( :-( class FrozenPtrConst(FrozenAbstractPtrConst, LLTypeMixin): PtrRedBox = PtrRedBox Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Tue Apr 1 11:01:32 2008 @@ -35,20 +35,24 @@ gc = FakeGenConst(42) box = rvalue.IntRedBox(gc) frozen = box.freeze(rvalue.freeze_memo()) - frozen_timestamp = 0 - assert box.future_usage is not None # attached by freeze() - box.future_usage.see_promote(timestamp=1) + assert box.most_recent_frozen is not None # attached by freeze() + box.see_promote() - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() gv = FakeGenVar() newbox = rvalue.IntRedBox(gv) assert not frozen.exactmatch(newbox, [], memo) - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() gc2 = FakeGenConst(43) newbox = rvalue.IntRedBox(gc2) py.test.raises(rvalue.DontMerge, frozen.exactmatch, newbox, [], memo) + memo = rvalue.exactmatch_memo() + gc3 = FakeGenConst(42) + newbox = rvalue.IntRedBox(gc3) + assert frozen.exactmatch(newbox, [], memo) + def test_promote_var(self): """We have a frozen variable which gets promoted after it is frozen. Then it should fail to merge with any live constant. @@ -56,16 +60,15 @@ gv = FakeGenVar() box = rvalue.IntRedBox(gv) frozen = box.freeze(rvalue.freeze_memo()) - frozen_timestamp = 0 - assert box.future_usage is not None # attached by freeze() - box.future_usage.see_promote(timestamp=1) + assert box.most_recent_frozen is not None # attached by freeze() + box.see_promote() - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() gv2 = FakeGenVar() newbox = rvalue.IntRedBox(gv2) assert frozen.exactmatch(newbox, [], memo) - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() gc = FakeGenConst(43) newbox = rvalue.IntRedBox(gc) py.test.raises(rvalue.DontMerge, frozen.exactmatch, newbox, [], memo) @@ -77,18 +80,17 @@ gc = FakeGenConst(42) box = rvalue.IntRedBox(gc) box.freeze(rvalue.freeze_memo()) - assert box.future_usage is not None # attached by freeze() - box.future_usage.see_promote(timestamp=1) + assert box.most_recent_frozen is not None # attached by freeze() + box.see_promote() - frozen_timestamp = 2 frozen = box.freeze(rvalue.freeze_memo()) - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() gv = FakeGenVar() newbox = rvalue.IntRedBox(gv) assert not frozen.exactmatch(newbox, [], memo) - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() gc2 = FakeGenConst(43) newbox = rvalue.IntRedBox(gc2) assert not frozen.exactmatch(newbox, [], memo) From arigo at codespeak.net Tue Apr 1 11:16:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Apr 2008 11:16:04 +0200 (CEST) Subject: [pypy-svn] r53229 - in pypy/branch/jit-merging-logic/pypy/jit/timeshifter: . test Message-ID: <20080401091604.C072D168437@codespeak.net> Author: arigo Date: Tue Apr 1 11:16:04 2008 New Revision: 53229 Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Log: Update the last test too (still failing). Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py Tue Apr 1 11:16:04 2008 @@ -218,6 +218,7 @@ try: return memo[self] except KeyError: + xxx # use self.most_recent_frozen if self.is_constant(): result = FrozenBoolConst(self.genvar) else: @@ -241,6 +242,7 @@ try: return memo[self] except KeyError: + xxx # use self.most_recent_frozen if self.is_constant(): result = FrozenDoubleConst(self.genvar) else: Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Tue Apr 1 11:16:04 2008 @@ -106,28 +106,27 @@ gc = FakeGenConst(prebuilt_s) box = rvalue.PtrRedBox(gc) frozen = box.freeze(rvalue.freeze_memo()) - assert box.future_usage is not None # attached by freeze - frozen_timestamp = 0 + assert box.most_recent_frozen is not None # attached by freeze jitstate = FakeJITState() x_box = rtimeshift.gengetfield(jitstate, False, self.fielddesc, box) assert x_box.genvar.revealconst(lltype.Signed) == 42 assert x_box.future_usage is not None # attached by gengetfield() - x_box.future_usage.see_promote(timestamp=1) + x_box.see_promote() - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() assert frozen.exactmatch(box, [], memo) prebuilt_s2 = lltype.malloc(self.STRUCT) prebuilt_s2.x = 42 box2 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s2)) - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() assert not frozen.exactmatch(box2, [], memo) # ^^^no DontMerge because box2.x is equal, so we don't loose its value prebuilt_s3 = lltype.malloc(self.STRUCT) prebuilt_s3.x = 43 box3 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s3)) - memo = rvalue.exactmatch_memo(frozen_timestamp=frozen_timestamp) + memo = rvalue.exactmatch_memo() py.test.raises(rvalue.DontMerge, frozen.exactmatch, box3, [], memo) From cfbolz at codespeak.net Tue Apr 1 14:04:28 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 1 Apr 2008 14:04:28 +0200 (CEST) Subject: [pypy-svn] r53230 - in pypy/branch/jit-merging-logic/pypy/jit/timeshifter: . test Message-ID: <20080401120428.E0E5D168422@codespeak.net> Author: cfbolz Date: Tue Apr 1 14:04:26 2008 New Revision: 53230 Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py Log: (cfbolz, arigo): use the new approach of remembering the last frozen box on each box to pass the new merging tests Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py Tue Apr 1 14:04:26 2008 @@ -23,7 +23,8 @@ _attrs_ = [] def op_getfield(self, jitstate, fielddesc): - raise NotImplementedError + rgenop = jitstate.curbuilder.rgenop + return self.getfield_dont_generate_code(rgenop, fielddesc) def op_setfield(self, jitstate, fielddesc, valuebox): raise NotImplementedError @@ -31,6 +32,9 @@ def op_getsubstruct(self, jitstate, fielddesc): raise NotImplementedError + def getfield_dont_generate_code(self, rgenop, fielddesc): + raise NotImplementedError + class VirtualContainer(AbstractContainer): _attrs_ = ('ownbox',) @@ -639,6 +643,9 @@ if self.virtualizable: self.structdesc = StructTypeDesc(RGenOp, T) self.redboxcls = rvalue.ll_redboxcls(RESTYPE) + # fish for the FrozenConst subclass + dummybox = self.redboxcls(self.gv_default) + self.frozenconstcls = dummybox.FrozenConstCls self.immutable = deref(PTRTYPE)._hints.get('immutable', False) @@ -909,15 +916,15 @@ content_boxes[i] = content_boxes[i].replace(memo) self.ownbox = self.ownbox.replace(memo) - def op_getfield(self, jitstate, fielddesc): - return self.content_boxes[fielddesc.fieldindex] - def op_setfield(self, jitstate, fielddesc, valuebox): self.content_boxes[fielddesc.fieldindex] = valuebox def op_getsubstruct(self, jitstate, fielddesc): return self.ownbox + def getfield_dont_generate_code(self, rgenop, fielddesc): + return self.content_boxes[fielddesc.fieldindex] + def make_rti(self, jitstate, memo): try: return memo.containers[self] @@ -1284,6 +1291,9 @@ fielddesc.generate_set(jitstate, gv_ptr, valuebox.getgenvar(jitstate)) + def getfield_dont_generate_code(self, rgenop, fielddesc): + xxx + def op_ptreq(self, jitstate, otherbox, reverse): if self is otherbox.content: answer = True @@ -1346,7 +1356,7 @@ def __init__(self): self.data = [] - def op_getfield(self, jitstate, fielddesc): + def getfield_dont_generate_code(self, rgenop, fielddesc): searchindex = fielddesc.fieldindex for index, box in self.data: if index == searchindex: Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py Tue Apr 1 14:04:26 2008 @@ -166,9 +166,10 @@ pass else: result = fielddesc.makebox(jitstate, resgv) - if argbox.future_usage is not None: - future_usage = argbox.future_usage.retrieve_child_usage(fielddesc) - result.future_usage = future_usage + fz = argbox.most_recent_frozen + if fz is not None: + newfz = fz.get_const_child(fielddesc, resgv) + result.most_recent_frozen = newfz return result return argbox.op_getfield(jitstate, fielddesc) Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py Tue Apr 1 14:04:26 2008 @@ -14,8 +14,9 @@ def freeze_memo(): return Memo() -def exactmatch_memo(force_merge=False): +def exactmatch_memo(rgenop, force_merge=False): memo = Memo() + memo.rgenop = rgenop memo.partialdatamatch = {} memo.forget_nonzeroness = {} memo.force_merge=force_merge @@ -346,30 +347,41 @@ try: return boxmemo[self] except KeyError: - future_usage = self.retrieve_future_usage() content = self.content - if not self.genvar: - from pypy.jit.timeshifter import rcontainer - assert isinstance(content, rcontainer.VirtualContainer) - result = self.FrozenPtrVirtual(future_usage) + if content is None: + result = self.most_recent_frozen + if result is None: + if self.genvar.is_const: + result = self.FrozenPtrConst(self.genvar) + elif content is None: + result = self.FrozenPtrVar(self.known_nonzero) + self.most_recent_frozen = result + else: + # sanity-check the most_recent_frozen object + if self.genvar.is_const: + assert isinstance(result, self.FrozenPtrConst) + else: + assert isinstance(result, self.FrozenPtrVar) boxmemo[self] = result - result.fz_content = content.freeze(memo) - return result - elif self.genvar.is_const: - result = self.FrozenPtrConst(future_usage, self.genvar) - elif content is None: - result = self.FrozenPtrVar(future_usage, self.known_nonzero) else: - # if self.content is not None, it's a PartialDataStruct - from pypy.jit.timeshifter import rcontainer - assert isinstance(content, rcontainer.PartialDataStruct) - result = self.FrozenPtrVarWithPartialData(future_usage, - known_nonzero=True) - boxmemo[self] = result - result.fz_partialcontent = content.partialfreeze(memo) - return result - result.fz_access_info = self.access_info.copy() - boxmemo[self] = result + self.most_recent_frozen = None # for now + if not self.genvar: + from pypy.jit.timeshifter import rcontainer + assert isinstance(content, rcontainer.VirtualContainer) + result = self.FrozenPtrVirtual() + # store the result in the memo before content.freeze(), + # for recursive data structures + boxmemo[self] = result + result.fz_content = content.freeze(memo) + else: + # if self.content is not None, it's a PartialDataStruct + from pypy.jit.timeshifter import rcontainer + assert isinstance(content, rcontainer.PartialDataStruct) + result = self.FrozenPtrVarWithPartialData(known_nonzero=True) + # store the result in the memo before content.freeze(), + # for recursive data structures + boxmemo[self] = result + result.fz_partialcontent = content.partialfreeze(memo) return result def getgenvar(self, jitstate): @@ -431,6 +443,19 @@ assert self.content is not None self.content.op_setfield(jitstate, fielddesc, valuebox) + def getfield_dont_generate_code(self, rgenop, fielddesc): + if self.content is not None: + return self.content.getfield_dont_generate_code(rgenop, fielddesc) + elif self.genvar.is_const: + # this raises if something's wrong, never returns None right + try: + gv_result = fielddesc.perform_getfield(rgenop, self.genvar) + except rcontainer.SegfaultException: + return None + return fielddesc.redboxcls(gv_result) + else: + return None + def remember_field(self, fielddesc, box): if self.genvar.is_const: return # no point in remembering field then @@ -481,6 +506,11 @@ outgoingvarboxes.append(box) return False + def check_future_promotions(self, box, memo): + if (self.will_be_promoted and box.is_constant() + and not self.is_constant_equal(box)): + raise DontMerge + class FrozenVar(FrozenValue): @@ -513,6 +543,8 @@ # XXX could return directly the original IntRedBox return IntRedBox(self.gv_const) +IntRedBox.FrozenConstCls = FrozenIntConst + class FrozenIntVar(FrozenVar): @@ -540,6 +572,8 @@ def unfreeze(self, incomingvarboxes, memo): return BoolRedBox(self.gv_const) +BoolRedBox.FrozenConstCls = FrozenBoolConst + class FrozenBoolVar(FrozenVar): @@ -566,6 +600,8 @@ def unfreeze(self, incomingvarboxes, memo): return DoubleRedBox(self.gv_const) +DoubleRedBox.FrozenConstCls = FrozenDoubleConst + class FrozenDoubleVar(FrozenVar): @@ -582,8 +618,8 @@ class FrozenAbstractPtrConst(FrozenConst): - def __init__(self, future_usage, gv_const): - FrozenConst.__init__(self, future_usage) + def __init__(self, gv_const): + FrozenConst.__init__(self) self.gv_const = gv_const def is_constant_equal(self, box): @@ -600,6 +636,8 @@ if self.is_constant_nullptr(): memo.forget_nonzeroness[box] = None match = FrozenConst.exactmatch(self, box, outgoingvarboxes, memo) + if not match: + self.check_future_promotions(box, memo) #if not memo.force_merge and not match: # from pypy.jit.timeshifter.rcontainer import VirtualContainer # if isinstance(box.content, VirtualContainer): @@ -609,18 +647,46 @@ def unfreeze(self, incomingvarboxes, memo): return self.PtrRedBox(self.gv_const) + const_children = None + + def get_const_child(self, fielddesc, gv_value): + # constant children of a constant immutable FrozenPtrConst + # are only used to track future promotions; they have no + # other effect on exactmatch(). + if self.const_children is None: + self.const_children = {} + else: + try: + return self.const_children[fielddesc] + except KeyError: + pass + newfz = fielddesc.frozenconstcls(gv_value) + self.const_children[fielddesc] = newfz + return newfz + + def check_future_promotions(self, box, memo): + FrozenConst.check_future_promotions(self, box, memo) + if self.const_children is not None: + for fielddesc, fz_child in self.const_children.items(): + box_child = box.getfield_dont_generate_code(memo.rgenop, + fielddesc) + if box_child is not None: + fz_child.check_future_promotions(box_child, memo) + class FrozenPtrConst(FrozenAbstractPtrConst, LLTypeMixin): PtrRedBox = PtrRedBox +PtrRedBox.FrozenConstCls = FrozenPtrConst class FrozenInstanceConst(FrozenAbstractPtrConst, OOTypeMixin): PtrRedBox = InstanceRedBox +InstanceRedBox.FrozenConstCls = FrozenInstanceConst class AbstractFrozenPtrVar(FrozenVar): - def __init__(self, future_usage, known_nonzero): - FrozenVar.__init__(self, future_usage) + def __init__(self, known_nonzero): + FrozenVar.__init__(self) self.known_nonzero = known_nonzero def exactmatch(self, box, outgoingvarboxes, memo): Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Tue Apr 1 14:04:26 2008 @@ -32,23 +32,25 @@ """We have a frozen constant 42 which gets a (no-op) promotion after it is frozen. Then it should fail to merge with a live constant 43. """ + rgenop = FakeRGenOp() + gc = FakeGenConst(42) box = rvalue.IntRedBox(gc) frozen = box.freeze(rvalue.freeze_memo()) assert box.most_recent_frozen is not None # attached by freeze() box.see_promote() - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gv = FakeGenVar() newbox = rvalue.IntRedBox(gv) assert not frozen.exactmatch(newbox, [], memo) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gc2 = FakeGenConst(43) newbox = rvalue.IntRedBox(gc2) py.test.raises(rvalue.DontMerge, frozen.exactmatch, newbox, [], memo) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gc3 = FakeGenConst(42) newbox = rvalue.IntRedBox(gc3) assert frozen.exactmatch(newbox, [], memo) @@ -57,18 +59,20 @@ """We have a frozen variable which gets promoted after it is frozen. Then it should fail to merge with any live constant. """ + rgenop = FakeRGenOp() + gv = FakeGenVar() box = rvalue.IntRedBox(gv) frozen = box.freeze(rvalue.freeze_memo()) assert box.most_recent_frozen is not None # attached by freeze() box.see_promote() - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gv2 = FakeGenVar() newbox = rvalue.IntRedBox(gv2) assert frozen.exactmatch(newbox, [], memo) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gc = FakeGenConst(43) newbox = rvalue.IntRedBox(gc) py.test.raises(rvalue.DontMerge, frozen.exactmatch, newbox, [], memo) @@ -77,6 +81,8 @@ """In the merging logic, frozen boxes ignore promotions that occurred before the freezing. """ + rgenop = FakeRGenOp() + gc = FakeGenConst(42) box = rvalue.IntRedBox(gc) box.freeze(rvalue.freeze_memo()) @@ -85,12 +91,12 @@ frozen = box.freeze(rvalue.freeze_memo()) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gv = FakeGenVar() newbox = rvalue.IntRedBox(gv) assert not frozen.exactmatch(newbox, [], memo) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) gc2 = FakeGenConst(43) newbox = rvalue.IntRedBox(gc2) assert not frozen.exactmatch(newbox, [], memo) @@ -100,6 +106,8 @@ there is an incoming live s2 for which we already know the value of s2.x, and for which the merge would loose that information. """ + rgenop = FakeRGenOp() + prebuilt_s = lltype.malloc(self.STRUCT) prebuilt_s.x = 42 @@ -112,21 +120,21 @@ x_box = rtimeshift.gengetfield(jitstate, False, self.fielddesc, box) assert x_box.genvar.revealconst(lltype.Signed) == 42 - assert x_box.future_usage is not None # attached by gengetfield() + assert x_box.most_recent_frozen is not None # attached by gengetfield() x_box.see_promote() - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) assert frozen.exactmatch(box, [], memo) prebuilt_s2 = lltype.malloc(self.STRUCT) prebuilt_s2.x = 42 box2 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s2)) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) assert not frozen.exactmatch(box2, [], memo) # ^^^no DontMerge because box2.x is equal, so we don't loose its value prebuilt_s3 = lltype.malloc(self.STRUCT) prebuilt_s3.x = 43 box3 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s3)) - memo = rvalue.exactmatch_memo() + memo = rvalue.exactmatch_memo(rgenop) py.test.raises(rvalue.DontMerge, frozen.exactmatch, box3, [], memo) Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py Tue Apr 1 14:04:26 2008 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.timeshifter import rvalue, rcontainer from pypy.jit.timeshifter.test.support import FakeJITState, FakeGenVar -from pypy.jit.timeshifter.test.support import FakeGenConst +from pypy.jit.timeshifter.test.support import FakeGenConst, FakeRGenOp from pypy.jit.timeshifter.test.support import signed_kind from pypy.jit.timeshifter.test.support import vmalloc, makebox from pypy.jit.timeshifter.test.support import getfielddesc @@ -42,9 +42,10 @@ # of 'box' that correspond to FrozenVar placeholders in frozenbox. # Otherwise, it is the list of subboxes of 'box' that should be # generalized to become variables. + rgenop = FakeRGenOp() outgoingvarboxes = [] res = frozenbox.exactmatch(box, outgoingvarboxes, - rvalue.exactmatch_memo()) + rvalue.exactmatch_memo(rgenop)) assert outgoingvarboxes == expected_outgoing return res From cfbolz at codespeak.net Tue Apr 1 15:24:01 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 1 Apr 2008 15:24:01 +0200 (CEST) Subject: [pypy-svn] r53231 - in pypy/branch/jit-merging-logic/pypy/jit/timeshifter: . test Message-ID: <20080401132401.9E4F5168450@codespeak.net> Author: cfbolz Date: Tue Apr 1 15:24:00 2008 New Revision: 53231 Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py Log: (cfbolz, arigo) One more test passing. Trying to refactor along the way. Kill the access_info stuff again Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rcontainer.py Tue Apr 1 15:24:00 2008 @@ -643,9 +643,9 @@ if self.virtualizable: self.structdesc = StructTypeDesc(RGenOp, T) self.redboxcls = rvalue.ll_redboxcls(RESTYPE) - # fish for the FrozenConst subclass + # fish for the getfrozen() static method dummybox = self.redboxcls(self.gv_default) - self.frozenconstcls = dummybox.FrozenConstCls + self.getfrozen = dummybox.getfrozen self.immutable = deref(PTRTYPE)._hints.get('immutable', False) Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rtimeshift.py Tue Apr 1 15:24:00 2008 @@ -168,7 +168,7 @@ result = fielddesc.makebox(jitstate, resgv) fz = argbox.most_recent_frozen if fz is not None: - newfz = fz.get_const_child(fielddesc, resgv) + newfz = fz.get_ghost_child(fielddesc, resgv) result.most_recent_frozen = newfz return result return argbox.op_getfield(jitstate, fielddesc) Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/rvalue.py Tue Apr 1 15:24:00 2008 @@ -64,8 +64,7 @@ return bool(self.genvar) and self.genvar.is_const def getkind(self): - if self.genvar is None: - return None + assert self.genvar is not None return self.genvar.getkind() def getgenvar(self, jitstate): @@ -84,6 +83,25 @@ incoming.append(self) memo[self] = None + def freeze(self, memo): + memo = memo.boxes + try: + return memo[self] + except KeyError: + assert self.genvar is not None + result = self.most_recent_frozen + if result is None: + result = self.getfrozen(self.genvar) + self.most_recent_frozen = result + else: + # sanity-check the most_recent_frozen object + if self.genvar.is_const: + assert isinstance(result, FrozenConst) + else: + assert isinstance(result, FrozenVar) + memo[self] = result + return result + def forcevar(self, jitstate, memo, forget_nonzeroness): if self.is_constant(): # cannot mutate constant boxes in-place @@ -172,20 +190,13 @@ result = memo[self] = IntRedBox(self.genvar) return result - def freeze(self, memo): - memo = memo.boxes - try: - return memo[self] - except KeyError: - result = self.most_recent_frozen - if result is None: - if self.is_constant(): - result = FrozenIntConst(self.genvar) - else: - result = FrozenIntVar() - self.most_recent_frozen = result - memo[self] = result - return result + @staticmethod + def getfrozen(gv_value): + if gv_value.is_const: + return FrozenIntConst(gv_value) + else: + return FrozenIntVar() + class BoolRedBox(RedBox): # XXX make true and false singletons? @@ -214,18 +225,13 @@ result.iftrue = [effect.copy(memo) for effect in self.iftrue] return result - def freeze(self, memo): - memo = memo.boxes - try: - return memo[self] - except KeyError: - xxx # use self.most_recent_frozen - if self.is_constant(): - result = FrozenBoolConst(self.genvar) - else: - result = FrozenBoolVar() - memo[self] = result - return result + @staticmethod + def getfrozen(gv_value): + if gv_value.is_const: + return FrozenBoolConst(gv_value) + else: + return FrozenBoolVar() + class DoubleRedBox(RedBox): "A red box that contains a constant double-precision floating point value." @@ -238,34 +244,12 @@ result = memo[self] = DoubleRedBox(self.genvar) return result - def freeze(self, memo): - memo = memo.boxes - try: - return memo[self] - except KeyError: - xxx # use self.most_recent_frozen - if self.is_constant(): - result = FrozenDoubleConst(self.genvar) - else: - result = FrozenDoubleVar() - memo[self] = result - return result - - -class AccessInfo(object): - def __init__(self): - self.read_fields = 0 - self.write_fields = 0 - # XXX what else is needed? - - def __repr__(self): - return "" % ( - self.read_fields, self.write_fields) - - def copy(self): - result = AccessInfo() - result.read_fields = self.read_fields - result.write_fields = self.write_fields + @staticmethod + def getfrozen(gv_value): + if gv_value.is_const: + return FrozenDoubleConst(gv_value) + else: + return FrozenDoubleVar() class AbstractPtrRedBox(RedBox): @@ -280,7 +264,6 @@ if genvar is not None and genvar.is_const: known_nonzero = bool(self._revealconst(genvar)) self.known_nonzero = known_nonzero - self.access_info = AccessInfo() def setgenvar(self, newgenvar): RedBox.setgenvar(self, newgenvar) @@ -325,8 +308,6 @@ boxmemo[self] = result if self.content: result.content = self.content.copy(memo) - # XXX is this correct? - result.access_info = self.access_info assert isinstance(result, AbstractPtrRedBox) return result @@ -349,11 +330,12 @@ except KeyError: content = self.content if content is None: + assert self.genvar is not None result = self.most_recent_frozen if result is None: if self.genvar.is_const: result = self.FrozenPtrConst(self.genvar) - elif content is None: + else: result = self.FrozenPtrVar(self.known_nonzero) self.most_recent_frozen = result else: @@ -362,26 +344,25 @@ assert isinstance(result, self.FrozenPtrConst) else: assert isinstance(result, self.FrozenPtrVar) + return result + self.most_recent_frozen = None # for now + if not self.genvar: + from pypy.jit.timeshifter import rcontainer + assert isinstance(content, rcontainer.VirtualContainer) + result = self.FrozenPtrVirtual() + # store the result in the memo before content.freeze(), + # for recursive data structures boxmemo[self] = result + result.fz_content = content.freeze(memo) else: - self.most_recent_frozen = None # for now - if not self.genvar: - from pypy.jit.timeshifter import rcontainer - assert isinstance(content, rcontainer.VirtualContainer) - result = self.FrozenPtrVirtual() - # store the result in the memo before content.freeze(), - # for recursive data structures - boxmemo[self] = result - result.fz_content = content.freeze(memo) - else: - # if self.content is not None, it's a PartialDataStruct - from pypy.jit.timeshifter import rcontainer - assert isinstance(content, rcontainer.PartialDataStruct) - result = self.FrozenPtrVarWithPartialData(known_nonzero=True) - # store the result in the memo before content.freeze(), - # for recursive data structures - boxmemo[self] = result - result.fz_partialcontent = content.partialfreeze(memo) + # if self.content is not None, it's a PartialDataStruct + from pypy.jit.timeshifter import rcontainer + assert isinstance(content, rcontainer.PartialDataStruct) + result = self.FrozenPtrVarWithPartialData(known_nonzero=True) + # store the result in the memo before content.freeze(), + # for recursive data structures + boxmemo[self] = result + result.fz_partialcontent = content.partialfreeze(memo) return result def getgenvar(self, jitstate): @@ -420,7 +401,6 @@ self.content.enter_block(incoming, memo) def op_getfield(self, jitstate, fielddesc): - self.access_info.read_fields += 1 self.learn_nonzeroness(jitstate, True) if self.content is not None: box = self.content.op_getfield(jitstate, fielddesc) @@ -430,10 +410,13 @@ box = fielddesc.generate_get(jitstate, gv_ptr) if fielddesc.immutable: self.remember_field(fielddesc, box) + fz = self.most_recent_frozen + if fz is not None: + newfz = fz.get_ghost_child(fielddesc, box.genvar) + box.most_recent_frozen = newfz return box def op_setfield(self, jitstate, fielddesc, valuebox): - self.access_info.write_fields += 1 self.learn_nonzeroness(jitstate, True) gv_ptr = self.genvar if gv_ptr: @@ -476,9 +459,22 @@ assert self.content is not None return self.content.op_getsubstruct(jitstate, fielddesc) + @staticmethod + def getfrozen(gv_value): + if gv_value.is_const: + return FrozenPtrConst(gv_value) + else: + return FrozenPtrVar(known_nonzero=False) + class InstanceRedBox(AbstractPtrRedBox, OOTypeMixin): - pass + + @staticmethod + def getfrozen(gv_value): + if gv_value.is_const: + return FrozenInstanceConst(gv_value) + else: + return FrozenInstanceVar() # ____________________________________________________________ @@ -486,6 +482,7 @@ class FrozenValue(object): """An abstract value frozen in a saved state. """ + _attrs_ = ['will_be_promoted'] will_be_promoted = False def is_constant_equal(self, box): @@ -494,6 +491,11 @@ def is_constant_nullptr(self): return False + def check_future_promotions(self, box, memo): + if (self.will_be_promoted and box.is_constant() + and not self.is_constant_equal(box)): + raise DontMerge + class FrozenConst(FrozenValue): @@ -506,11 +508,6 @@ outgoingvarboxes.append(box) return False - def check_future_promotions(self, box, memo): - if (self.will_be_promoted and box.is_constant() - and not self.is_constant_equal(box)): - raise DontMerge - class FrozenVar(FrozenValue): @@ -543,8 +540,6 @@ # XXX could return directly the original IntRedBox return IntRedBox(self.gv_const) -IntRedBox.FrozenConstCls = FrozenIntConst - class FrozenIntVar(FrozenVar): @@ -572,8 +567,6 @@ def unfreeze(self, incomingvarboxes, memo): return BoolRedBox(self.gv_const) -BoolRedBox.FrozenConstCls = FrozenBoolConst - class FrozenBoolVar(FrozenVar): @@ -600,8 +593,6 @@ def unfreeze(self, incomingvarboxes, memo): return DoubleRedBox(self.gv_const) -DoubleRedBox.FrozenConstCls = FrozenDoubleConst - class FrozenDoubleVar(FrozenVar): @@ -616,7 +607,36 @@ return memo[self] -class FrozenAbstractPtrConst(FrozenConst): +class FrozenPtrMixin(object): + _mixin_ = True + ghost_children = None + + def get_ghost_child(self, fielddesc, gv_value): + # ghost children of a constant immutable FrozenPtrConst + # are only used to track future promotions; they have no + # other effect on exactmatch(). + if self.ghost_children is None: + self.ghost_children = {} + else: + try: + return self.ghost_children[fielddesc] + except KeyError: + pass + newfz = fielddesc.getfrozen(gv_value) + self.ghost_children[fielddesc] = newfz + return newfz + + def check_future_promotions(self, box, memo): + FrozenValue.check_future_promotions(self, box, memo) + if self.ghost_children is not None: + for fielddesc, fz_child in self.ghost_children.items(): + box_child = box.getfield_dont_generate_code(memo.rgenop, + fielddesc) + if box_child is not None: + fz_child.check_future_promotions(box_child, memo) + + +class FrozenAbstractPtrConst(FrozenPtrMixin, FrozenConst): def __init__(self, gv_const): FrozenConst.__init__(self) @@ -647,43 +667,15 @@ def unfreeze(self, incomingvarboxes, memo): return self.PtrRedBox(self.gv_const) - const_children = None - - def get_const_child(self, fielddesc, gv_value): - # constant children of a constant immutable FrozenPtrConst - # are only used to track future promotions; they have no - # other effect on exactmatch(). - if self.const_children is None: - self.const_children = {} - else: - try: - return self.const_children[fielddesc] - except KeyError: - pass - newfz = fielddesc.frozenconstcls(gv_value) - self.const_children[fielddesc] = newfz - return newfz - - def check_future_promotions(self, box, memo): - FrozenConst.check_future_promotions(self, box, memo) - if self.const_children is not None: - for fielddesc, fz_child in self.const_children.items(): - box_child = box.getfield_dont_generate_code(memo.rgenop, - fielddesc) - if box_child is not None: - fz_child.check_future_promotions(box_child, memo) - class FrozenPtrConst(FrozenAbstractPtrConst, LLTypeMixin): PtrRedBox = PtrRedBox -PtrRedBox.FrozenConstCls = FrozenPtrConst class FrozenInstanceConst(FrozenAbstractPtrConst, OOTypeMixin): PtrRedBox = InstanceRedBox -InstanceRedBox.FrozenConstCls = FrozenInstanceConst -class AbstractFrozenPtrVar(FrozenVar): +class AbstractFrozenPtrVar(FrozenPtrMixin, FrozenVar): def __init__(self, known_nonzero): FrozenVar.__init__(self) @@ -698,13 +690,7 @@ match = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo) if self.known_nonzero and not box.known_nonzero: match = False - if not memo.force_merge: - if isinstance(box.content, VirtualContainer): - # heuristic: if a virtual is neither written to, nor read from - # it might not be "important enough" to keep it virtual - if not box.access_info.read_fields: - return match - raise DontMerge # XXX recursive data structures? + self.check_future_promotions(box, memo) return match def unfreeze(self, incomingvarboxes, memo): @@ -736,12 +722,8 @@ exact = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo) match = exact and partialdatamatch if not memo.force_merge and not match: - # heuristic: if a virtual is neither written to, nor read from - # it might not be "important enough" to keep it virtual from pypy.jit.timeshifter.rcontainer import VirtualContainer if isinstance(box.content, VirtualContainer): - if not box.access_info.read_fields: - return match raise DontMerge # XXX recursive data structures? return match @@ -751,7 +733,6 @@ def exactmatch(self, box, outgoingvarboxes, memo): assert isinstance(box, PtrRedBox) if box.genvar: - # XXX should we consider self.access_info here too? raise DontMerge else: assert box.content is not None Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_merging.py Tue Apr 1 15:24:00 2008 @@ -138,3 +138,34 @@ box3 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s3)) memo = rvalue.exactmatch_memo(rgenop) py.test.raises(rvalue.DontMerge, frozen.exactmatch, box3, [], memo) + + def test_promote_field_of_variable_immutable(self): + rgenop = FakeRGenOp() + gv = FakeGenVar() + box = rvalue.PtrRedBox(gv) + frozen = box.freeze(rvalue.freeze_memo()) + assert box.most_recent_frozen is not None # attached by freeze + + jitstate = FakeJITState() + + x_box = rtimeshift.gengetfield(jitstate, False, self.fielddesc, box) + assert not x_box.genvar.is_const + assert x_box.most_recent_frozen is not None # attached by gengetfield() + x_box.see_promote() + + memo = rvalue.exactmatch_memo(rgenop) + assert frozen.exactmatch(box, [], memo) + + prebuilt_s2 = lltype.malloc(self.STRUCT) + prebuilt_s2.x = 42 + box2 = rvalue.PtrRedBox(FakeGenConst(prebuilt_s2)) + memo = rvalue.exactmatch_memo(rgenop) + py.test.raises(rvalue.DontMerge, frozen.exactmatch, box2, [], memo) + + gv2 = FakeGenVar() + box3 = rvalue.PtrRedBox(gv2) + x_box3 = rtimeshift.gengetfield(jitstate, False, self.fielddesc, box3) + x_box3.see_promote() + x_box3.setgenvar(FakeGenConst(42)) + memo = rvalue.exactmatch_memo(rgenop) + py.test.raises(rvalue.DontMerge, frozen.exactmatch, box3, [], memo) Modified: pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/branch/jit-merging-logic/pypy/jit/timeshifter/test/test_rcontainer.py Tue Apr 1 15:24:00 2008 @@ -99,27 +99,6 @@ # constbox20 in oldbox. - def test_merge_with_ptrvar(self): - DontMerge = rvalue.DontMerge - V0 = FakeGenVar() - ptrbox = rvalue.PtrRedBox(V0) - jitstate = FakeJITState() - S = self.STRUCT - constbox20 = makebox(20) - oldbox = vmalloc(S, constbox20) - - # do a getfield to prevent a merge - box2 = oldbox.op_getfield(jitstate, self.fielddesc) - assert box2 is constbox20 - assert oldbox.access_info.read_fields == 1 - frozenbox = oldbox.freeze(rvalue.freeze_memo()) - # check that ptrbox does not match the frozen virtual struct ever - py.test.raises(DontMerge, self.match, frozenbox, ptrbox, [ptrbox]) - - # try it the other way round - frozenptrbox = ptrbox.freeze(rvalue.freeze_memo()) - py.test.raises(DontMerge, self.match, frozenptrbox, oldbox, [oldbox]) - def test_merge_with_ptrvar_virtual_never_read(self): DontMerge = rvalue.DontMerge V0 = FakeGenVar() From antocuni at codespeak.net Tue Apr 1 16:38:06 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 1 Apr 2008 16:38:06 +0200 (CEST) Subject: [pypy-svn] r53232 - in pypy/branch/jit-hotpath/pypy: jit/rainbow jit/rainbow/test jit/timeshifter rpython/ootypesystem translator Message-ID: <20080401143806.3CB421684F0@codespeak.net> Author: antocuni Date: Tue Apr 1 16:38:05 2008 New Revision: 53232 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py pypy/branch/jit-hotpath/pypy/translator/exceptiontransform.py Log: port oopspec and vlist to ootype. First test passes Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Tue Apr 1 16:38:05 2008 @@ -5,6 +5,7 @@ from pypy.objspace.flow import model as flowmodel from pypy.rpython.annlowlevel import cachedtype from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.hintannotator import model as hintmodel from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, exception @@ -732,13 +733,13 @@ self.exceptioninstance_positions[exc_class] = result return result - def oopspecdesc_position(self, fnobj, canraise): - key = fnobj, canraise + def oopspecdesc_position(self, opname, oparg, canraise): + key = opname, oparg, canraise if key in self.oopspecdesc_positions: return self.oopspecdesc_positions[key] oopspecdesc = oop.OopSpecDesc(self.RGenOp, self.rtyper, self.exceptiondesc, - fnobj, canraise) + opname, oparg, canraise) result = len(self.oopspecdescs) self.oopspecdescs.append(oopspecdesc) self.oopspecdesc_positions[key] = result @@ -1053,7 +1054,7 @@ def handle_oopspec_call(self, op, withexc): from pypy.jit.timeshifter.oop import Index fnobj = get_funcobj(op.args[0].value) - oopspecdescindex = self.oopspecdesc_position(fnobj, withexc) + oopspecdescindex = self.oopspecdesc_position('call', fnobj, withexc) oopspecdesc = self.oopspecdescs[oopspecdescindex] opargs = op.args[1:] args_v = [] @@ -1591,10 +1592,55 @@ return self.serialize_op_setfield_impl(op) def serialize_op_new(self, op): + TYPE = op.args[0].value + if TYPE.oopspec_name is not None: + # XXX: works only for List + oopspecdescindex = self.oopspecdesc_position('new', TYPE, False) + oopspecdesc = self.oopspecdescs[oopspecdescindex] + deepfrozen = False + index = self.serialize_oparg("red", flowmodel.Constant(0, lltype.Signed)) + self.emit('red_oopspec_call_1') + self.emit(oopspecdescindex) + self.emit(deepfrozen) + self.emit(index) + self.register_redvar(op.result) + return + index = self.structtypedesc_position(op.args[0].value) self.emit("red_new", index) self.register_redvar(op.result) + def serialize_op_oosend(self, op): + if self.hannotator.bookkeeper.is_green_call(op): + assert False, 'TODO' + + withexc = self.can_raise(op) + name = op.args[0].value + opargs = op.args[1:] + SELFTYPE = opargs[0].concretetype + if SELFTYPE.oopspec_name is not None: + hasresult = op.result.concretetype != lltype.Void + _, meth = SELFTYPE._lookup(name) + oopspecdescindex = self.oopspecdesc_position('send', meth, withexc) + oopspecdesc = self.oopspecdescs[oopspecdescindex] + args_v = [] + args = [] + for v in opargs: + args_v.append(v) + args.append(self.serialize_oparg("red", v)) + + hs_self = self.hannotator.binding(opargs[0]) + deepfrozen = hs_self.deepfrozen + + self.emit("red_oopspec_call%s_%s" % ("_noresult" * (not hasresult), + len(args))) + self.emit(oopspecdescindex) + self.emit(deepfrozen) + self.emit(*args) + + else: + assert False, 'TODO' + class GraphTransformer(object): def __init__(self, hannotator): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Tue Apr 1 16:38:05 2008 @@ -5,7 +5,7 @@ -class TestVList(InterpretationTest): +class VListTest(InterpretationTest): type_system = "lltype" def test_vlist(self): @@ -187,3 +187,24 @@ res = self.interpret(f, [2], [0], policy=P_OOPSPEC) assert res == -7 + + +class TestLLType(VListTest): + type_system = "lltype" + +class TestOOType(VListTest): + type_system = "ootype" + + def _skip(self): + py.test.skip('in progress') + + test_enter_block = _skip + test_merge = _skip + test_replace = _skip + test_force = _skip + test_oop_vlist = _skip + test_alloc_and_set = _skip + test_lists_deepfreeze = _skip + test_frozen_list = _skip + test_frozen_list_indexerror = _skip + test_bogus_index_while_compiling = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py Tue Apr 1 16:38:05 2008 @@ -4,7 +4,7 @@ def deref(T): if isinstance(T, lltype.Ptr): return T.TO - assert isinstance(T, (ootype.Instance, ootype.Record)) + assert isinstance(T, (ootype.Instance, ootype.BuiltinType)) return T def fieldType(T, name): Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py Tue Apr 1 16:38:05 2008 @@ -5,98 +5,59 @@ from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.tool.sourcetools import func_with_new_name from pypy.translator import exceptiontransform from pypy.translator.simplify import get_funcobj, get_functype +from pypy.jit.rainbow.typesystem import deref + +def OopSpecDesc(RGenOp, rtyper, exceptiondesc, opname, oparg, can_raise): + if opname == 'new': + cls = NewOopSpecDesc + elif opname == 'send': + cls = SendOopSpecDesc + elif opname == 'call': + cls = CallOopSpecDesc + return cls(RGenOp, rtyper, exceptiondesc, oparg, can_raise) class Index: def __init__(self, n): self.n = n - -class OopSpecDesc: +class AbstractOopSpecDesc: __metaclass__ = cachedtype def __init__(self, RGenOp, rtyper, exceptiondesc, fnobj, can_raise): self.rtyper = rtyper - ll_func = fnobj._callable - FUNCTYPE = lltype.typeOf(fnobj) - nb_args = len(FUNCTYPE.ARGS) - self.can_raise = can_raise + self._setup_oopdesc(RGenOp, fnobj) - # parse the oopspec and fill in the arguments - operation_name, args = ll_func.oopspec.split('(', 1) - assert args.endswith(')') - args = args[:-1] + ',' # trailing comma to force tuple syntax - if args.strip() == ',': - args = '()' - argnames = ll_func.func_code.co_varnames[:nb_args] - argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)])) - self.argtuple = eval(args, argname2index) - # end of rather XXX'edly hackish parsing - - OOPARGTYPES = [] - arg_llsig_to_oopsig = {} - for i, obj in enumerate(self.argtuple): - if isinstance(obj, Index): - arg_llsig_to_oopsig[obj.n] = i - OOPARG = FUNCTYPE.ARGS[obj.n] - else: - OOPARG = lltype.typeOf(obj) - OOPARGTYPES.append(OOPARG) - - self.residualargsources = [] - for i in range(nb_args): - ARGTYPE = FUNCTYPE.ARGS[i] - if ARGTYPE is not lltype.Void: - self.residualargsources.append(arg_llsig_to_oopsig[i]) - - self.args_gv = [None] * nb_args - fnptr = fnobj._as_ptr() - self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnptr) - result_kind = RGenOp.kindToken(FUNCTYPE.RESULT) - self.result_kind = result_kind - if FUNCTYPE.RESULT is lltype.Void: + if self.RESULT is lltype.Void: self.errorbox = None self.gv_whatever_return_value = None else: - error_value = exceptiontransform.error_value(FUNCTYPE.RESULT) + error_value = exceptiontransform.error_value(self.RESULT) self.errorbox = rvalue.redbox_from_prebuilt_value(RGenOp, error_value) self.gv_whatever_return_value = self.errorbox.genvar - redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT) + redboxbuilder = rvalue.ll_redboxbuilder(self.RESULT) self.redboxbuilder = redboxbuilder - self.sigtoken = RGenOp.sigToken(FUNCTYPE) - - if operation_name == 'newlist': - typename, method = 'list', 'oop_newlist' - SELFTYPE = FUNCTYPE.RESULT.TO - is_method = False - elif operation_name == 'newdict': - typename, method = 'dict', 'oop_newdict' - SELFTYPE = FUNCTYPE.RESULT.TO - is_method = False - else: - typename, method = operation_name.split('.') - method = 'oop_%s_%s' % (typename, method) - SELFTYPE = FUNCTYPE.ARGS[self.argtuple[0].n].TO - is_method = True - self.is_method = is_method # hack! to avoid confusion between the .typedesc attribute # of oopspecdescs of different types (lists, dicts, etc.) # let's use different subclasses for the oopspecdesc too. - self.__class__ = myrealclass = globals()['OopSpecDesc_%s' % typename] + thisclass = self.__class__.__name__ + self.__class__ = myrealclass = globals()['%s_%s' % (thisclass, self.typename)] - vmodule = __import__('pypy.jit.timeshifter.v%s' % (typename,), - None, None, [method]) + vmodule = __import__('pypy.jit.timeshifter.v%s' % (self.typename,), + None, None, [self.method]) self.typedesc = vmodule.TypeDesc(RGenOp, rtyper, exceptiondesc, - SELFTYPE) - handler = getattr(vmodule, method) + self.SELFTYPE) + handler = getattr(vmodule, self.method) boxargcount_max = handler.func_code.co_argcount - 3 boxargcount_min = boxargcount_max - len(handler.func_defaults or ()) + is_method = self.is_method def ll_handler(jitstate, oopspecdesc, deepfrozen, *argboxes): # an indirection to support the fact that the handler() can @@ -114,7 +75,7 @@ assert isinstance(oopspecdesc, myrealclass) if is_method: selfbox = argboxes[0] - assert isinstance(selfbox, rvalue.PtrRedBox) + assert isinstance(selfbox, rvalue.AbstractPtrRedBox) return handler(jitstate, oopspecdesc, deepfrozen, selfbox, *argboxes[1:]) else: @@ -124,21 +85,25 @@ self.couldfold = getattr(handler, 'couldfold', False) if self.couldfold: + # XXX: works only with lltype + ll_func = fnobj._callable oopargcheck = ll_func.oopargcheck # required if couldfold=True # make a copy of the function, for specialization purposes oopargcheck = func_with_new_name(oopargcheck, - 'argcheck_%s' % (method,)) + 'argcheck_%s' % (self.method,)) else: oopargcheck = None if True: # preserve indentation for svn history. # This used to be only if couldfold, but it is now # always required, for the fallback interp - ARGS = FUNCTYPE.ARGS + ARGS = self.ARGS residualargsources = self.residualargsources unrolling_ARGS = unrolling_iterable(ARGS) - unrolling_OOPARGS = unrolling_iterable(enumerate(OOPARGTYPES)) + unrolling_OOPARGS = unrolling_iterable(enumerate(self.OOPARGTYPES)) + RESULT = self.RESULT + fnptr = self.fnptr def do_call(rgenop, args_gv): oopargs = () for i, ARG in unrolling_OOPARGS: @@ -158,7 +123,7 @@ v = oopargs[argsrc] args += (v,) result = maybe_on_top_of_llinterp(exceptiondesc, fnptr)(*args) - if FUNCTYPE.RESULT == lltype.Void: + if RESULT == lltype.Void: return None return rgenop.genconst(result) @@ -179,8 +144,7 @@ jitstate.residual_exception(e) return self.errorbox else: - gv_result = builder.genop_call(self.sigtoken, - self.gv_fnptr, args_gv) + gv_result = self.generate_call(builder, args_gv) if self.can_raise: jitstate.generated_oop_residual_can_raise = True return self.redboxbuilder(gv_result) @@ -195,11 +159,127 @@ return self.errorbox residual_exception._annspecialcase_ = 'specialize:arg(2)' + def __repr__(self): + return '<%s(%s)>' % (self.__class__.__name__, self.method) + +class CallOopSpecDesc(AbstractOopSpecDesc): + + def _setup_oopdesc(self, RGenOp, fnobj): + FUNCTYPE = lltype.typeOf(fnobj) + self.ARGS = FUNCTYPE.ARGS + self.RESULT = FUNCTYPE.RESULT + ll_func = fnobj._callable + nb_args = len(FUNCTYPE.ARGS) + + # parse the oopspec and fill in the arguments + operation_name, args = ll_func.oopspec.split('(', 1) + assert args.endswith(')') + args = args[:-1] + ',' # trailing comma to force tuple syntax + if args.strip() == ',': + args = '()' + argnames = ll_func.func_code.co_varnames[:nb_args] + argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)])) + self.argtuple = eval(args, argname2index) + # end of rather XXX'edly hackish parsing + + self.OOPARGTYPES = [] + arg_llsig_to_oopsig = {} + for i, obj in enumerate(self.argtuple): + if isinstance(obj, Index): + arg_llsig_to_oopsig[obj.n] = i + OOPARG = FUNCTYPE.ARGS[obj.n] + else: + OOPARG = lltype.typeOf(obj) + self.OOPARGTYPES.append(OOPARG) + + self.residualargsources = [] + for i in range(nb_args): + ARGTYPE = FUNCTYPE.ARGS[i] + if ARGTYPE is not lltype.Void: + self.residualargsources.append(arg_llsig_to_oopsig[i]) + + if operation_name == 'newlist': + self.typename = 'list' + self.method = 'oop_newlist' + self.SELFTYPE = deref(FUNCTYPE.RESULT) + self.is_method = False + elif operation_name == 'newdict': + self.typename = 'dict' + self.method = 'oop_newdict' + self.SELFTYPE = deref(FUNCTYPE.RESULT) + is_method = False + else: + self.typename, method = operation_name.split('.') + self.method = 'oop_%s_%s' % (self.typename, method) + self.SELFTYPE = deref(FUNCTYPE.ARGS[self.argtuple[0].n]) + self.is_method = True + + self.fnptr = fnobj._as_ptr() + self.gv_fnptr = RGenOp.constPrebuiltGlobal(self.fnptr) + self.sigtoken = RGenOp.sigToken(FUNCTYPE) + + # the following attributes seem to be unused +## result_kind = RGenOp.kindToken(FUNCTYPE.RESULT) +## self.result_kind = result_kind +## self.args_gv = [None] * nb_args + + def generate_call(self, builder, args_gv): + return builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv) + + +class CallOopSpecDesc_list(CallOopSpecDesc): + pass + +class CallOopSpecDesc_dict(CallOopSpecDesc): + pass + + +class NewOopSpecDesc(AbstractOopSpecDesc): + def _setup_oopdesc(self, RGenOp, TYPE): + self.SELFTYPE = TYPE + self.ARGS = [] + self.RESULT = TYPE + self.OOPARGTYPES = [] + self.residualargsources = [] + self.typename = TYPE.oopspec_name + self.method = 'oop_new%s' % self.typename + self.is_method = False + + def allocate(): + return ootype.new(TYPE) + self.fnptr = self.rtyper.annotate_helper_fn(allocate, []) + +class NewOopSpecDesc_list(NewOopSpecDesc): + pass + +class NewOopSpecDesc_dict(NewOopSpecDesc): + pass + + +class SendOopSpecDesc(AbstractOopSpecDesc): + def _setup_oopdesc(self, RGenOp, meth): + METH = ootype.typeOf(meth) + assert METH.SELFTYPE is not None, 'fix ootype' + self.SELFTYPE = METH.SELFTYPE + self.ARGS = METH.ARGS + self.RESULT = METH.RESULT + + # we assume the number and position of the arguments are the + # same as in the original oosend + self.OOPARGTYPES = [self.SELFTYPE] + list(METH.ARGS) + self.residualargsources = range(len(self.OOPARGTYPES)) + self.typename = self.SELFTYPE.oopspec_name + methname = meth._name.lstrip('_') + methname = methname.lstrip('ll_') + self.method = 'oop_%s_method_%s' % (self.typename, methname) + self.is_method = True + self.fnptr = meth + -class OopSpecDesc_list(OopSpecDesc): +class SendOopSpecDesc_list(SendOopSpecDesc): pass -class OopSpecDesc_dict(OopSpecDesc): +class SendOopSpecDesc_dict(SendOopSpecDesc): pass Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Tue Apr 1 16:38:05 2008 @@ -86,8 +86,9 @@ self.name = self._get_type_name(TYPE) self.ptrkind = RGenOp.kindToken(self.PTRTYPE) - self.immutable = TYPE._hints.get('immutable', False) - self.noidentity = TYPE._hints.get('noidentity', False) + hints = getattr(TYPE, '_hints', {}) + self.immutable = hints.get('immutable', False) + self.noidentity = hints.get('noidentity', False) fixsize = not TYPE._is_varsize() @@ -260,14 +261,19 @@ pass def _iter_fields(self, TYPE): - for name, (FIELDTYPE, defl) in TYPE._fields.iteritems(): + try: + fields = TYPE._fields + except AttributeError: + return + for name, (FIELDTYPE, defl) in fields.iteritems(): yield name, FIELDTYPE def _get_type_name(self, TYPE): - if isinstance(TYPE, ootype.Record): - return TYPE._short_name() - else: + try: return TYPE._name + except AttributeError: + return TYPE._short_name() + def create_varsize(jitstate, contdesc, sizebox): gv_size = sizebox.getgenvar(jitstate) Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Tue Apr 1 16:38:05 2008 @@ -6,6 +6,12 @@ from pypy.rpython.lltypesystem import lloperation debug_print = lloperation.llop.debug_print +def TypeDesc(RGenOp, rtyper, exceptiondesc, LIST): + if rtyper.type_system.name == 'lltypesystem': + return LLTypeListTypeDesc(RGenOp, rtyper, exceptiondesc, LIST) + else: + return OOTypeListTypeDesc(RGenOp, rtyper, exceptiondesc, LIST) + class ItemDesc(object): __metaclass__ = cachedtype @@ -24,17 +30,59 @@ if not T._is_varsize(): self.canbevirtual = True -class ListTypeDesc(object): +class AbstractListTypeDesc(object): __metaclass__ = cachedtype def __init__(self, RGenOp, rtyper, exceptiondesc, LIST): self.LIST = LIST - self.LISTPTR = lltype.Ptr(LIST) + self.LISTPTR = self.Ptr(LIST) self.ptrkind = RGenOp.kindToken(self.LISTPTR) self.null = self.LISTPTR._defl() self.gv_null = RGenOp.constPrebuiltGlobal(self.null) self.exceptiondesc = exceptiondesc + self._setup(RGenOp, rtyper, LIST) + self._define_devirtualize() + self._define_allocate() + + def _define_allocate(self): + LIST = self.LIST + LISTPTR = self.LISTPTR + + def allocate(rgenop, n): + l = LIST.ll_newlist(n) + return rgenop.genconst(l) + + def populate(item_boxes, gv_lst, box_gv_reader): + l = gv_lst.revealconst(LISTPTR) + # NB. len(item_boxes) may be l.ll_length()+1 if need_reshaping :-( + for i in range(l.ll_length()): + box = item_boxes[i] + if box is not None: + gv_value = box_gv_reader(box) + v = gv_value.revealconst(LIST.ITEM) + l.ll_setitem_fast(i, v) + + self.allocate = allocate + self.populate = populate + + def _freeze_(self): + return True + + def factory(self, length, itembox): + vlist = VirtualList(self, length, itembox) + box = self.PtrRedBox(known_nonzero=True) + box.content = vlist + vlist.ownbox = box + return box + + +class LLTypeListTypeDesc(AbstractListTypeDesc): + + Ptr = staticmethod(lltype.Ptr) + PtrRedBox = rvalue.PtrRedBox + + def _setup(self, RGenOp, rtyper, LIST): argtypes = [lltype.Signed] ll_newlist_ptr = rtyper.annotate_helper_fn(LIST.ll_newlist, argtypes) @@ -48,9 +96,6 @@ self.tok_ll_setitem_fast = RGenOp.sigToken( lltype.typeOf(ll_setitem_fast).TO) - self._define_devirtualize() - self._define_allocate() - def _define_devirtualize(self): LIST = self.LIST LISTPTR = self.LISTPTR @@ -70,39 +115,18 @@ self.devirtualize = make, fill_into - def _define_allocate(self): - LIST = self.LIST - LISTPTR = self.LISTPTR - - def allocate(rgenop, n): - l = LIST.ll_newlist(n) - return rgenop.genconst(l) - - def populate(item_boxes, gv_lst, box_gv_reader): - l = gv_lst.revealconst(LISTPTR) - # NB. len(item_boxes) may be l.ll_length()+1 if need_reshaping :-( - for i in range(l.ll_length()): - box = item_boxes[i] - if box is not None: - gv_value = box_gv_reader(box) - v = gv_value.revealconst(LIST.ITEM) - l.ll_setitem_fast(i, v) + - self.allocate = allocate - self.populate = populate +class OOTypeListTypeDesc(AbstractListTypeDesc): - def _freeze_(self): - return True - - def factory(self, length, itembox): - vlist = VirtualList(self, length, itembox) - box = rvalue.PtrRedBox(known_nonzero=True) - box.content = vlist - vlist.ownbox = box - return box + Ptr = staticmethod(lambda T: T) + PtrRedBox = rvalue.InstanceRedBox -TypeDesc = ListTypeDesc + def _setup(self, RGenOp, rtyper, LIST): + pass + def _define_devirtualize(self): + pass # XXX class FrozenVirtualList(FrozenContainer): @@ -163,6 +187,7 @@ def __init__(self, typedesc, length=0, itembox=None): self.typedesc = typedesc + self.itembox = itembox self.item_boxes = [itembox] * length # self.ownbox = ... set in factory() @@ -355,6 +380,18 @@ deepfrozen=deepfrozen) oop_list_nonzero.couldfold = True +def oop_list_method_resize(jitstate, oopspecdesc, deepfrozen, selfbox, lengthbox): + content = selfbox.content + if isinstance(content, VirtualList): + item_boxes = content.item_boxes + length = rvalue.ll_getvalue(lengthbox, lltype.Signed) + if len(item_boxes) < length: + diff = length - len(item_boxes) + item_boxes += [itembox] * diff + else: + oopspecdesc.residual_call(jitstate, [selfbox], + deepfrozen=deepfrozen) + def oop_list_append(jitstate, oopspecdesc, deepfrozen, selfbox, itembox): content = selfbox.content if isinstance(content, VirtualList): Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Tue Apr 1 16:38:05 2008 @@ -13,6 +13,8 @@ class OOType(LowLevelType): + oopspec_name = None + def _is_compatible(TYPE1, TYPE2): if TYPE1 == TYPE2: return True @@ -476,6 +478,7 @@ # placeholder, because we want backends to distinguish that. SELFTYPE_T = object() ITEMTYPE_T = object() + oopspec_name = 'list' def __init__(self, ITEMTYPE=None): self._ITEMTYPE = ITEMTYPE @@ -564,6 +567,7 @@ SELFTYPE_T = object() KEYTYPE_T = object() VALUETYPE_T = object() + oopspec_name = 'dict' def __init__(self, KEYTYPE=None, VALUETYPE=None): self._KEYTYPE = KEYTYPE @@ -1016,6 +1020,9 @@ def __repr__(self): return 'sm %s' % self._name + def _as_ptr(self): + return self + class _forward_static_meth(_static_meth): allowed_types = (StaticMethod, ForwardReference) Modified: pypy/branch/jit-hotpath/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/exceptiontransform.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/exceptiontransform.py Tue Apr 1 16:38:05 2008 @@ -473,8 +473,11 @@ return obj1 is obj2 def check_for_alloc_shortcut(self, spaceop): +## if spaceop.opname in ('new', 'runtimenew', 'oonewcustomdict'): +## return True return False + def ExceptionTransformer(translator): type_system = translator.rtyper.type_system.name if type_system == 'lltypesystem': From antocuni at codespeak.net Tue Apr 1 17:03:30 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 1 Apr 2008 17:03:30 +0200 (CEST) Subject: [pypy-svn] r53233 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080401150330.7F26B168417@codespeak.net> Author: antocuni Date: Tue Apr 1 17:03:29 2008 New Revision: 53233 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Log: this test passes out of the box Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Tue Apr 1 17:03:29 2008 @@ -198,7 +198,6 @@ def _skip(self): py.test.skip('in progress') - test_enter_block = _skip test_merge = _skip test_replace = _skip test_force = _skip From fijal at codespeak.net Tue Apr 1 18:02:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 18:02:32 +0200 (CEST) Subject: [pypy-svn] r53234 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080401160232.EE00B168447@codespeak.net> Author: fijal Date: Tue Apr 1 18:02:31 2008 New Revision: 53234 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: support for NEW opcode. Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Tue Apr 1 18:02:31 2008 @@ -130,7 +130,6 @@ def visit_memberexpression(self, node): if isinstance(node.children[0], Symbol) and \ node.children[0].additional_info == 'new': # XXX could be a identifier? - raise NotImplementedError pos = self.get_pos(node) left = self.dispatch(node.children[1]) right = self.dispatch(node.children[2]) Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Tue Apr 1 18:02:31 2008 @@ -2,7 +2,8 @@ """ Base operations implementations """ -from pypy.lang.js.jsobj import W_String, W_IntNumber, W_FloatNumber +from pypy.lang.js.jsobj import W_String, W_IntNumber, W_FloatNumber,\ + W_PrimitiveObject from pypy.rlib.rarithmetic import r_uint, intmask, INFINITY, NAN, ovfcheck,\ isnan, isinf @@ -199,3 +200,13 @@ if type1 == "boolean": return x.ToBoolean() == x.ToBoolean() return x == y + + +def commonnew(ctx, obj, args): + if not isinstance(obj, W_PrimitiveObject): + raise ThrowException(W_String('it is not a constructor')) + try: + res = obj.Construct(ctx=ctx, args=args) + except JsTypeError: + raise ThrowException(W_String('it is not a constructor')) + return res Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Tue Apr 1 18:02:31 2008 @@ -2,11 +2,11 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\ W_Array, W_PrimitiveObject, W_Reference, ActivationObject,\ create_object, W_Object, w_Undefined, W_Boolean, newbool,\ - w_True, w_False + w_True, w_False, W_List from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException from pypy.rlib.unroll import unrolling_iterable from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ - compare_e, increment + compare_e, increment, commonnew from pypy.rlib.jit import hint class AlreadyRun(Exception): @@ -229,6 +229,16 @@ def __repr__(self): return 'LOAD_ARRAY %d' % (self.counter,) +class LOAD_LIST(Opcode): + def __init__(self, counter): + self.counter = counter + + def eval(self, ctx, stack): + to_cut = len(stack)-self.counter + list_w = stack[to_cut:] + del stack[to_cut:] + stack.append(W_List(list_w)) + class LOAD_FUNCTION(Opcode): def __init__(self, funcobj): self.funcobj = funcobj @@ -589,6 +599,14 @@ def __repr__(self): return "TRYCATCHBLOCK" # XXX shall we add stuff here??? +class NEW(Opcode): + def eval(self, ctx, stack): + y = stack.pop() + x = stack.pop() + assert isinstance(y, W_List) + args = y.get_args() + stack.append(commonnew(ctx, x, args)) + OpcodeMap = {} for name, value in locals().items(): Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Tue Apr 1 18:02:31 2008 @@ -488,6 +488,9 @@ def get_args(self): return self.list_w + def tolist(self): + return self.list_w + def __repr__(self): return 'W_List(%s)' % (self.list_w,) Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Tue Apr 1 18:02:31 2008 @@ -552,7 +552,7 @@ def emit(self, bytecode): for node in self.nodes: node.emit(bytecode) - bytecode.emit('LOAD_ARRAY', len(self.nodes)) + bytecode.emit('LOAD_LIST', len(self.nodes)) ############################################################################## # @@ -577,26 +577,21 @@ # ############################################################################## -def commonnew(ctx, obj, args): - if not isinstance(obj, W_PrimitiveObject): - raise ThrowException(W_String('it is not a constructor')) - try: - res = obj.Construct(ctx=ctx, args=args) - except JsTypeError: - raise ThrowException(W_String('it is not a constructor')) - return res - #class New(UnaryOp): # def eval(self, ctx): # x = self.expr.eval(ctx).GetValue() # return commonnew(ctx, x, []) - -# class NewWithArgs(BinaryOp): -# def eval(self, ctx): -# x = self.left.eval(ctx).GetValue() -# args = self.right.eval(ctx).get_args() -# return commonnew(ctx, x, args) +class NewWithArgs(Expression): + def __init__(self, pos, left, right): + self.pos = pos + self.left = left + self.right = right + + def emit(self, bytecode): + self.left.emit(bytecode) + self.right.emit(bytecode) + bytecode.emit('NEW') class BaseNumber(Expression): pass From fijal at codespeak.net Tue Apr 1 18:32:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 18:32:10 +0200 (CEST) Subject: [pypy-svn] r53235 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080401163210.BADFC16842D@codespeak.net> Author: fijal Date: Tue Apr 1 18:32:10 2008 New Revision: 53235 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py Log: introduce a hack. toon, please test it. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Tue Apr 1 18:32:10 2008 @@ -6,6 +6,7 @@ from pypy.rlib.objectmodel import free_non_gc_object from pypy.rlib.debug import ll_assert from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rlib.nonconst import NonConstant # The following flag is never set on young objects, i.e. the ones living # in the nursery. It is initially set on all prebuilt and old objects, @@ -500,7 +501,8 @@ size = rffi.sizeof(rffi.LONGLONG) l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0) len_p[0] = rffi.cast(rffi.SIZE_T, size) - result = sysctlbyname("hw.l2cachesize", + # XXX a hack for llhelper not being robust-enough + result = sysctlbyname(NonConstant("hw.l2cachesize"), rffi.cast(rffi.VOIDP, l2cache_p), len_p, lltype.nullptr(rffi.VOIDP.TO), From antocuni at codespeak.net Tue Apr 1 19:35:29 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 1 Apr 2008 19:35:29 +0200 (CEST) Subject: [pypy-svn] r53236 - in pypy/branch/jit-hotpath/pypy/jit: rainbow/test timeshifter Message-ID: <20080401173529.B7FDE168051@codespeak.net> Author: antocuni Date: Tue Apr 1 19:35:28 2008 New Revision: 53236 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py Log: two more test pass Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Tue Apr 1 19:35:28 2008 @@ -189,17 +189,12 @@ assert res == -7 -class TestLLType(VListTest): - type_system = "lltype" - class TestOOType(VListTest): type_system = "ootype" def _skip(self): py.test.skip('in progress') - test_merge = _skip - test_replace = _skip test_force = _skip test_oop_vlist = _skip test_alloc_and_set = _skip @@ -207,3 +202,7 @@ test_frozen_list = _skip test_frozen_list_indexerror = _skip test_bogus_index_while_compiling = _skip + + +class TestLLType(VListTest): + type_system = "lltype" Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py Tue Apr 1 19:35:28 2008 @@ -662,7 +662,7 @@ class FrozenPtrVirtual(FrozenValue): def exactmatch(self, box, outgoingvarboxes, memo): - assert isinstance(box, PtrRedBox) + assert isinstance(box, AbstractPtrRedBox) if box.genvar: # XXX should we consider self.access_info here too? raise DontMerge @@ -695,7 +695,7 @@ PtrRedBox.FrozenPtrVar = FrozenPtrVar PtrRedBox.FrozenPtrVarWithPartialData = FrozenPtrVarWithPartialData -InstanceRedBox.FrozenPtrVirtual = None +InstanceRedBox.FrozenPtrVirtual = FrozenPtrVirtual InstanceRedBox.FrozenPtrConst = FrozenInstanceConst InstanceRedBox.FrozenPtrVar = FrozenInstanceVar InstanceRedBox.FrozenPtrVarWithPartialData = None From fijal at codespeak.net Tue Apr 1 19:39:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Apr 2008 19:39:57 +0200 (CEST) Subject: [pypy-svn] r53237 - in pypy/dist/pypy/module/zipimport: . test Message-ID: <20080401173957.C7D281683FA@codespeak.net> Author: fijal Date: Tue Apr 1 19:39:57 2008 New Revision: 53237 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: .prefix attribute for zipimporter. Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Tue Apr 1 19:39:57 2008 @@ -25,11 +25,15 @@ (False, False, '.py')]) class W_ZipImporter(Wrappable): - def __init__(self, space, name, w_dir, w_zipfile): + def __init__(self, space, name, w_dir, w_zipfile, prefix): self.space = space self.name = name self.w_dir = w_dir self.w_zipfile = w_zipfile + self.prefix = prefix + + def getprefix(space, self): + return space.wrap(self.prefix) def import_py_file(self, space, modname, filename, w_buf, pkgpath): buf = space.str_w(w_buf) @@ -220,6 +224,10 @@ if not ok: raise OperationError(space.w_ImportError, space.wrap( "Did not find %s to be a valid zippath" % (name,))) + last_elem = filename.split(os.path.sep)[-1] + stop = len(filename)-len(last_elem) + assert stop > 0 + prefix = filename[:stop] w_import = space.builtin.get('__import__') w_zipfile = space.call(w_import, space.newlist([ space.wrap('zipfile'), @@ -232,7 +240,7 @@ except OperationError, e: # we catch everything as this function raise OperationError(space.w_ImportError, space.wrap( "%s seems not to be a zipfile" % (filename,))) - w_result = space.wrap(W_ZipImporter(space, name, w_dir, w_zipfile)) + w_result = space.wrap(W_ZipImporter(space, name, w_dir, w_zipfile, prefix)) space.setitem(w_zip_cache, space.wrap(name), w_result) return w_result @@ -248,4 +256,5 @@ is_package = interp2app(W_ZipImporter.is_package), load_module = interp2app(W_ZipImporter.load_module), archive = GetSetProperty(W_ZipImporter.getarchive), + prefix = GetSetProperty(W_ZipImporter.getprefix), ) Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Tue Apr 1 19:39:57 2008 @@ -227,7 +227,10 @@ # value. Not sure why it doesn't the assertion uses import.archive # directly. -exarkun archive = importer.archive + allbutlast = self.zipfile.split(os.path.sep)[:-1] + prefix = os.path.sep.join(allbutlast + ['']) assert archive == self.zipfile + assert importer.prefix == prefix class AppTestZipimportDeflated(AppTestZipimport): From cfbolz at codespeak.net Tue Apr 1 21:15:58 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 1 Apr 2008 21:15:58 +0200 (CEST) Subject: [pypy-svn] r53238 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080401191558.3A9A116841F@codespeak.net> Author: cfbolz Date: Tue Apr 1 21:15:56 2008 New Revision: 53238 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: fix green ptr equality Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py Tue Apr 1 21:15:56 2008 @@ -339,6 +339,17 @@ addr = gv_ptr.revealconst(llmemory.Address) return self.rgenop.genconst(not addr) + @arguments("green", returns="green") + def opimpl_green_ptr_nonzero(self, gv_ptr): + addr = gv_ptr.revealconst(llmemory.Address) + return self.rgenop.genconst(bool(addr)) + + @arguments("green", returns="green") + def opimpl_green_ptr_iszero(self, gv_ptr): + addr = gv_ptr.revealconst(llmemory.Address) + return self.rgenop.genconst(not addr) + + @arguments("red", "red", returns="red") def opimpl_red_ptr_eq(self, gv_ptr1, gv_ptr2): addr1 = gv_ptr1.revealconst(llmemory.Address) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Tue Apr 1 21:15:56 2008 @@ -540,6 +540,17 @@ return rtimeshift.genptreq(self.jitstate, ptrbox1, ptrbox2, True) + @arguments("green", returns="green") + def opimpl_green_ptr_nonzero(self, gv_ptr): + addr = gv_ptr.revealconst(llmemory.Address) + return self.rgenop.genconst(bool(addr)) + + @arguments("green", returns="green") + def opimpl_green_ptr_iszero(self, gv_ptr): + addr = gv_ptr.revealconst(llmemory.Address) + return self.rgenop.genconst(not bool(addr)) + + @arguments("red", "bool") def opimpl_learn_boolvalue(self, redbox, boolval): redbox.learn_boolvalue(self.jitstate, boolval) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Tue Apr 1 21:15:56 2008 @@ -1971,6 +1971,35 @@ assert res == 7 self.check_insns(getfield=0) + def test_green_ptrequality(self): + class A(object): + _immutable_ = True + def __init__(self, a): + self.a = a + + five = A(5) + seven = A(7) + + def g(x): + if x: + return seven + return five + def f(green1, green2): + hint(None, global_merge_point=True) + hint(green1, concrete=True) + hint(green2, concrete=True) + if green1: + a = seven + else: + a = five + if green2: + b = seven + else: + b = five + return int(a is not b) + int(a is b) + res = self.interpret(f, [True, True], policy=StopAtXPolicy(g)) + assert res == f(True, True) + # void tests def test_void_args(self): class Space(object): @@ -2097,6 +2126,7 @@ test_learn_nonzeroness = _skip test_void_args = _skip test_ptrequality = _skip + test_green_ptrequality = _skip From antocuni at codespeak.net Tue Apr 1 23:51:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 1 Apr 2008 23:51:56 +0200 (CEST) Subject: [pypy-svn] r53239 - in pypy/branch/jit-hotpath/pypy/jit: codegen codegen/llgraph rainbow/test timeshifter Message-ID: <20080401215156.49F69168433@codespeak.net> Author: antocuni Date: Tue Apr 1 23:51:55 2008 New Revision: 53239 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/model.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Log: implement forcing for virtual lists on ootype. test_force passes Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/rgenop.py Tue Apr 1 23:51:55 2008 @@ -146,10 +146,8 @@ gv_Bool.v)) return gv_res, gv_exc - def genop_call(self, (ARGS_gv, gv_RESULT, _), gv_callable, args_gv): - ll_assert(self.rgenop.currently_writing is self, - "genop_call: bad currently_writing") - vars_gv = [gv_callable] + def _cast_args_gv(self, ARGS_gv, args_gv): + vars_gv = [] j = 0 for i in range(len(ARGS_gv)): if ARGS_gv[i] is gv_Void: @@ -158,6 +156,13 @@ gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, args_gv[j].v)) j += 1 vars_gv.append(gv_arg) + return vars_gv + + def genop_call(self, (ARGS_gv, gv_RESULT, _), gv_callable, args_gv): + ll_assert(self.rgenop.currently_writing is self, + "genop_call: bad currently_writing") + vars_gv = [gv_callable] + vars_gv += self._cast_args_gv(ARGS_gv, args_gv) if gv_callable.is_const: v = llimpl.genop(self.b, 'direct_call', vars_gv, gv_RESULT.v) else: @@ -165,6 +170,14 @@ v = llimpl.genop(self.b, 'indirect_call', vars_gv, gv_RESULT.v) return LLVar(v) + def genop_oosend(self, (gv_methname, (ARGS_gv, gv_RESULT, _)), gv_self, args_gv): + ll_assert(self.rgenop.currently_writing is self, + "genop_oosend: bad currently_writing") + vars_gv = [gv_methname, gv_self] + vars_gv += self._cast_args_gv(ARGS_gv, args_gv) + v = llimpl.genop(self.b, 'oosend', vars_gv, gv_RESULT.v) + return LLVar(v) + def genop_getfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr): ll_assert(self.rgenop.currently_writing is self, "genop_getfield: bad currently_writing") @@ -459,6 +472,14 @@ gv_TYPE(FUNCTYPE.RESULT), gv_TYPE(FUNCTYPE)) + @staticmethod + @specialize.memo() + def methToken(TYPE, methname): + _, meth = TYPE._lookup(methname) + METH = ootype.typeOf(meth) + gv_methname = LLConst(llimpl.constFieldName(methname)) + return (gv_methname, RGenOp.sigToken(METH)) + constPrebuiltGlobal = genconst @staticmethod Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/model.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/model.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/model.py Tue Apr 1 23:51:55 2008 @@ -349,6 +349,12 @@ # raise NotImplementedError #@staticmethod + #@specialize.memo() + #def methToken(TYPE, methname): + # """Return a token describing the method methname of type TYPE.""" + # raise NotImplementedError + + #@staticmethod #@specialize.arg(0) #def read_frame_var(T, base, info, index): # """Read from the stack frame of a caller. The 'base' is the Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Tue Apr 1 23:51:55 2008 @@ -195,7 +195,6 @@ def _skip(self): py.test.skip('in progress') - test_force = _skip test_oop_vlist = _skip test_alloc_and_set = _skip test_lists_deepfreeze = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Tue Apr 1 23:51:55 2008 @@ -115,6 +115,16 @@ self.devirtualize = make, fill_into + def gen_newlist(self, builder, args_gv): + return builder.genop_call(self.tok_ll_newlist, + self.gv_ll_newlist, + args_gv) + + def gen_setitem_fast(self, builder, args_gv): + return builder.genop_call(self.tok_ll_setitem_fast, + self.gv_ll_setitem_fast, + args_gv) + class OOTypeListTypeDesc(AbstractListTypeDesc): @@ -123,11 +133,24 @@ PtrRedBox = rvalue.InstanceRedBox def _setup(self, RGenOp, rtyper, LIST): - pass + self.alloctoken = RGenOp.allocToken(LIST) + self.tok_ll_resize = RGenOp.methToken(LIST, '_ll_resize') + self.tok_ll_setitem_fast = RGenOp.methToken(LIST, + 'll_setitem_fast') def _define_devirtualize(self): pass # XXX + def gen_newlist(self, builder, args_gv): + gv_lst = builder.genop_new(self.alloctoken) + builder.genop_oosend(self.tok_ll_resize, gv_lst, args_gv) + return gv_lst + + def gen_setitem_fast(self, builder, args_gv): + gv_lst = args_gv.pop(0) + return builder.genop_oosend(self.tok_ll_setitem_fast, + gv_lst, args_gv) + class FrozenVirtualList(FrozenContainer): def __init__(self, typedesc): @@ -211,17 +234,13 @@ debug_print(lltype.Void, "FORCE LIST (%d items)" % (len(boxes),)) args_gv = [builder.rgenop.genconst(len(boxes))] - gv_list = builder.genop_call(typedesc.tok_ll_newlist, - typedesc.gv_ll_newlist, - args_gv) + gv_list = typedesc.gen_newlist(builder, args_gv) self.setforced(gv_list) for i in range(len(boxes)): gv_item = boxes[i].getgenvar(jitstate) args_gv = [gv_list, builder.rgenop.genconst(i), gv_item] - builder.genop_call(typedesc.tok_ll_setitem_fast, - typedesc.gv_ll_setitem_fast, - args_gv) + typedesc.gen_setitem_fast(builder, args_gv) def freeze(self, memo): contmemo = memo.containers From antocuni at codespeak.net Wed Apr 2 00:01:25 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 2 Apr 2008 00:01:25 +0200 (CEST) Subject: [pypy-svn] r53241 - in pypy/branch/jit-hotpath/pypy/jit: rainbow/test timeshifter Message-ID: <20080401220125.705E2168433@codespeak.net> Author: antocuni Date: Wed Apr 2 00:01:24 2008 New Revision: 53241 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Log: some minor fixes, and test_oop_vlist passes Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Wed Apr 2 00:01:24 2008 @@ -195,7 +195,6 @@ def _skip(self): py.test.skip('in progress') - test_oop_vlist = _skip test_alloc_and_set = _skip test_lists_deepfreeze = _skip test_frozen_list = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Wed Apr 2 00:01:24 2008 @@ -302,7 +302,7 @@ vars_gv.append(box.genvar) else: varindexes.append(j) - assert isinstance(box, rvalue.PtrRedBox) + assert isinstance(box, rvalue.AbstractPtrRedBox) content = box.content assert content.allowed_in_virtualizable vrtis.append(content.make_rti(jitstate, memo)) @@ -349,7 +349,7 @@ for box in boxes: if not box.genvar: - assert isinstance(box, rvalue.PtrRedBox) + assert isinstance(box, rvalue.AbstractPtrRedBox) content = box.content assert content.allowed_in_virtualizable content.store_back_gv_reshaped(shapemask, memo) @@ -406,7 +406,9 @@ length = rvalue.ll_getvalue(lengthbox, lltype.Signed) if len(item_boxes) < length: diff = length - len(item_boxes) - item_boxes += [itembox] * diff + item_boxes += [content.itembox] * diff + else: + assert False, 'XXX' else: oopspecdesc.residual_call(jitstate, [selfbox], deepfrozen=deepfrozen) @@ -431,7 +433,7 @@ def oop_list_concat(jitstate, oopspecdesc, deepfrozen, selfbox, otherbox): content = selfbox.content if isinstance(content, VirtualList): - assert isinstance(otherbox, rvalue.PtrRedBox) + assert isinstance(otherbox, rvalue.AbstractPtrRedBox) othercontent = otherbox.content if othercontent is not None and isinstance(othercontent, VirtualList): newbox = oopspecdesc.typedesc.factory(0, None) @@ -493,6 +495,8 @@ else: oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) +oop_list_method_setitem_fast = oop_list_setitem + def oop_list_delitem(jitstate, oopspecdesc, deepfrozen, selfbox, indexbox): content = selfbox.content if isinstance(content, VirtualList) and indexbox.is_constant(): From antocuni at codespeak.net Wed Apr 2 00:04:19 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 2 Apr 2008 00:04:19 +0200 (CEST) Subject: [pypy-svn] r53242 - in pypy/branch/jit-hotpath/pypy/jit: rainbow/test timeshifter Message-ID: <20080401220419.8F1D8168426@codespeak.net> Author: antocuni Date: Wed Apr 2 00:04:19 2008 New Revision: 53242 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Log: all tests pass! :-) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Wed Apr 2 00:04:19 2008 @@ -192,15 +192,5 @@ class TestOOType(VListTest): type_system = "ootype" - def _skip(self): - py.test.skip('in progress') - - test_alloc_and_set = _skip - test_lists_deepfreeze = _skip - test_frozen_list = _skip - test_frozen_list_indexerror = _skip - test_bogus_index_while_compiling = _skip - - class TestLLType(VListTest): type_system = "lltype" Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Wed Apr 2 00:04:19 2008 @@ -407,7 +407,7 @@ if len(item_boxes) < length: diff = length - len(item_boxes) item_boxes += [content.itembox] * diff - else: + elif len(item_boxes) > length: assert False, 'XXX' else: oopspecdesc.residual_call(jitstate, [selfbox], From cfbolz at codespeak.net Wed Apr 2 02:28:39 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 2 Apr 2008 02:28:39 +0200 (CEST) Subject: [pypy-svn] r53243 - in pypy/branch/jit-hotpath/pypy/lang/prolog: builtin interpreter interpreter/test Message-ID: <20080402002839.481A2168411@codespeak.net> Author: cfbolz Date: Wed Apr 2 02:28:39 2008 New Revision: 53243 Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/allsolution.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/arithmeticbuiltin.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/atomconstruction.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/control.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/database.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/exception.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/formatting.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/parseraccess.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/register.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/source.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/termconstruction.py pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/unify.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/arithmetic.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/choice.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/helper.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/interactive.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/portal.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/term.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/dont_test_translate.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_engine.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_jit.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_parsing.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_unification.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/tool.py pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/translatedmain.py Log: whack a bit at the prolog interpreter, trying to make it jittable Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/allsolution.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/allsolution.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/allsolution.py Wed Apr 2 02:28:39 2008 @@ -11,22 +11,23 @@ self.template = template def _call(self, engine): - clone = self.template.getvalue(engine.heap) + clone = self.template.getvalue(engine) self.found.append(clone) raise error.UnificationFailed() def impl_findall(engine, template, goal, bag): - oldstate = engine.heap.branch() + oldstate = engine.branch() collector = FindallContinuation(template) try: engine.call(goal, collector) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) result = term.Atom.newatom("[]") for i in range(len(collector.found) - 1, -1, -1): copy = collector.found[i] d = {} - copy = copy.copy(engine.heap, d) + copy = copy.copy(engine, d) result = term.Term(".", [copy, result]) - bag.unify(result, engine.heap) + bag.unify(result, engine) +impl_findall._look_inside_me_ = False expose_builtin(impl_findall, "findall", unwrap_spec=['raw', 'callable', 'raw']) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/arithmeticbuiltin.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/arithmeticbuiltin.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/arithmeticbuiltin.py Wed Apr 2 02:28:39 2008 @@ -9,13 +9,13 @@ def impl_between(engine, lower, upper, varorint, continuation): if isinstance(varorint, term.Var): for i in range(lower, upper): - oldstate = engine.heap.branch() + oldstate = engine.branch() try: - varorint.unify(term.Number(i), engine.heap) + varorint.unify(term.Number(i), engine) return continuation.call(engine, choice_point=True) except error.UnificationFailed: - engine.heap.revert(oldstate) - varorint.unify(term.Number(upper), engine.heap) + engine.revert(oldstate) + varorint.unify(term.Number(upper), engine) return continuation.call(engine, choice_point=False) else: integer = helper.unwrap_int(varorint) @@ -26,8 +26,7 @@ handles_continuation=True) def impl_is(engine, var, num): - var.unify(num, engine.heap) -impl_is._look_inside_me_ = True + var.unify(num, engine) expose_builtin(impl_is, "is", unwrap_spec=["raw", "arithmetic"]) for ext, prolog, python in [("eq", "=:=", "=="), @@ -57,6 +56,7 @@ eq = n1 %s n2 if not eq: raise error.UnificationFailed()""" % (ext, python, python)).compile() - expose_builtin(globals()["impl_arith_%s" % (ext, )], prolog, + func = globals()["impl_arith_%s" % (ext, )] + expose_builtin(func, prolog, unwrap_spec=["arithmetic", "arithmetic"]) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/atomconstruction.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/atomconstruction.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/atomconstruction.py Wed Apr 2 02:28:39 2008 @@ -11,13 +11,13 @@ # nondeterministic splitting of result r = helper.convert_to_str(result) for i in range(len(r) + 1): - oldstate = engine.heap.branch() + oldstate = engine.branch() try: - a1.unify(term.Atom(r[:i]), engine.heap) - a2.unify(term.Atom(r[i:]), engine.heap) + a1.unify(term.Atom(r[:i]), engine) + a2.unify(term.Atom(r[i:]), engine) return continuation.call(engine, choice_point=True) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise error.UnificationFailed() else: s2 = helper.convert_to_str(a2) @@ -25,7 +25,7 @@ if r.endswith(s2): stop = len(r) - len(s2) assert stop > 0 - a1.unify(term.Atom(r[:stop]), engine.heap) + a1.unify(term.Atom(r[:stop]), engine) else: raise error.UnificationFailed() else: @@ -33,12 +33,12 @@ if isinstance(a2, term.Var): r = helper.convert_to_str(result) if r.startswith(s1): - a2.unify(term.Atom(r[len(s1):]), engine.heap) + a2.unify(term.Atom(r[len(s1):]), engine) else: raise error.UnificationFailed() else: s2 = helper.convert_to_str(a2) - result.unify(term.Atom(s1 + s2), engine.heap) + result.unify(term.Atom(s1 + s2), engine) return continuation.call(engine, choice_point=False) expose_builtin(impl_atom_concat, "atom_concat", unwrap_spec=["obj", "obj", "obj"], @@ -47,7 +47,7 @@ def impl_atom_length(engine, s, length): if not (isinstance(length, term.Var) or isinstance(length, term.Number)): error.throw_type_error("integer", length) - term.Number(len(s)).unify(length, engine.heap) + term.Number(len(s)).unify(length, engine) expose_builtin(impl_atom_length, "atom_length", unwrap_spec = ["atom", "obj"]) def impl_sub_atom(engine, s, before, length, after, sub, continuation): @@ -70,7 +70,7 @@ if startbefore < 0: startbefore = 0 stopbefore = len(s) + 1 - oldstate = engine.heap.branch() + oldstate = engine.branch() if not isinstance(sub, term.Var): s1 = helper.unwrap_atom(sub) if len(s1) >= stoplength or len(s1) < startlength: @@ -83,12 +83,12 @@ if b < 0: break start = b + 1 - before.unify(term.Number(b), engine.heap) - after.unify(term.Number(len(s) - len(s1) - b), engine.heap) - length.unify(term.Number(len(s1)), engine.heap) + before.unify(term.Number(b), engine) + after.unify(term.Number(len(s) - len(s1) - b), engine) + length.unify(term.Number(len(s1)), engine) return continuation.call(engine, choice_point=True) except: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise except error.UnificationFailed: pass @@ -100,13 +100,13 @@ continue try: try: - before.unify(term.Number(b), engine.heap) - after.unify(term.Number(len(s) - l - b), engine.heap) - length.unify(term.Number(l), engine.heap) - sub.unify(term.Atom(s[b:b + l]), engine.heap) + before.unify(term.Number(b), engine) + after.unify(term.Number(len(s) - l - b), engine) + length.unify(term.Number(l), engine) + sub.unify(term.Atom(s[b:b + l]), engine) return continuation.call(engine, choice_point=True) except: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise except error.UnificationFailed: pass @@ -119,14 +119,14 @@ continue try: try: - before.unify(term.Number(b), engine.heap) - after.unify(term.Number(a), engine.heap) - length.unify(term.Number(l), engine.heap) - sub.unify(term.Atom(s[b:b + l]), engine.heap) + before.unify(term.Number(b), engine) + after.unify(term.Number(a), engine) + length.unify(term.Number(l), engine) + sub.unify(term.Atom(s[b:b + l]), engine) return continuation.call(engine, choice_point=True) return None except: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise except error.UnificationFailed: pass Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/control.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/control.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/control.py Wed Apr 2 02:28:39 2008 @@ -33,7 +33,7 @@ self.continuation = continuation def _call(self, engine): - next_call = self.next_call.dereference(engine.heap) + next_call = self.next_call.dereference(engine) next_call = helper.ensure_callable(next_call) return engine.call(next_call, self.continuation, choice_point=False) @@ -46,11 +46,11 @@ handles_continuation=True) def impl_or(engine, call1, call2, continuation): - oldstate = engine.heap.branch() + oldstate = engine.branch() try: return engine.call(call1, continuation) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) return engine.call(call2, continuation, choice_point=False) expose_builtin(impl_or, ";", unwrap_spec=["callable", "callable"], @@ -68,11 +68,11 @@ expose_builtin(impl_not, ["not", "\\+"], unwrap_spec=["callable"]) def impl_if(engine, if_clause, then_clause, continuation): - oldstate = engine.heap.branch() + oldstate = engine.branch() try: engine.call(if_clause) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise return engine.call(helper.ensure_callable(then_clause), continuation, choice_point=False) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/database.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/database.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/database.py Wed Apr 2 02:28:39 2008 @@ -19,11 +19,11 @@ expose_builtin(impl_abolish, "abolish", unwrap_spec=["obj"]) def impl_assert(engine, rule): - engine.add_rule(rule.getvalue(engine.heap)) + engine.add_rule(rule.getvalue(engine)) expose_builtin(impl_assert, ["assert", "assertz"], unwrap_spec=["callable"]) def impl_asserta(engine, rule): - engine.add_rule(rule.getvalue(engine.heap), end=False) + engine.add_rule(rule.getvalue(engine), end=False) expose_builtin(impl_asserta, "asserta", unwrap_spec=["callable"]) @@ -46,14 +46,14 @@ rulechain = function.rulechain while rulechain: rule = rulechain.rule - oldstate = engine.heap.branch() + oldstate = engine.branch() # standardizing apart try: - deleted_body = rule.clone_and_unify_head(engine.heap, head) + deleted_body = rule.clone_and_unify_head(engine, head) if body is not None: - body.unify(deleted_body, engine.heap) + body.unify(deleted_body, engine) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) else: if function.rulechain is rulechain: if rulechain.next is None: @@ -66,6 +66,7 @@ rulechain = rulechain.next else: raise error.UnificationFailed() +impl_retract._look_inside_me_ = False expose_builtin(impl_retract, "retract", unwrap_spec=["callable"]) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/exception.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/exception.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/exception.py Wed Apr 2 02:28:39 2008 @@ -8,29 +8,30 @@ def impl_catch(engine, goal, catcher, recover, continuation): catching_continuation = enginemod.LimitedScopeContinuation(continuation) - old_state = engine.heap.branch() + old_state = engine.branch() try: return engine.call(goal, catching_continuation) except error.CatchableError, e: if not catching_continuation.scope_active: raise - exc_term = e.term.getvalue(engine.heap) - engine.heap.revert(old_state) + exc_term = e.term.getvalue(engine) + engine.revert(old_state) d = {} - exc_term = exc_term.copy(engine.heap, d) + exc_term = exc_term.copy(engine, d) try: impl_ground(engine, exc_term) except error.UnificationFailed: raise error.UncatchableError( "not implemented: catching of non-ground terms") try: - catcher.unify(exc_term, engine.heap) + catcher.unify(exc_term, engine) except error.UnificationFailed: if isinstance(e, error.UserError): raise error.UserError(exc_term) if isinstance(e, error.CatchableError): raise error.CatchableError(exc_term) return engine.call(recover, continuation, choice_point=False) +impl_catch._look_inside_me_ = False expose_builtin(impl_catch, "catch", unwrap_spec=["callable", "obj", "callable"], handles_continuation=True) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/formatting.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/formatting.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/formatting.py Wed Apr 2 02:28:39 2008 @@ -147,10 +147,12 @@ def impl_write_term(engine, term, options): f = TermFormatter.from_option_list(engine, options) os.write(1, f.format(term)) # XXX use streams +impl_write_term._look_inside_me_ = False expose_builtin(impl_write_term, "write_term", unwrap_spec=["concrete", "list"]) def impl_nl(engine): os.write(1, "\n") # XXX use streams +impl_nl._look_inside_me_ = False expose_builtin(impl_nl, "nl", unwrap_spec=[]) def impl_write(engine, term): Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/parseraccess.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/parseraccess.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/parseraccess.py Wed Apr 2 02:28:39 2008 @@ -9,14 +9,14 @@ for prec, allops in engine.getoperations(): for form, ops in allops: for op in ops: - oldstate = engine.heap.branch() + oldstate = engine.branch() try: - precedence.unify(term.Number(prec), engine.heap) - typ.unify(term.Atom.newatom(form), engine.heap) - name.unify(term.Atom(op), engine.heap) + precedence.unify(term.Number(prec), engine) + typ.unify(term.Atom.newatom(form), engine) + name.unify(term.Atom(op), engine) return continuation.call(engine, choice_point=True) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise error.UnificationFailed() expose_builtin(impl_current_op, "current_op", unwrap_spec=["obj", "obj", "obj"], handles_continuation=True) @@ -53,6 +53,7 @@ else: operations.append((precedence, [(typ, [name])])) engine.parser = parsing.make_parser_at_runtime(engine.operations) +impl_op._look_inside_me_ = False expose_builtin(impl_op, "op", unwrap_spec=["int", "atom", "atom"]) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/register.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/register.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/register.py Wed Apr 2 02:28:39 2008 @@ -42,10 +42,10 @@ varname = "var%s" % (i, ) subargs.append(varname) if spec in ("obj", "callable", "int", "atom", "arithmetic"): - code.append(" %s = query.args[%s].dereference(engine.heap)" % + code.append(" %s = query.args[%s].dereference(engine)" % (varname, i)) elif spec in ("concrete", "list"): - code.append(" %s = query.args[%s].getvalue(engine.heap)" % + code.append(" %s = query.args[%s].getvalue(engine)" % (varname, i)) if spec in ("int", "atom", "arithmetic", "list"): code.append( Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/source.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/source.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/source.py Wed Apr 2 02:28:39 2008 @@ -28,6 +28,7 @@ finally: os.close(fd) engine.runstring(file_content) +impl_consult._look_inside_me_ = False expose_builtin(impl_consult, "consult", unwrap_spec=["obj"]) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/termconstruction.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/termconstruction.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/termconstruction.py Wed Apr 2 02:28:39 2008 @@ -7,11 +7,11 @@ def impl_functor(engine, t, functor, arity): if helper.is_atomic(t): - functor.unify(t, engine.heap) - arity.unify(term.Number(0), engine.heap) + functor.unify(t, engine) + arity.unify(term.Number(0), engine) elif isinstance(t, term.Term): - functor.unify(term.Atom(t.name), engine.heap) - arity.unify(term.Number(len(t.args)), engine.heap) + functor.unify(term.Atom(t.name), engine) + arity.unify(term.Number(len(t.args)), engine) elif isinstance(t, term.Var): if isinstance(functor, term.Var): error.throw_instantiation_error() @@ -21,12 +21,12 @@ else: functor = helper.ensure_atomic(functor) if a == 0: - t.unify(helper.ensure_atomic(functor), engine.heap) + t.unify(helper.ensure_atomic(functor), engine) else: name = helper.unwrap_atom(functor) t.unify( term.Term(name, [term.Var() for i in range(a)]), - engine.heap) + engine) expose_builtin(impl_functor, "functor", unwrap_spec=["obj", "obj", "obj"]) def impl_arg(engine, first, second, third, continuation): @@ -39,13 +39,13 @@ if isinstance(first, term.Var): for i in range(len(second.args)): arg = second.args[i] - oldstate = engine.heap.branch() + oldstate = engine.branch() try: - third.unify(arg, engine.heap) - first.unify(term.Number(i + 1), engine.heap) + third.unify(arg, engine) + first.unify(term.Number(i + 1), engine) return continuation.call(engine, choice_point=True) except error.UnificationFailed: - engine.heap.revert(oldstate) + engine.revert(oldstate) raise error.UnificationFailed() elif isinstance(first, term.Number): num = first.num @@ -56,7 +56,7 @@ if num > len(second.args): raise error.UnificationFailed() arg = second.args[num - 1] - third.unify(arg, engine.heap) + third.unify(arg, engine) else: error.throw_type_error("integer", first) return continuation.call(engine, choice_point=False) @@ -71,9 +71,9 @@ l = [first] u1 = helper.wrap_list(l) if not isinstance(second, term.Var): - u1.unify(second, engine.heap) + u1.unify(second, engine) else: - u1.unify(second, engine.heap) + u1.unify(second, engine) else: if isinstance(second, term.Var): error.throw_instantiation_error() @@ -82,13 +82,15 @@ head = l[0] if not isinstance(head, term.Atom): error.throw_type_error("atom", head) - term.Term(head.name, l[1:]).unify(first, engine.heap) + term.Term(head.name, l[1:]).unify(first, engine) expose_builtin(impl_univ, "=..", unwrap_spec=["obj", "obj"]) def impl_copy_term(engine, interm, outterm): d = {} - copy = interm.copy(engine.heap, d) - outterm.unify(copy, engine.heap) + copy = interm.copy(engine, d) + outterm.unify(copy, engine) +impl_copy_term._look_inside_me_ = False expose_builtin(impl_copy_term, "copy_term", unwrap_spec=["obj", "obj"]) + Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/unify.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/unify.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/builtin/unify.py Wed Apr 2 02:28:39 2008 @@ -8,21 +8,21 @@ # comparison and unification of terms def impl_unify(engine, obj1, obj2): - obj1.unify(obj2, engine.heap) + obj1.unify(obj2, engine) expose_builtin(impl_unify, "=", unwrap_spec=["raw", "raw"]) def impl_unify_with_occurs_check(engine, obj1, obj2): - obj1.unify(obj2, engine.heap, occurs_check=True) + obj1.unify(obj2, engine, occurs_check=True) expose_builtin(impl_unify_with_occurs_check, "unify_with_occurs_check", unwrap_spec=["raw", "raw"]) def impl_does_not_unify(engine, obj1, obj2): try: - branch = engine.heap.branch() + branch = engine.branch() try: - obj1.unify(obj2, engine.heap) + obj1.unify(obj2, engine) finally: - engine.heap.revert(branch) + engine.revert(branch) except error.UnificationFailed: return raise error.UnificationFailed() @@ -37,7 +37,7 @@ ("ge", "@>=", "!= -1")]: exec py.code.Source(""" def impl_standard_comparison_%s(engine, obj1, obj2): - c = term.cmp_standard_order(obj1, obj2, engine.heap) + c = term.cmp_standard_order(obj1, obj2, engine) if not c %s: raise error.UnificationFailed()""" % (ext, python)).compile() expose_builtin(globals()["impl_standard_comparison_%s" % (ext, )], prolog, Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/arithmetic.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/arithmetic.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/arithmetic.py Wed Apr 2 02:28:39 2008 @@ -85,6 +85,7 @@ code.end_block("else") code.emit("return norm_float(term.Float(%s))" % pattern) code.end_block("def") + code.emit("general_%s._look_inside_me_ = False" % (name, )) miniglobals = globals().copy() exec py.code.Source(code.tostring()).compile() in miniglobals result = miniglobals["prolog_" + name] @@ -95,7 +96,6 @@ def eval_arithmetic(engine, query): return query.eval_arithmetic(engine) -eval_arithmetic._look_inside_me_ = True def norm_float(obj): v = obj.floatval Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/choice.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/choice.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/choice.py Wed Apr 2 02:28:39 2008 @@ -29,7 +29,7 @@ def __init__(self, engine, continuation, stop_cut=False): self._init_current() self.engine = engine - self.oldstate = engine.heap.branch() + self.oldstate = engine.branch() self.continuation = continuation self.stop_cut = stop_cut self.any_choice = True @@ -50,7 +50,7 @@ else: self.exception = e except UnificationFailed: - self.engine.heap.revert(self.oldstate) + self.engine.revert(self.oldstate) if last: raise return Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py Wed Apr 2 02:28:39 2008 @@ -38,38 +38,39 @@ self.scope_active = False return self.continuation.call(engine, choice_point=False) -class Heap(object): - def __init__(self): +class TrailChunk(object): + def __init__(self, prev=None): self.trail = [] + self.prev = prev + +class Heap(object): + _mixin_ = True + def reset(self): - self.trail = [] - self.last_branch = 0 + self.current_chunk = TrailChunk() + __init__ = reset def add_trail(self, var): - self.trail.append((var, var.binding)) + self.current_chunk.trail.append((var, var.binding)) def branch(self): - return len(self.trail) + result = self.current_chunk + self.current_chunk = TrailChunk(self.current_chunk) + return result def revert(self, state): - trails = state - for i in range(len(self.trail) - 1, trails - 1, -1): - var, val = self.trail[i] - var.binding = val - del self.trail[trails:] + curr = self.current_chunk + while curr is not state: + for i in range(len(curr.trail) - 1, -1, -1): + var, val = curr.trail[i] + var.binding = val + curr = curr.prev + self.current_chunk = TrailChunk(curr) def discard(self, state): pass #XXX for now - def maxvar(self): - XXX - return self.needed_vars - - def newvar(self): - result = Var(self) - return result - class LinkedRules(object): _immutable_ = True def __init__(self, rule, next=None): @@ -134,15 +135,14 @@ last.next = rulechain.next -class Engine(object): +class Engine(Heap): + _virtualizable_ = True + def __init__(self): - self.heap = Heap() + self.reset() self.signature2function = {} self.parser = None self.operations = None - #XXX circular imports hack - from pypy.lang.prolog.builtin import builtins_list - globals()['unrolling_builtins'] = unrolling_iterable(builtins_list) def add_rule(self, rule, end=True): from pypy.lang.prolog import builtin @@ -199,30 +199,39 @@ def _call(self, query, continuation): signature = query.signature - from pypy.lang.prolog.builtin import builtins - builtins = hint(builtins, deepfreeze=True) signature = hint(signature, promote=True) - for bsig, builtin in unrolling_builtins: - if signature == bsig: - return builtin.call(self, query, continuation) + builtin = _jit_builtin_lookup(signature) + if builtin is not None: + return builtin.call(self, query, continuation) return self.user_call(query, continuation, choice_point=False) - def main_loop(self, where, query, continuation, rule=None): + def jit_main_loop(self, where, query, continuation, rule=None): next = (DONE, None, None, None) - hint(where, concrete=True) - hint(rule, concrete=True) while 1: + myjitdriver.jit_merge_point(where=where, continuation=continuation, + query=query, rule=rule, _self=self, + next=next) + hint(where, concrete=True) + hint(rule, concrete=True) if where == DONE: return next - next = self.dispatch_bytecode(where, query, continuation, rule) + next = self.dispatch_bytecode(next, where, query, continuation, rule) where, query, continuation, rule = next where = hint(where, promote=True) + rule = hint(rule, promote=True) - def dispatch_bytecode(self, where, query, continuation, rule): + def main_loop(self, where, query, continuation, rule=None): + return self.jit_main_loop(where, query, continuation, rule) + main_loop._look_inside_me_ = False + + def dispatch_bytecode(self, next, where, query, continuation, rule): if where == CALL: next = self._call(query, continuation) elif where == TRY_RULE: - rule = hint(rule, promote=True) + # XXX seems a slightly strange place to put it + myjitdriver.can_enter_jit(where=where, continuation=continuation, + query=query, rule=rule, _self=self, + next=next) next = self._try_rule(rule, query, continuation) elif where == USER_CALL: next = self._user_call(query, continuation) @@ -233,13 +242,10 @@ raise Exception("unknown bytecode") return next - @purefunction - def _jit_lookup(self, signature): + def _lookup(self, signature): signature2function = self.signature2function - function = signature2function.get(signature, None) - if function is None: - signature2function[signature] = function = Function() - return function + signature2function = hint(signature2function, promote=True) + return _jit_lookup(signature2function, signature) def user_call(self, query, continuation, choice_point=True): if not choice_point: @@ -248,21 +254,21 @@ def _user_call(self, query, continuation): signature = hint(query.signature, promote=True) - function = self._jit_lookup(signature) + function = self._lookup(signature) startrulechain = function.rulechain startrulechain = hint(startrulechain, promote=True) if startrulechain is None: error.throw_existence_error( "procedure", query.get_prolog_signature()) - unify_hash = query.unify_hash_of_children(self.heap) + unify_hash = query.unify_hash_of_children(self) rulechain = startrulechain.find_applicable_rule(unify_hash) if rulechain is None: # none of the rules apply raise UnificationFailed() rule = rulechain.rule rulechain = rulechain.next - oldstate = self.heap.branch() + oldstate = self.branch() while 1: if rulechain is not None: rulechain = rulechain.find_applicable_rule(unify_hash) @@ -274,10 +280,10 @@ continuation = LimitedScopeContinuation(continuation) try: result = self.try_rule(rule, query, continuation) - self.heap.discard(oldstate) + self.discard(oldstate) return result except UnificationFailed: - self.heap.revert(oldstate) + self.revert(oldstate) except CutException, e: if continuation.scope_active: return self.continue_after_cut(e.continuation, @@ -291,11 +297,11 @@ result = self.try_rule(rule, query, continuation, choice_point=choice_point, inline=inline) - self.heap.discard(oldstate) + self.discard(oldstate) return result except UnificationFailed: assert choice_point - self.heap.revert(oldstate) + self.revert(oldstate) rule = rulechain.rule rulechain = rulechain.next @@ -307,9 +313,8 @@ def _try_rule(self, rule, query, continuation): rule = hint(rule, deepfreeze=True) - hint(self, concrete=True) # standardizing apart - nextcall = rule.clone_and_unify_head(self.heap, query) + nextcall = rule.clone_and_unify_head(self, query) if nextcall is not None: return self.call(nextcall, continuation, choice_point=False) else: @@ -338,5 +343,24 @@ return self.operations + at purefunction +def _jit_builtin_lookup(signature): + from pypy.lang.prolog.builtin import builtins + return builtins.get(signature, None) + + + at purefunction +def _jit_lookup(signature2function, signature): + function = signature2function.get(signature, None) + if function is None: + signature2function[signature] = function = Function() + return function + +class MyJitDriver(JitDriver): + reds = ['continuation', 'query', 'next', '_self'] + greens = ['where', 'rule'] + + def on_enter_jit(self, invariant, reds, where, rule): + reds._self.branch() - +myjitdriver = MyJitDriver() Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/helper.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/helper.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/helper.py Wed Apr 2 02:28:39 2008 @@ -25,7 +25,6 @@ def is_callable(var, engine): return isinstance(var, term.Callable) -is_callable._look_inside_me_ = True def ensure_callable(var): if isinstance(var, term.Var): @@ -34,7 +33,6 @@ return var else: error.throw_type_error("callable", var) -ensure_callable._look_inside_me_ = True def unwrap_int(obj): if isinstance(obj, term.Number): @@ -49,7 +47,6 @@ if isinstance(obj, term.Atom): return obj.name error.throw_type_error('atom', obj) -unwrap_atom._look_inside_me_ = True def unwrap_predicate_indicator(predicate): if not isinstance(predicate, term.Term): @@ -79,6 +76,10 @@ elif isinstance(obj, term.Number): return str(obj.num) elif isinstance(obj, term.Float): - return str(obj.floatval) + return convert_float_to_str(obj) error.throw_type_error("atomic", obj) + +def convert_float_to_str(obj): + return str(obj.floatval) +convert_float_to_str._look_inside_me_ = False Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/interactive.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/interactive.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/interactive.py Wed Apr 2 02:28:39 2008 @@ -59,7 +59,7 @@ f = TermFormatter(engine, quoted=True, max_depth=10) vars = var_to_pos.items() vars.sort() - heap = engine.heap + heap = engine for var, real_var in vars: if var.startswith("_"): continue Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/portal.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/portal.py Wed Apr 2 02:28:39 2008 @@ -1,66 +1,20 @@ from pypy.jit.hintannotator.policy import ManualGraphPolicy from pypy.lang.prolog.interpreter import term, engine, helper from pypy.translator.translator import graphof -from pypy.annotation.specialize import getuniquenondirectgraph forbidden_modules = {'pypy.lang.prolog.interpreter.parser': True, } -good_modules = {'pypy.lang.prolog.builtin.control': True, - 'pypy.lang.prolog.builtin.register': True - } - - -PORTAL = engine.Engine.portal_try_rule.im_func class PyrologHintAnnotatorPolicy(ManualGraphPolicy): - PORTAL = PORTAL + hotpath = True + def look_inside_graph_of_module(self, graph, func, mod): if mod in forbidden_modules: return False - if mod in good_modules: - return True - if mod.startswith("pypy.lang.prolog"): - return False return True - def fill_timeshift_graphs(self): - import pypy - for cls in [term.Var, term.Term, term.Number, term.Atom]: - self.seegraph(cls.copy) - self.seegraph(cls.__init__) - self.seegraph(cls.copy_and_unify) - for cls in [term.Term, term.Number, term.Atom]: - self.seegraph(cls.copy_and_basic_unify) - self.seegraph(cls.dereference) - self.seegraph(cls.copy_and_basic_unify) - for cls in [term.Var, term.Term, term.Number, term.Atom]: - self.seegraph(cls.get_unify_hash) - self.seegraph(cls.eval_arithmetic) - for cls in [term.Callable, term.Atom, term.Term]: - self.seegraph(cls.get_prolog_signature) - self.seegraph(cls.unify_hash_of_children) - self.seegraph(PORTAL) - self.seegraph(engine.Heap.newvar) - self.seegraph(term.Rule.clone_and_unify_head) - self.seegraph(engine.Engine.call) - self.seegraph(engine.Engine._call) - self.seegraph(engine.Engine.user_call) - self.seegraph(engine.Engine._user_call) - self.seegraph(engine.Engine.try_rule) - self.seegraph(engine.Engine._try_rule) - self.seegraph(engine.Engine.main_loop) - self.seegraph(engine.Engine.dispatch_bytecode) - self.seegraph(engine.LinkedRules.find_applicable_rule) - for method in "branch revert discard newvar extend maxvar".split(): - self.seegraph(getattr(engine.Heap, method)) - self.seegraph(engine.Continuation.call) - for cls in [engine.Continuation, engine.LimitedScopeContinuation, - pypy.lang.prolog.builtin.control.AndContinuation]: - self.seegraph(cls._call) - for function in "".split(): - self.seegraph(getattr(helper, function)) def get_portal(drv): t = drv.translator Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/term.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/term.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/term.py Wed Apr 2 02:28:39 2008 @@ -78,7 +78,7 @@ __slots__ = ('binding', ) cache = {} - def __init__(self, heap=None): + def __init__(self): self.binding = None @specialize.arg(3) @@ -120,7 +120,7 @@ try: return memo[self] except KeyError: - newvar = memo[self] = heap.newvar() + newvar = memo[self] = Var() return newvar def copy_and_unify(self, other, heap, memo): @@ -160,7 +160,7 @@ return self is other def eval_arithmetic(self, engine): - self = self.dereference(engine.heap) + self = self.dereference(engine) if isinstance(self, Var): error.throw_instantiation_error() return self.eval_arithmetic(engine) @@ -318,6 +318,8 @@ TAG = tag() STANDARD_ORDER = 2 _immutable_ = True + + floatval = 0.0 def __init__(self, floatval): self.floatval = floatval @@ -342,6 +344,7 @@ m, e = math.frexp(self.floatval) m = intmask(int(m / 2 * 2 ** (32 - TAGBITS))) return intmask(m << TAGBITS | self.TAG) + get_unify_hash._look_inside_me_ = False def __str__(self): return repr(self.floatval) @@ -387,9 +390,6 @@ # helper functions for various Term methods -def _clone(obj, offset): - return obj.clone(offset) - def _getvalue(obj, heap): return obj.getvalue(heap) @@ -538,6 +538,7 @@ memo = {} h2 = self.head hint(h2, concrete=True) + h2 = hint(h2, deepfreeze=True) if isinstance(h2, Term): assert isinstance(head, Term) i = 0 @@ -604,3 +605,4 @@ elif isinstance(obj2, Float): return rcmp(obj1.floatval, obj2.floatval) assert 0 +cmp_standard_order._look_inside_me_ = False Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/dont_test_translate.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/dont_test_translate.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/dont_test_translate.py Wed Apr 2 02:28:39 2008 @@ -39,7 +39,7 @@ def run(): e.run(t1) e.run(t2) - v0 = e.heap.getvar(0) + v0 = e.getvar(0) if isinstance(v0, Atom): return v0.name return "no!" Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_engine.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_engine.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_engine.py Wed Apr 2 02:28:39 2008 @@ -12,7 +12,7 @@ """) t, vars = get_query_and_vars("f(X).") e.run(t) - assert vars['X'].dereference(e.heap).name == "a" + assert vars['X'].dereference(e).name == "a" def test_and(): e = get_engine(""" @@ -24,7 +24,7 @@ e.run(parse_query_term("f(a, c).")) t, vars = get_query_and_vars("f(X, c).") e.run(t) - assert vars['X'].dereference(e.heap).name == "a" + assert vars['X'].dereference(e).name == "a" def test_and_long(): e = get_engine(""" @@ -56,7 +56,7 @@ e.run(parse_query_term("num(succ(0)).")) t, vars = get_query_and_vars("num(X).") e.run(t) - assert vars['X'].dereference(e.heap).num == 0 + assert vars['X'].dereference(e).num == 0 e.run(parse_query_term("add(0, 0, 0).")) py.test.raises(UnificationFailed, e.run, parse_query_term(""" add(0, 0, succ(0)).""")) @@ -93,7 +93,7 @@ """) t, vars = get_query_and_vars("f(a, b, Z).") e.run(t) - assert vars['Z'].dereference(e.heap).name == "a" + assert vars['Z'].dereference(e).name == "a" f = collect_all(e, "X = 1; X = 2.") assert len(f) == 2 Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_jit.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_jit.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_jit.py Wed Apr 2 02:28:39 2008 @@ -1,34 +1,42 @@ import py -py.test.skip("port me") -from pypy.jit.timeshifter.test.test_portal import PortalTest, P_NOVIRTUAL +from pypy.rlib.debug import ll_assert +from pypy.jit.rainbow.test import test_hotpath from pypy.lang.prolog.interpreter import portal from pypy.lang.prolog.interpreter import engine, term from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine +py.test.skip("fix me") POLICY = portal.PyrologHintAnnotatorPolicy() - -class TestPortal(PortalTest): +class TestPortal(test_hotpath.HotPathTest): small = False def test_simple(self): - e = get_engine(""" - f(x, y). - f(a(X), b(b(Y))) :- f(X, Y). - """) - X = e.heap.newvar() - Y = e.heap.newvar() + X = term.Var() + Y = term.Var() larger = term.Term( - "f", [term.Term("a", [X]), term.Term("b", [term.Term("b", [Y])])]) + "h", [term.Number(100), X]) + e = get_engine(""" + f(X) :- h(X, _). + h(0, foo). + h(X, Y) :- Z is X - 1, h(Z, Y). + """) + signature2function = e.signature2function + parser = e.parser + operations = e.operations def main(n): - e.heap.reset() + # XXX workaround for problems with prebuilt virtualizables + e = engine.Engine() + e.signature2function = signature2function + e.parser = parser + e.operations = operations if n == 0: - e.call(term.Term("f", [X, Y])) - return isinstance(X.dereference(e.heap), term.Atom) + e.call(term.Term("h", [term.Number(2), Y])) + return isinstance(Y.dereference(e), term.Atom) if n == 1: e.call(larger) - return isinstance(X.dereference(e.heap), term.Atom) + return isinstance(Y.dereference(e), term.Atom) else: return False @@ -38,16 +46,10 @@ assert res == True - res = self.timeshift_from_portal(main, portal.PORTAL, - [1], policy=POLICY, - backendoptimize=True, - inline=0.0) + res = self.run(main, [1], threshold=2, policy=POLICY) assert res == True - res = self.timeshift_from_portal(main, portal.PORTAL, - [0], policy=POLICY, - backendoptimize=True, - inline=0.0) + res = self.run(main, [0], threshold=2, policy=POLICY) assert res == True def test_and(self): @@ -59,13 +61,13 @@ f(X) :- b(X), a(X). f(X) :- fail. """) - X = e.heap.newvar() + X = term.Var() def main(n): - e.heap.reset() + e.reset() if n == 0: e.call(term.Term("h", [X])) - return isinstance(X.dereference(e.heap), term.Atom) + return isinstance(X.dereference(e), term.Atom) else: return False @@ -84,19 +86,19 @@ append([X|Y], L, [X|Z]) :- append(Y, L, Z). """) t = parse_query_term("append([a, b, c], [d, f, g], X).") - X = e.heap.newvar() + X = term.Var() def main(n): if n == 0: e.call(t) - return isinstance(X.dereference(e.heap), term.Term) + return isinstance(X.dereference(e), term.Term) else: return False res = main(0) assert res == True - e.heap.reset() + e.reset() res = self.timeshift_from_portal(main, portal.PORTAL, [0], policy=POLICY, backendoptimize=True, @@ -111,13 +113,13 @@ f(X, b) :- g(X). g(b). """) - X = e.heap.newvar() + X = term.Var() def main(n): - e.heap.reset() + e.reset() if n == 0: e.call(term.Term("h", [X])) - return isinstance(X.dereference(e.heap), term.Atom) + return isinstance(X.dereference(e), term.Atom) else: return False @@ -132,16 +134,10 @@ assert res == True def test_loop(self): - e = get_engine(""" - f(X) :- h(X, _). - f(50). - h(0, _). - h(X, Y) :- Y is X - 1, h(Y, _). - """) num = term.Number(50) def main(n): - e.heap.reset() + e.reset() if n == 0: e.call(term.Term("f", [num])) return True Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_parsing.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_parsing.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_parsing.py Wed Apr 2 02:28:39 2008 @@ -37,10 +37,10 @@ term = parse_query_term( """add_numeral(succ(succ(null)), succ(succ(null)), X).""") e.run(term) - var = Var(0).getvalue(e.heap) - print var, e.heap + var = Var().getvalue(e) + print var, e # does not raise - var.unify(four, e.heap) + var.unify(four, e) term = parse_query_term( """greater_than(succ(succ(succ(null))), succ(succ(null))).""") e.run(term) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_unification.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_unification.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/test_unification.py Wed Apr 2 02:28:39 2008 @@ -60,9 +60,9 @@ e.add_rule(Term("f", [X, X])) e.add_rule(Term(":-", [Term("f", [X, Y]), Term("f", [Y, X])])) - X = e.heap.newvar() + X = Var() e.run(Term("f", [Atom.newatom("b"), X])) - assert X.dereference(e.heap).name == "b" + assert X.dereference(e).name == "b" e.run(Term("f", [Atom.newatom("b"), Atom.newatom("a")])) Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/tool.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/tool.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/test/tool.py Wed Apr 2 02:28:39 2008 @@ -9,7 +9,7 @@ terms, vars = e.parse(query) term, = terms e.run(term) - return dict([(name, var.dereference(e.heap)) + return dict([(name, var.dereference(e)) for name, var in vars.iteritems()]) def assert_false(query, e=None): if e is None: @@ -27,7 +27,7 @@ self.vars = vars def _call(self, engine): - self.heaps.append(dict([(name, var.dereference(engine.heap)) + self.heaps.append(dict([(name, var.dereference(engine)) for name, var in self.vars.iteritems()])) print "restarting computation" raise UnificationFailed Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/translatedmain.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/translatedmain.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/translatedmain.py Wed Apr 2 02:28:39 2008 @@ -43,7 +43,7 @@ for var, real_var in var_to_pos.iteritems(): if var.startswith("_"): continue - val = f.format(real_var.getvalue(engine.heap)) + val = f.format(real_var.getvalue(engine)) write("%s = %s\n" % (var, val)) def getch(): From fijal at codespeak.net Wed Apr 2 04:23:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 04:23:49 +0200 (CEST) Subject: [pypy-svn] r53244 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080402022349.2B8F6168410@codespeak.net> Author: fijal Date: Wed Apr 2 04:23:47 2008 New Revision: 53244 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: steal from i386 simplified version (we always have default case by now) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Wed Apr 2 04:23:47 2008 @@ -263,24 +263,15 @@ return targetbuilder def _add_case(self, gv_case, targetbuilder): - # XXX this code needs to be simplified, now that we always - # have a default case start = self.nextfreepos end = self.endfreepos mc = self.rgenop.InMemoryCodeBuilder(start, end) mc.CMP(eax, gv_case.operand(None)) self._je_key = targetbuilder.come_from(mc, 'JE', self._je_key) pos = mc.tell() - 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 = self.rgenop.InMemoryCodeBuilder(illegal_start, end) - illegal_mc.JMP(rel32(ud2_addr)) + assert self.defaultcaseaddr != 0 + self.default_case_key = self.default_case_builder.come_from( + mc, 'JMP', self.default_case_key) mc.done() self._je_key = 0 self.nextfreepos = pos From fijal at codespeak.net Wed Apr 2 04:24:52 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 04:24:52 +0200 (CEST) Subject: [pypy-svn] r53245 - in pypy/branch/jit-hotpath/pypy/jit/codegen: . ppc ppc/test test Message-ID: <20080402022452.0B417168410@codespeak.net> Author: fijal Date: Wed Apr 2 04:24:52 2008 New Revision: 53245 Added: pypy/branch/jit-hotpath/pypy/jit/codegen/emit_moves.py - copied unchanged from r53202, pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/emit_moves.py pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py (contents, props changed) Removed: pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/emit_moves.py pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/test/test_emit_moves.py Log: Move emit_moves one level up, for more general use Added: pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py ============================================================================== --- (empty file) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py Wed Apr 2 04:24:52 2008 @@ -0,0 +1,99 @@ +import py +from pypy.jit.codegen.ppc.emit_moves import emit_moves, emit_moves_safe + +class TheHeap(object): + def __init__(self, locs): + self.data = {} + for i in range(locs): + self.data[i] = i + self.numlocs = locs + def emit_move(self, tar, src): + self.data[tar] = self.data[src] + def create_fresh_location(self): + self.numlocs += 1 + return self.numlocs-1 + +def test_simple_cycle(): + heap = TheHeap(2) + tar2src = {'A':'b', 'B':'a'} + tar2loc = {'A':0, 'B':1} + src2loc = {'a':0, 'b':1} + assert heap.data[0] == 0 + assert heap.data[1] == 1 + emit_moves(heap, tar2src.keys(), tar2src, tar2loc, src2loc) + assert heap.data[0] == 1 + assert heap.data[1] == 0 + assert heap.numlocs == 3 # only creates 1 extra loc + +def test_cycle_3(): + heap = TheHeap(3) + tar2src = {'A':'b', 'B':'c', 'C':'a'} + tar2loc = {'A':0, 'B':1, 'C':2} + src2loc = {'a':0, 'b':1, 'c':2} + assert heap.data[0] == 0 + assert heap.data[1] == 1 + assert heap.data[2] == 2 + emit_moves(heap, tar2src.keys(), tar2src, tar2loc, src2loc) + assert heap.data[0] == 1 + assert heap.data[1] == 2 + assert heap.data[2] == 0 + assert heap.numlocs == 4 # only creates 1 extra loc + +def test_dag(): + heap = TheHeap(3) + tar2src = {'A':'a', 'B':'b'} + tar2loc = {'A':0, 'B':1} + src2loc = {'a':1, 'b':2} + assert heap.data[0] == 0 + assert heap.data[1] == 1 + assert heap.data[2] == 2 + emit_moves(heap, tar2src.keys(), tar2src, tar2loc, src2loc) + assert heap.data[0] == 1 + assert heap.data[1] == 2 + assert heap.data[2] == 2 + assert heap.numlocs == 3 # only creates 1 extra loc + +def test_one_to_many(): + heap = TheHeap(4) + tar2src = {'A':'a', 'B':'b', 'C':'a'} + tar2loc = {'A':2, 'B':1, 'C':3} + src2loc = {'a':1, 'b':0} + assert heap.data[0] == 0 # b + assert heap.data[1] == 1 # a + assert heap.data[2] == 2 + assert heap.data[3] == 3 + emit_moves(heap, ['B', 'A', 'C'], tar2src, tar2loc, src2loc) + assert heap.data[1] == 0 # B + assert heap.data[2] == 1 # A + assert heap.data[3] == 1 # C + +def test_random(): + for _ in range(20): + import random + NVAR = random.randrange(1000) + heap = TheHeap(NVAR) + varlist = range(NVAR) + tar2src = {} + src2loc = {} + tar2loc = {} + for i in varlist: + tar2src[i] = random.randrange(NVAR) + srcs = list(dict.fromkeys(tar2src.values())) + srclocs = srcs[:] + random.shuffle(srclocs) + for j, k in zip(srcs, srclocs): + src2loc[j] = k + varlist2 = varlist[:] + random.shuffle(varlist2) + for i, j in zip(varlist, varlist2): + tar2loc[i] = j + for i in range(10): + random.shuffle(varlist) + heap1 = TheHeap(NVAR) + emit_moves(heap1, varlist, + tar2src.copy(), tar2loc.copy(), src2loc.copy()) + heap2 = TheHeap(NVAR) + emit_moves_safe(heap2, varlist, + tar2src.copy(), tar2loc.copy(), src2loc.copy()) + for i in range(NVAR): + assert heap1.data[i] == heap2.data[i] From fijal at codespeak.net Wed Apr 2 04:25:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 04:25:35 +0200 (CEST) Subject: [pypy-svn] r53246 - pypy/branch/jit-hotpath/pypy/jit/codegen/ppc Message-ID: <20080402022535.EFF1E168410@codespeak.net> Author: fijal Date: Wed Apr 2 04:25:35 2008 New Revision: 53246 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/rgenop.py Log: fix import Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/rgenop.py Wed Apr 2 04:25:35 2008 @@ -13,7 +13,7 @@ from pypy.jit.codegen.ppc.instruction import rSP, rFP, rSCRATCH, gprs from pypy.jit.codegen.ppc import instruction as insn from pypy.jit.codegen.ppc.regalloc import RegisterAllocation -from pypy.jit.codegen.ppc.emit_moves import emit_moves, emit_moves_safe +from pypy.jit.codegen.emit_moves import emit_moves, emit_moves_safe from pypy.jit.codegen.ppc.ppcgen.rassemblermaker import make_rassembler from pypy.jit.codegen.ppc.ppcgen.ppc_assembler import MyPPCAssembler From fijal at codespeak.net Wed Apr 2 04:26:16 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 04:26:16 +0200 (CEST) Subject: [pypy-svn] r53247 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080402022616.AC128168410@codespeak.net> Author: fijal Date: Wed Apr 2 04:26:16 2008 New Revision: 53247 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py Log: fix import Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py Wed Apr 2 04:26:16 2008 @@ -1,5 +1,5 @@ import py -from pypy.jit.codegen.ppc.emit_moves import emit_moves, emit_moves_safe +from pypy.jit.codegen.emit_moves import emit_moves, emit_moves_safe class TheHeap(object): def __init__(self, locs): From fijal at codespeak.net Wed Apr 2 05:23:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 05:23:09 +0200 (CEST) Subject: [pypy-svn] r53248 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080402032309.24818168412@codespeak.net> Author: fijal Date: Wed Apr 2 05:23:08 2008 New Revision: 53248 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py Log: Some minor fixes. Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 05:23:08 2008 @@ -239,6 +239,9 @@ del stack[to_cut:] stack.append(W_List(list_w)) + def __repr__(self): + return 'LOAD_LIST %d' % (self.counter,) + class LOAD_FUNCTION(Opcode): def __init__(self, funcobj): self.funcobj = funcobj Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Wed Apr 2 05:23:08 2008 @@ -557,7 +557,7 @@ return obj.propdict[identifier].value except KeyError: pass - raise Exception("stuff") + raise Exception("XXX shall never land here, fix") #return W_Reference(identifier) def global_context(w_global): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Wed Apr 2 05:23:08 2008 @@ -212,26 +212,6 @@ bytecode.emit('STORE_MEMBER' + self._get_name()) class StuffAssignment(Expression): - def __init__(self, pos, left, right, operand): - self.pos = pos - # check the sanity of lefthandside - if isinstance(left, Identifier): - self.identifier = left.name - self.single_assignement = True - elif isinstance(left, Member): - import pdb - pdb.set_trace() - self.lefthandside = left - self.single_assignement = False - self.right = right - self.operand = operand - - def emit(self, bytecode): - op = self.operand - if op == '==': - bytecode.emit('STORE', self.identifier) - else: - XXX def eval(self, ctx): v1 = self.left.eval(ctx) @@ -672,8 +652,6 @@ for node in self.nodes: node.emit(bytecode) - # we don't need to pop after certain instructions, let's - # list them def execute(self, ctx): for varname in self.var_decl: @@ -766,9 +744,9 @@ def emit(self, bytecode): if self.expr is not None: self.expr.emit(bytecode) + bytecode.emit('STORE', self.identifier) else: - bytecode.emit('LOAD_UNDEFINED') - bytecode.emit('STORE', self.identifier) + return True def eval(self, ctx): name = self.identifier.get_literal() @@ -797,12 +775,8 @@ def emit(self, bytecode): for node in self.nodes: - node.emit(bytecode) - - def eval(self, ctx): - for var in self.nodes: - var.eval(ctx) - return w_Undefined + if node.emit(bytecode) is None: + bytecode.emit('POP') class Variable(Statement): def __init__(self, pos, body): @@ -811,7 +785,6 @@ def emit(self, bytecode): self.body.emit(bytecode) - bytecode.emit('POP') def execute(self, ctx): return self.body.eval(ctx) Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py Wed Apr 2 05:23:08 2008 @@ -460,10 +460,16 @@ 'STORE "x"', 'POP']) + def test_var_declr(self): + self.check('x; var x;', [ + 'DECLARE_VAR "x"', + 'LOAD_VARIABLE "x"', + 'POP']) + def test_call(self): self.check('print("stuff")',[ 'LOAD_STRINGCONSTANT "stuff"', - 'LOAD_ARRAY 1', + 'LOAD_LIST 1', 'LOAD_VARIABLE "print"', 'CALL', 'POP']) From fijal at codespeak.net Wed Apr 2 05:35:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 05:35:41 +0200 (CEST) Subject: [pypy-svn] r53249 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080402033541.B308016806A@codespeak.net> Author: fijal Date: Wed Apr 2 05:35:41 2008 New Revision: 53249 Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/constants.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: * Get rid of horrible SLASH * general progress * get rid of W_Reference for good * get rid of GetValue Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Wed Apr 2 05:35:41 2008 @@ -6,6 +6,7 @@ W_PrimitiveObject from pypy.rlib.rarithmetic import r_uint, intmask, INFINITY, NAN, ovfcheck,\ isnan, isinf +from pypy.lang.js.execution import ThrowException, JsTypeError def plus(ctx, nleft, nright): if isinstance(nleft, W_String) or isinstance(nright, W_String): Modified: pypy/branch/js-refactoring/pypy/lang/js/constants.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/constants.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/constants.py Wed Apr 2 05:35:41 2008 @@ -27,4 +27,3 @@ escapedict = dict(zip(codes, escapes)) unescapedict = dict(zip(escapes, codes)) -SLASH = "\\" \ No newline at end of file Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Wed Apr 2 05:35:41 2008 @@ -152,7 +152,7 @@ def printjs(ctx, args, this): - writer(",".join([i.GetValue().ToString(ctx) for i in args])) + writer(",".join([i.ToString(ctx) for i in args])) return w_Undefined def isnanjs(ctx, args, this): Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 05:35:41 2008 @@ -1,6 +1,6 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\ - W_Array, W_PrimitiveObject, W_Reference, ActivationObject,\ + W_Array, W_PrimitiveObject, ActivationObject,\ create_object, W_Object, w_Undefined, W_Boolean, newbool,\ w_True, w_False, W_List from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException @@ -92,6 +92,8 @@ return "\n".join([repr(i) for i in self.opcodes]) def __eq__(self, list_of_opcodes): + if not isinstance(list_of_opcodes, list): + return False if len(list_of_opcodes) != len(self.opcodes): return False return all([i == j for i, j in zip(self.opcodes, list_of_opcodes)]) @@ -383,20 +385,19 @@ class BaseStoreMember(Opcode): - pass - #def eval(self, ctx, ): - # XXX + def eval(self, ctx, stack): + XXX -class STORE_MEMBER(Opcode): +class STORE_MEMBER(BaseStoreMember): pass -class STORE_MEMBER_POSTINCR(Opcode): +class STORE_MEMBER_POSTINCR(BaseStoreMember): pass -class STORE_MEMBER_PREINCR(Opcode): +class STORE_MEMBER_PREINCR(BaseStoreMember): pass -class STORE_MEMBER_SUB(Opcode): +class STORE_MEMBER_SUB(BaseStoreMember): pass class BaseStore(Opcode): @@ -544,17 +545,8 @@ args = stack.pop() if not isinstance(r1, W_PrimitiveObject): raise ThrowException(W_String("it is not a callable")) - - if isinstance(r1, W_Reference): - r6 = r1.GetBase() - else: - r6 = None - if isinstance(args, ActivationObject): - r7 = None - else: - r7 = r6 try: - res = r1.Call(ctx=ctx, args=args.tolist(), this=r7) + res = r1.Call(ctx=ctx, args=args.tolist(), this=None) except JsTypeError: raise ThrowException(W_String('it is not a function')) stack.append(res) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Wed Apr 2 05:35:41 2008 @@ -2,7 +2,7 @@ from pypy.rlib.rarithmetic import r_uint, intmask, isnan, isinf,\ ovfcheck_float_to_int from pypy.lang.js.execution import ThrowException, JsTypeError,\ - RangeError + RangeError, ReturnException class SeePage(NotImplementedError): pass @@ -29,8 +29,8 @@ return Property(name, value, True, True, True, True) class W_Root(object): - def GetValue(self): - return self + #def GetValue(self): + # return self def ToBoolean(self): return False @@ -159,10 +159,9 @@ try: #this is a hack to be compatible to spidermonkey self.Call(ctx, args, this=obj) return obj - except ExecutionReturned, e: + except ReturnException, e: return e.value - def Get(self, P): try: return self.propdict[P].value @@ -557,8 +556,7 @@ return obj.propdict[identifier].value except KeyError: pass - raise Exception("XXX shall never land here, fix") - #return W_Reference(identifier) + raise ThrowException(W_String("ReferenceError: %s is not defined" % identifier)) def global_context(w_global): assert isinstance(w_global, W_PrimitiveObject) @@ -591,36 +589,36 @@ jsproperty = Property('', w_Undefined)) return ctx -class W_Reference(W_Root): - """Reference Type""" - def __init__(self, property_name, base=None): - self.base = base - self.property_name = property_name - - def check_empty(self): - if self.base is None: - exception = "ReferenceError: %s is not defined"%(self.property_name,) - raise ThrowException(W_String(exception)) +# class W_Reference(W_Root): +# """Reference Type""" +# def __init__(self, property_name, base=None): +# self.base = base +# self.property_name = property_name + +# def check_empty(self): +# if self.base is None: +# exception = "ReferenceError: %s is not defined"%(self.property_name,) +# raise ThrowException(W_String(exception)) + +# #def GetValue(self): +# # self.check_empty() +# # return self.base.Get(self.property_name) + +# #def PutValue(self, w, ctx): +# # base = self.base +# # if base is None: +# # base = ctx.scope[-1] +# # base.Put(self.property_name, w) +# # return w - #def GetValue(self): - # self.check_empty() - # return self.base.Get(self.property_name) +# #def GetBase(self): +# # return self.base - #def PutValue(self, w, ctx): - # base = self.base - # if base is None: - # base = ctx.scope[-1] - # base.Put(self.property_name, w) - # return w +# #def GetPropertyName(self): +# # return self.property_name - #def GetBase(self): - # return self.base - - #def GetPropertyName(self): - # return self.property_name - - def __str__(self): - return "<" + str(self.base) + " -> " + str(self.property_name) + ">" +# def __str__(self): +# return "<" + str(self.base) + " -> " + str(self.property_name) + ">" def create_object(ctx, prototypename, callfunc=None, Value=w_Undefined): proto = ctx.get_global().Get(prototypename).Get('prototype') Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Wed Apr 2 05:35:41 2008 @@ -6,12 +6,12 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_Object,\ w_Undefined, W_NewBuiltin, W_String, create_object, W_List,\ - W_PrimitiveObject, W_Reference, ActivationObject, W_Array, W_Boolean,\ + W_PrimitiveObject, ActivationObject, W_Array, W_Boolean,\ w_Null, W_BaseNumber, isnull_or_undefined from pypy.rlib.parsing.ebnfparse import Symbol, Nonterminal from pypy.lang.js.execution import JsTypeError, ThrowException from pypy.lang.js.jscode import JsCode, JsFunction -from constants import unescapedict, SLASH +from constants import unescapedict from pypy.rlib.unroll import unrolling_iterable import sys @@ -205,6 +205,7 @@ self.prefix = prefix def emit(self, bytecode): + # XXX optimize this a bit if self.right is not None: self.right.emit(bytecode) bytecode.emit('LOAD_STRINGCONSTANT', self.itemname) @@ -618,11 +619,11 @@ internalstring = string[1:stop] for c in internalstring: - if last == SLASH: + if last == "\\": unescapeseq = unescapedict[last+c] temp.append(unescapeseq) c = ' ' # Could be anything - elif c != SLASH: + elif c != "\\": temp.append(c) last = c return ''.join(temp) Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Wed Apr 2 05:35:41 2008 @@ -12,7 +12,7 @@ bytecode.emit('LOAD_FLOATCONSTANT', 4) bytecode.emit('ADD') bytecode.run(ExecutionContext([W_Object()]), check_stack=False) - assert bytecode.stack[0].GetValue().ToNumber() == 6.0 + assert bytecode.stack[0].ToNumber() == 6.0 def assertp(code, prints): l = [] @@ -39,7 +39,7 @@ assert isinstance(bytecode.opcodes[-1], POP) bytecode.opcodes.pop() bytecode.run(ExecutionContext([ctx]), check_stack=False) - code_val = bytecode.stack[0].GetValue() + code_val = bytecode.stack[0] except ThrowException, excpt: code_val = excpt.exception print code_val, value From fijal at codespeak.net Wed Apr 2 05:40:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 05:40:36 +0200 (CEST) Subject: [pypy-svn] r53250 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080402034036.CD4E7168414@codespeak.net> Author: fijal Date: Wed Apr 2 05:40:36 2008 New Revision: 53250 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py Log: Basic member assignment Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 05:40:36 2008 @@ -386,7 +386,11 @@ class BaseStoreMember(Opcode): def eval(self, ctx, stack): - XXX + left = stack.pop() + elem = stack.pop() + value = stack.pop() + left.Put(elem.ToString(), value) + stack.append(left) class STORE_MEMBER(BaseStoreMember): pass From fijal at codespeak.net Wed Apr 2 05:41:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 05:41:09 +0200 (CEST) Subject: [pypy-svn] r53251 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080402034109.DE8AF168417@codespeak.net> Author: fijal Date: Wed Apr 2 05:41:09 2008 New Revision: 53251 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py Log: be explicit about that Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 05:41:09 2008 @@ -389,20 +389,25 @@ left = stack.pop() elem = stack.pop() value = stack.pop() + self.operation() left.Put(elem.ToString(), value) stack.append(left) class STORE_MEMBER(BaseStoreMember): - pass + def operation(self): + pass class STORE_MEMBER_POSTINCR(BaseStoreMember): - pass + def operation(self): + raise NotImplementedError class STORE_MEMBER_PREINCR(BaseStoreMember): - pass + def operation(self): + raise NotImplementedError class STORE_MEMBER_SUB(BaseStoreMember): - pass + def operation(self): + raise NotImplementedError class BaseStore(Opcode): def __init__(self, name): From antocuni at codespeak.net Wed Apr 2 15:22:46 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 2 Apr 2008 15:22:46 +0200 (CEST) Subject: [pypy-svn] r53253 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080402132246.3810C1684FC@codespeak.net> Author: antocuni Date: Wed Apr 2 15:22:45 2008 New Revision: 53253 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: one more test Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Wed Apr 2 15:22:45 2008 @@ -711,6 +711,23 @@ assert res == 72 self.check_insns({}) + def test_complex_struct(self): + S = self.GcStruct('S', ('n', lltype.Signed)) + PTRS = self.Ptr(S) + T = self.GcStruct('T', ('s', PTRS), ('n', lltype.Signed)) + malloc = self.malloc + + def ll_function(x, y): + t = malloc(T) + t.s = malloc(S) + t.s.n = y + t.n = x + return t.n + t.s.n + + res = self.interpret(ll_function, [20, 22]) + assert res == 42 + self.check_insns({'int_add': 1}) + def test_simple_array(self): A = lltype.GcArray(lltype.Signed, hints={'immutable': True}) @@ -792,7 +809,6 @@ def test_degenerated_before_return(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - malloc = self.malloc def ll_function(flag): t = lltype.malloc(T) From fijal at codespeak.net Wed Apr 2 18:00:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 18:00:10 +0200 (CEST) Subject: [pypy-svn] r53254 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080402160010.17071168406@codespeak.net> Author: fijal Date: Wed Apr 2 18:00:08 2008 New Revision: 53254 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: In and For Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Wed Apr 2 18:00:08 2008 @@ -33,7 +33,7 @@ '.': operations.MemberDot, '[': operations.Member, ',': operations.Comma, - #'in': operations.In, + 'in': operations.In, } UNOP_TO_CLS = { #'~': operations.BitwiseNot, Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 18:00:08 2008 @@ -319,6 +319,14 @@ def operation(ctx, left, right): return sub(ctx, left, right) +class IN(BaseBinaryOperation): + @staticmethod + def operation(ctx, left, right): + if not isinstance(right, W_Object): + raise ThrowException(W_String("TypeError")) + name = left.ToString(ctx) + return W_Boolean(right.HasProperty(name)) + class ADD(BaseBinaryOperation): @staticmethod def operation(ctx, left, right): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Wed Apr 2 18:00:08 2008 @@ -501,15 +501,8 @@ StrictEq = create_binary_op('IS') StrictNe = create_binary_op('ISNOT') -# class In(BinaryOp): -# """ -# The in operator, eg: "property in object" -# """ -# def decision(self, ctx, op1, op2): -# if not isinstance(op2, W_Object): -# raise ThrowException(W_String("TypeError")) -# name = op1.ToString(ctx) -# return W_Boolean(op2.HasProperty(name)) +In = create_binary_op('IN') + # class Delete(UnaryOp): # """ @@ -921,6 +914,19 @@ self.condition = condition self.update = update self.body = body + + def emit(self, bytecode): + self.setup.emit(bytecode) + bytecode.emit('POP') + precond = bytecode.emit_label() + finish = bytecode.prealocate_label() + self.condition.emit(bytecode) + bytecode.emit('JUMP_IF_FALSE', finish) + self.body.emit(bytecode) + self.update.emit(bytecode) + bytecode.emit('POP') + bytecode.emit('JUMP', precond) + bytecode.emit('LABEL', finish) def execute(self, ctx): self.setup.eval(ctx).GetValue() From fijal at codespeak.net Wed Apr 2 18:25:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 18:25:54 +0200 (CEST) Subject: [pypy-svn] r53255 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080402162554.9963B168515@codespeak.net> Author: fijal Date: Wed Apr 2 18:25:51 2008 New Revision: 53255 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: eval Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Wed Apr 2 18:25:51 2008 @@ -100,26 +100,26 @@ TEST = False def evaljs(ctx, args, this): - raise NotImplementedError if len(args) >= 1: if isinstance(args[0], W_String): - code = args[0] + src = args[0].strval else: return args[0] else: - code = W_String('') + src = '' try: - node = load_source(code.ToString(ctx), 'evalcode') + node = load_source(src, 'evalcode') except ParseError, e: - raise ThrowException(W_String('SintaxError: '+str(e))) - - if TEST: - try: - return node.execute(ctx) - except ThrowException, e: - return W_String("error") - else: - return node.execute(ctx) + raise ThrowException(W_String('SyntaxError: '+str(e))) + + bytecode = JsCode() + node.emit(bytecode) + # XXX awful hack, we shall have a general way of doing that + from pypy.lang.js.jscode import POP + assert isinstance(bytecode.opcodes[-1], POP) + bytecode.opcodes.pop() + bytecode.run(ctx, check_stack=False) + return bytecode.stack[-1] def parseIntjs(ctx, args, this): if len(args) < 1: Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Wed Apr 2 18:25:51 2008 @@ -928,19 +928,6 @@ bytecode.emit('JUMP', precond) bytecode.emit('LABEL', finish) - def execute(self, ctx): - self.setup.eval(ctx).GetValue() - while self.condition.eval(ctx).ToBoolean(): - try: - self.body.execute(ctx) - self.update.eval(ctx) - except ExecutionReturned, e: - if e.type == 'break': - break - elif e.type == 'continue': - self.update.eval(ctx) - continue - class Boolean(Expression): def __init__(self, pos, boolval): self.pos = pos From fijal at codespeak.net Wed Apr 2 18:39:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 18:39:09 +0200 (CEST) Subject: [pypy-svn] r53256 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080402163909.1477F16840A@codespeak.net> Author: fijal Date: Wed Apr 2 18:39:08 2008 New Revision: 53256 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: break and continue Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 18:39:08 2008 @@ -42,16 +42,44 @@ self.label_count = 0 self.has_labels = True self.stack = T() + self.startlooplabel = [] + self.endlooplabel = [] - def emit_label(self): - num = self.prealocate_label() + def emit_label(self, num = -1): + if num == -1: + num = self.prealocate_label() self.emit('LABEL', num) return num + def emit_startloop_label(self): + num = self.emit_label() + self.startlooplabel.append(num) + return num + def prealocate_label(self): num = self.label_count self.label_count += 1 - return num + return num + + def prealocate_endloop_label(self): + num = self.prealocate_label() + self.endlooplabel.append(num) + return num + + def emit_endloop_label(self, label): + self.endlooplabel.pop() + self.startlooplabel.pop() + self.emit_label(label) + + def emit_break(self): + if not self.endlooplabel: + raise ThrowError(W_String("Break outside loop")) + self.emit('JUMP', self.endlooplabel[-1]) + + def emit_continue(self): + if not self.startlooplabel: + raise ThrowError(W_String("Continue outside loop")) + self.emit('JUMP', self.startlooplabel[-1]) def emit(self, operation, *args): opcode = None Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Wed Apr 2 18:39:08 2008 @@ -290,15 +290,14 @@ self.target = target class Break(Unconditional): - def execute(self, ctx): - raise ExecutionReturned('break', None, None) - + def emit(self, bytecode): + assert self.target is None + bytecode.emit_break() class Continue(Unconditional): - def execute(self, ctx): - raise ExecutionReturned('continue', None, None) - - + def emit(self, bytecode): + assert self.target is None + bytecode.emit_continue() class Call(Expression): def __init__(self, pos, left, args): @@ -815,38 +814,23 @@ class Do(WhileBase): opcode = 'DO' - def execute(self, ctx): - try: - self.body.execute(ctx) - except ExecutionReturned, e: - if e.type == 'break': - return - elif e.type == 'continue': - pass - while self.condition.eval(ctx).ToBoolean(): - try: - self.body.execute(ctx) - except ExecutionReturned, e: - if e.type == 'break': - break - elif e.type == 'continue': - continue - def emit(self, bytecode): - startlabel = bytecode.emit_label() + startlabel = bytecode.emit_startloop_label() + end = bytecode.preallocate_endloop_label() self.body.emit(bytecode) self.condition.emit(bytecode) bytecode.emit('JUMP_IF_TRUE', startlabel) + bytecode.emit_endloop_label(end) class While(WhileBase): def emit(self, bytecode): - startlabel = bytecode.emit_label() + startlabel = bytecode.emit_startloop_label() self.condition.emit(bytecode) - endlabel = bytecode.prealocate_label() + endlabel = bytecode.prealocate_endloop_label() bytecode.emit('JUMP_IF_FALSE', endlabel) self.body.emit(bytecode) bytecode.emit('JUMP', startlabel) - bytecode.emit('LABEL', endlabel) + bytecode.emit_endloop_label(endlabel) def execute(self, ctx): while self.condition.eval(ctx).ToBoolean(): @@ -918,15 +902,15 @@ def emit(self, bytecode): self.setup.emit(bytecode) bytecode.emit('POP') - precond = bytecode.emit_label() - finish = bytecode.prealocate_label() + precond = bytecode.emit_startloop_label() + finish = bytecode.prealocate_endloop_label() self.condition.emit(bytecode) bytecode.emit('JUMP_IF_FALSE', finish) self.body.emit(bytecode) self.update.emit(bytecode) bytecode.emit('POP') bytecode.emit('JUMP', precond) - bytecode.emit('LABEL', finish) + bytecode.emit_endloop_label(finish) class Boolean(Expression): def __init__(self, pos, boolval): From antocuni at codespeak.net Wed Apr 2 19:03:37 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 2 Apr 2008 19:03:37 +0200 (CEST) Subject: [pypy-svn] r53257 - in pypy/branch/jit-hotpath/pypy/jit: codegen/llgraph rainbow rainbow/test timeshifter Message-ID: <20080402170337.80B4E1684F8@codespeak.net> Author: antocuni Date: Wed Apr 2 19:03:36 2008 New Revision: 53257 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Log: move the various test_degenerated_* to TestLLType, and write the equivalents for ootype. To make test_degenerated_at_return passing we need to erase the type of all instances to the most general superclass (ROOT excluded); I'm not sure this is 100% correct, but tests seem to pass. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py Wed Apr 2 19:03:36 2008 @@ -140,6 +140,12 @@ if TYPE is llmemory.GCREF or v.concretetype is llmemory.GCREF: lltype.cast_opaque_ptr(TYPE, v.concretetype._defl()) # sanity check opname = 'cast_opaque_ptr' + elif isinstance(TYPE, ootype.Instance): + FROMTYPE = v.concretetype + if ootype.isSubclass(FROMTYPE, TYPE): + opname = 'ooupcast' + else: + opname = 'oodowncast' else: assert v.concretetype == lltype.erasedType(TYPE) opname = 'cast_pointer' @@ -159,6 +165,14 @@ op = flowmodel.SpaceOperation("cast_pointer", [v], v2) block.operations.append(op) return v2 + elif isinstance(T, ootype.Instance): + while T._superclass is not ootype.ROOT: + T = T._superclass + v2 = flowmodel.Variable() + v2.concretetype = T + op = flowmodel.SpaceOperation("ooupcast", [v], v2) + block.operations.append(op) + return v2 return v def genop(block, opname, vars_gv, gv_RESULT_TYPE): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Wed Apr 2 19:03:36 2008 @@ -1591,6 +1591,12 @@ def serialize_op_oosetfield(self, op): return self.serialize_op_setfield_impl(op) + def serialize_op_ooupcast(self, op): + return self.serialize_op_cast_pointer(op) + + def serialize_op_oodowncast(self, op): + return self.serialize_op_cast_pointer(op) + def serialize_op_new(self, op): TYPE = op.args[0].value if TYPE.oopspec_name is not None: Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Wed Apr 2 19:03:36 2008 @@ -806,83 +806,6 @@ assert res == 7 self.check_insns({}) - def test_degenerated_before_return(self): - S = lltype.GcStruct('S', ('n', lltype.Signed)) - T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - - def ll_function(flag): - t = lltype.malloc(T) - t.s.n = 3 - s = lltype.malloc(S) - s.n = 4 - if flag: - s = t.s - s.n += 1 - return s.n * t.s.n - res = self.interpret(ll_function, [0], []) - assert res == 5 * 3 - res = self.interpret(ll_function, [1], []) - assert res == 4 * 4 - - def test_degenerated_before_return_2(self): - S = lltype.GcStruct('S', ('n', lltype.Signed)) - T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - - def ll_function(flag): - t = lltype.malloc(T) - t.s.n = 3 - s = lltype.malloc(S) - s.n = 4 - if flag: - pass - else: - s = t.s - s.n += 1 - return s.n * t.s.n - res = self.interpret(ll_function, [1], []) - assert res == 5 * 3 - res = self.interpret(ll_function, [0], []) - assert res == 4 * 4 - - def test_degenerated_at_return(self): - S = lltype.GcStruct('S', ('n', lltype.Signed)) - T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - - def ll_function(flag): - t = lltype.malloc(T) - t.n = 3.25 - t.s.n = 3 - s = lltype.malloc(S) - s.n = 4 - if flag: - s = t.s - return s - - res = self.interpret(ll_function, [0], []) - assert res.n == 4 - res = self.interpret(ll_function, [1], []) - assert res.n == 3 - - def test_degenerated_via_substructure(self): - S = lltype.GcStruct('S', ('n', lltype.Signed)) - T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - - def ll_function(flag): - t = lltype.malloc(T) - t.s.n = 3 - s = lltype.malloc(S) - s.n = 7 - if flag: - pass - else: - s = t.s - t.s.n += 1 - return s.n * t.s.n - res = self.interpret(ll_function, [1], []) - assert res == 7 * 4 - res = self.interpret(ll_function, [0], []) - assert res == 4 * 4 - def test_degenerate_with_voids(self): S = self.GcStruct('S', ('y', lltype.Void), ('x', lltype.Signed)) @@ -2064,6 +1987,84 @@ class TestLLType(SimpleTests): type_system = "lltype" + def test_degenerated_before_return(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + + def ll_function(flag): + t = lltype.malloc(T) + t.s.n = 3 + s = lltype.malloc(S) + s.n = 4 + if flag: + s = t.s + s.n += 1 + return s.n * t.s.n + res = self.interpret(ll_function, [0], []) + assert res == 5 * 3 + res = self.interpret(ll_function, [1], []) + assert res == 4 * 4 + + def test_degenerated_before_return_2(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + + def ll_function(flag): + t = lltype.malloc(T) + t.s.n = 3 + s = lltype.malloc(S) + s.n = 4 + if flag: + pass + else: + s = t.s + s.n += 1 + return s.n * t.s.n + res = self.interpret(ll_function, [1], []) + assert res == 5 * 3 + res = self.interpret(ll_function, [0], []) + assert res == 4 * 4 + + def test_degenerated_at_return(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + + def ll_function(flag): + t = lltype.malloc(T) + t.n = 3.25 + t.s.n = 3 + s = lltype.malloc(S) + s.n = 4 + if flag: + s = t.s + return s + + res = self.interpret(ll_function, [0], []) + assert res.n == 4 + res = self.interpret(ll_function, [1], []) + assert res.n == 3 + + def test_degenerated_via_substructure(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + + def ll_function(flag): + t = lltype.malloc(T) + t.s.n = 3 + s = lltype.malloc(S) + s.n = 7 + if flag: + pass + else: + s = t.s + t.s.n += 1 + return s.n * t.s.n + res = self.interpret(ll_function, [1], []) + assert res == 7 * 4 + res = self.interpret(ll_function, [0], []) + assert res == 4 * 4 + + class TestOOType(SimpleTests): type_system = "ootype" @@ -2100,13 +2101,68 @@ del insns[a] return insns + def test_degenerated_before_return(self): + S = ootype.Instance('S', ootype.ROOT, {'x': ootype.Signed}) + T = ootype.Instance('T', S, {'y': ootype.Float}) + + def ll_function(flag): + t = ootype.new(T) + t.x = 3 + s = ootype.new(S) + s.x = 4 + if flag: + s = ootype.ooupcast(S, t) + s.x += 1 + return s.x * t.x + res = self.interpret(ll_function, [0], []) + assert res == 5 * 3 + res = self.interpret(ll_function, [1], []) + assert res == 4 * 4 + + def test_degenerated_before_return_2(self): + S = ootype.Instance('S', ootype.ROOT, {'x': lltype.Signed}) + T = ootype.Instance('T', S, {'y': lltype.Float}) + + def ll_function(flag): + t = ootype.new(T) + t.x = 3 + s = ootype.new(S) + s.x = 4 + if flag: + pass + else: + s = ootype.ooupcast(S, t) + s.x += 1 + return s.x * t.x + res = self.interpret(ll_function, [1], []) + assert res == 5 * 3 + res = self.interpret(ll_function, [0], []) + assert res == 4 * 4 + + def test_degenerated_at_return(self): + S = ootype.Instance('S', ootype.ROOT, {'x': lltype.Signed}) + T = ootype.Instance('T', S, {'y': lltype.Float}) + + def ll_function(flag): + t = ootype.new(T) + t.y = 3.25 + t.x = 3 + s = ootype.new(S) + s.x = 4 + if flag: + s = ootype.ooupcast(S, t) + return s + + res = self.interpret(ll_function, [0], []) + assert res.x == 4 + res = self.interpret(ll_function, [1], []) + assert res.x == 3 + + def _skip(self): py.test.skip('in progress') - test_degenerated_before_return = _skip - test_degenerated_before_return_2 = _skip - test_degenerated_at_return = _skip - test_degenerated_via_substructure = _skip + #test_degenerated_via_substructure = _skip test_plus_minus = _skip test_red_array = _skip test_red_struct_array = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Wed Apr 2 19:03:36 2008 @@ -274,6 +274,15 @@ except AttributeError: return TYPE._short_name() + def _compute_fielddescs(self, RGenOp): + AbstractStructTypeDesc._compute_fielddescs(self, RGenOp) + TYPE = self.TYPE + if isinstance(TYPE, ootype.Instance): + SUPERTYPE = TYPE._superclass + if SUPERTYPE is not None: + desc = InstanceTypeDesc(RGenOp, SUPERTYPE) + self.fielddescs = desc.fielddescs + self.fielddescs + self.fielddesc_by_name.update(desc.fielddesc_by_name) def create_varsize(jitstate, contdesc, sizebox): gv_size = sizebox.getgenvar(jitstate) From fijal at codespeak.net Wed Apr 2 19:04:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 19:04:07 +0200 (CEST) Subject: [pypy-svn] r53258 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080402170407.D76841684FE@codespeak.net> Author: fijal Date: Wed Apr 2 19:04:06 2008 New Revision: 53258 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: Some general progress. Only few things left (notable delete, forin, with) Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Wed Apr 2 19:04:06 2008 @@ -37,12 +37,12 @@ } UNOP_TO_CLS = { #'~': operations.BitwiseNot, - #'!': operations.Not, + '!': operations.Not, '+': operations.UPlus, '-': operations.UMinus, - #'typeof': operations.Typeof, - #'void': operations.Void, - #'delete': operations.Delete, + 'typeof': operations.Typeof, + 'void': operations.Void, + 'delete': operations.Delete, } LISTOP_TO_CLS = { '[': operations.Array, @@ -431,7 +431,7 @@ condition = self.dispatch(node.children[0]) truepart = self.dispatch(node.children[2]) falsepart = self.dispatch(node.children[3]) - return operations.Conditional(pos, condition, truepart, falsepart) + return operations.If(pos, condition, truepart, falsepart) def visit_trystatement(self, node): pos = self.get_pos(node) Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Wed Apr 2 19:04:06 2008 @@ -62,6 +62,7 @@ return W_IntNumber(ileft % iright) def division(ctx, nleft, nright): + # XXX optimise for ints and floats fleft = nleft.ToNumber() fright = nright.ToNumber() if fright == 0: @@ -211,3 +212,8 @@ except JsTypeError: raise ThrowException(W_String('it is not a constructor')) return res + +def uminus(obj): + if isinstance(obj, W_IntNumber): + return W_IntNumber(-obj.intval) + return W_FloatNumber(-obj.ToNumber()) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Wed Apr 2 19:04:06 2008 @@ -1,12 +1,12 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\ W_Array, W_PrimitiveObject, ActivationObject,\ - create_object, W_Object, w_Undefined, W_Boolean, newbool,\ - w_True, w_False, W_List + create_object, W_Object, w_Undefined, newbool,\ + w_True, w_False, W_List, w_Null from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException from pypy.rlib.unroll import unrolling_iterable from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ - compare_e, increment, commonnew + compare_e, increment, commonnew, mult, division, uminus, mod from pypy.rlib.jit import hint class AlreadyRun(Exception): @@ -195,6 +195,13 @@ def __repr__(self): return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.intval,) +class LOAD_BOOLCONSTANT(Opcode): + def __init__(self, value): + self.boolval = value + + def eval(self, ctx, stack): + stack.append(newbool(self.boolval)) + class LOAD_FLOATCONSTANT(Opcode): def __init__(self, value): self.w_floatvalue = W_FloatNumber(float(value)) @@ -222,6 +229,10 @@ def eval(self, ctx, stack): stack.append(w_Undefined) +class LOAD_NULL(Opcode): + def eval(self, ctx, stack): + stack.append(w_Null) + class LOAD_VARIABLE(Opcode): def __init__(self, identifier): self.identifier = identifier @@ -353,7 +364,20 @@ if not isinstance(right, W_Object): raise ThrowException(W_String("TypeError")) name = left.ToString(ctx) - return W_Boolean(right.HasProperty(name)) + return newbool(right.HasProperty(name)) + +class TYPEOF(BaseUnaryOperation): + def eval(self, ctx, stack): + one = stack.pop() + stack.append(W_String(one.type())) + +#class Typeof(UnaryOp): +# def eval(self, ctx): +# val = self.expr.eval(ctx) +# if isinstance(val, W_Reference) and val.GetBase() is None: +# return W_String("undefined") +# return W_String(val.GetValue().type()) + class ADD(BaseBinaryOperation): @staticmethod @@ -365,21 +389,36 @@ def operation(ctx, op1, op2): return W_IntNumber(op1&op2) - class MUL(BaseBinaryOperation): - pass + @staticmethod + def operation(ctx, op1, op2): + return mult(ctx, op1, op2) class DIV(BaseBinaryOperation): - pass + @staticmethod + def operation(ctx, op1, op2): + return division(ctx, op1, op2) class MOD(BaseBinaryOperation): - pass + @staticmethod + def operation(ctx, op1, op2): + return mod(ctx, op1, op2) class UPLUS(BaseUnaryOperation): - pass + def eval(self, ctx, stack): + if isinstance(stack[-1], W_IntNumber): + return + if isinstance(stack[-1], W_FloatNumber): + return + stack.append(stack.pop().ToNumber(ctx)) class UMINUS(BaseUnaryOperation): - pass + def eval(self, ctx, stack): + stack.append(uminus(stack.pop())) + +class NOT(BaseUnaryOperation): + def eval(self, ctx, stack): + stack.append(newbool(not stack.pop().ToBoolean())) class INCR(BaseUnaryOperation): pass Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Wed Apr 2 19:04:06 2008 @@ -409,13 +409,6 @@ else: bytecode.emit('LABEL', one) - def execute(self, ctx): - temp = self.condition.eval(ctx).GetValue() - if temp.ToBoolean(): - return self.thenPart.execute(ctx) - else: - return self.elsePart.execute(ctx) - #class Group(UnaryOp): # def eval(self, ctx): # return self.expr.eval(ctx) @@ -501,7 +494,7 @@ StrictNe = create_binary_op('ISNOT') In = create_binary_op('IN') - +Typeof = create_unary_op('TYPEOF') # class Delete(UnaryOp): # """ @@ -515,6 +508,14 @@ # r4 = r1.GetPropertyName() # return W_Boolean(r3.Delete(r4)) +class Delete(Expression): + def __init__(self, pos, what): + self.pos = pos + self.what = what + + #def emit(self, bytecode): + # + #class Index(BinaryOp): # def eval(self, ctx): # w_obj = self.left.eval(ctx).GetValue().ToObject(ctx) @@ -540,9 +541,8 @@ Sub = create_binary_op('SUB') class Null(Expression): - def eval(self, ctx): - return w_Null - + def emit(self, bytecode): + bytecode.emit('LOAD_NULL') ############################################################################## # @@ -721,13 +721,6 @@ bytecode.emit('TRYCATCHBLOCK', trycode, self.catchparam.get_literal(), catchcode, finallycode) -#class Typeof(UnaryOp): -# def eval(self, ctx): -# val = self.expr.eval(ctx) -# if isinstance(val, W_Reference) and val.GetBase() is None: -# return W_String("undefined") -# return W_String(val.GetValue().type()) - class VariableDeclaration(Expression): def __init__(self, pos, identifier, expr=None): self.pos = pos @@ -782,11 +775,15 @@ def execute(self, ctx): return self.body.eval(ctx) -#class Void(UnaryOp): -# def eval(self, ctx): -# self.expr.eval(ctx) -# return w_Undefined +class Void(Expression): + def __init__(self, pos, expr): + self.pos = pos + self.expr = expr + def emit(self, bytecode): + self.expr.emit(bytecode) + bytecode.emit('POP') + bytecode.emit('LOAD_UNDEFINED') class With(Statement): def __init__(self, pos, identifier, body): @@ -916,15 +913,11 @@ def __init__(self, pos, boolval): self.pos = pos self.bool = boolval - - def eval(self, ctx): - return W_Boolean(self.bool) - -#class Not(UnaryOp): -# def eval(self, ctx): -# return W_Boolean(not self.expr.eval(ctx).GetValue().ToBoolean()) + def emit(self, bytecode): + bytecode.emit('LOAD_BOOLCONSTANT', self.bool) +Not = create_unary_op('NOT') UMinus = create_unary_op('UMINUS') UPlus = create_unary_op('UPLUS') Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Wed Apr 2 19:04:06 2008 @@ -5,6 +5,7 @@ from pypy.lang.js.jsobj import W_Object, ExecutionContext, W_Root, w_Null from pypy.lang.js.execution import ThrowException from pypy.lang.js.jscode import JsCode, POP +from pypy.lang.js.baseop import AbstractEC def test_simple(): bytecode = JsCode() @@ -44,7 +45,7 @@ code_val = excpt.exception print code_val, value if isinstance(value, W_Root): - assert AEC(jsint.global_context, code_val, value) == True + assert AbstractEC(jsint.global_context, code_val, value) == True elif isinstance(value, bool): assert code_val.ToBoolean() == value elif isinstance(value, int): @@ -465,6 +466,7 @@ assertp("print(+1);", '1') def test_delete(): + py.test.skip("Unsupported") assertp(""" var x = {}; x.y = 1; From antocuni at codespeak.net Wed Apr 2 19:11:29 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 2 Apr 2008 19:11:29 +0200 (CEST) Subject: [pypy-svn] r53260 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080402171129.07DC3168514@codespeak.net> Author: antocuni Date: Wed Apr 2 19:11:28 2008 New Revision: 53260 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: port the last test_degenerated_* to ootype Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Wed Apr 2 19:11:28 2008 @@ -2158,11 +2158,29 @@ res = self.interpret(ll_function, [1], []) assert res.x == 3 + def test_degenerated_via_substructure(self): + S = ootype.Instance('S', ootype.ROOT, {'x': lltype.Signed}) + T = ootype.Instance('T', S, {'y': lltype.Float}) + + def ll_function(flag): + t = ootype.new(T) + t.x = 3 + s = ootype.new(S) + s.x = 7 + if flag: + pass + else: + s = ootype.ooupcast(S, t) + t.x += 1 + return s.x * t.x + res = self.interpret(ll_function, [1], []) + assert res == 7 * 4 + res = self.interpret(ll_function, [0], []) + assert res == 4 * 4 def _skip(self): py.test.skip('in progress') - #test_degenerated_via_substructure = _skip test_plus_minus = _skip test_red_array = _skip test_red_struct_array = _skip From fijal at codespeak.net Wed Apr 2 19:44:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Apr 2008 19:44:39 +0200 (CEST) Subject: [pypy-svn] r53261 - pypy/dist/pypy/doc Message-ID: <20080402174439.07489168557@codespeak.net> Author: fijal Date: Wed Apr 2 19:44:39 2008 New Revision: 53261 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: few notes Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Wed Apr 2 19:44:39 2008 @@ -45,12 +45,36 @@ .. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html -Future -====== +Limitations +=========== -The Ctypes implementation in PyPy is pretty much working and can run for example -pyglet. Because it's written in pure python, it's rather slow. As a next -step we'll measure which parts are costly and try to move certain parts from -app-level to interp-level to improve speed. Still, we will try to keep -interp-level part as simple as possible, to not loose robustness. +* No support for PyXxx functions from libpython, for obvious reasons. +* Subclassing works differently (ie it follows python subclassing scheme + instead of ctypes subclassing scheme, which does not do + inheritance) + +* It's not supposed to work on other platform than linux + +* ... + +Speed +===== + +Our ctypes implementation was created without putting to much effort into +making it fast. XXX finish improvement part + +Running example code +==================== + +You need a translation with ``--withmod-_rawffi`` in order to run any +ctypes code. For most examples ``--allworkingmodules`` translation option +also makes sense. Known applications to run are `pysqlite-ctypes`_ and +`pyglet`_. As of March 2008, from pysqlite all tests passes except one +that relies on __del__ being called immediately. From pyglet, known +examples to work are ones that does not require PIL (for example +examples/opengl.py) as well as `stress tests`_ from Johnathan Hartley. + +.. _`pysqlite-ctypes`:: XXX link +.. _`pyglet`:: http://pyglet.org/ +.. _`stress tests`:: http://tartley.com/?p=264 From cfbolz at codespeak.net Wed Apr 2 20:51:35 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 2 Apr 2008 20:51:35 +0200 (CEST) Subject: [pypy-svn] r53262 - pypy/dist/pypy/doc Message-ID: <20080402185135.E686D169EA9@codespeak.net> Author: cfbolz Date: Wed Apr 2 20:51:34 2008 New Revision: 53262 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: document which pyglet examples work Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Wed Apr 2 20:51:34 2008 @@ -71,10 +71,33 @@ ctypes code. For most examples ``--allworkingmodules`` translation option also makes sense. Known applications to run are `pysqlite-ctypes`_ and `pyglet`_. As of March 2008, from pysqlite all tests passes except one -that relies on __del__ being called immediately. From pyglet, known -examples to work are ones that does not require PIL (for example -examples/opengl.py) as well as `stress tests`_ from Johnathan Hartley. +that relies on __del__ being called immediately. From pyglet, the following +examples work: + + - opengl.py + - multiple_windows.py + - events.py + - window_platform_event.py + - fixed_resolution.py -.. _`pysqlite-ctypes`:: XXX link -.. _`pyglet`:: http://pyglet.org/ -.. _`stress tests`:: http://tartley.com/?p=264 +The following don't work: + + - fixed_resolution.py needs PIL + - image_convert.py needs PIL + - image_display.py needs PIL + - astraea/astraea.py needs PIL + - video.py (but didn't work for me on CPython either) + - soundscape needs avbin + +XXX the following all show a bug ctypes (all the same, somewhere in the font +stuff of pyglet), should be fixed: + + - html_label.py + - media_player.py + - timer.py + +The `stress tests`_ of Johnathan Hartley is also working. + +.. _`pysqlite-ctypes`: XXX link +.. _`pyglet`: http://pyglet.org/ +.. _`stress tests`: http://tartley.com/?p=264 From cami at codespeak.net Thu Apr 3 00:11:34 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 3 Apr 2008 00:11:34 +0200 (CEST) Subject: [pypy-svn] r53265 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080402221134.21D2C169F5B@codespeak.net> Author: cami Date: Thu Apr 3 00:11:33 2008 New Revision: 53265 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py Log: change cryptic functon names in cpu adapted test add reset method to registers added reste method tests Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Thu Apr 3 00:11:33 2008 @@ -3,11 +3,14 @@ class Register(object): def __init__(self, cpu, value=0): - self.value = 0 + self.resetValue = self.value = value self.cpu = cpu - if value is not 0: + if value != 0: self.set(value) + def reset(self): + self.value = self.resetValue + def set(self, value, useCycles=True): self.value = value & 0xFF if (useCycles): @@ -25,16 +28,20 @@ # ___________________________________________________________________________ class DoubleRegister(Register): - def __init__(self, cpu, hi=None, lo=None): + def __init__(self, cpu, hi=None, lo=None, resetValue=None): self.cpu = cpu - if hi==None: - self.hi = Register(self.cpu) - else: + if isinstance(hi, (Register)) : self.hi = hi + else: + self.hi = Register(self.cpu) if lo==None: self.lo = Register(self.cpu) else: self.lo = lo + if (resetValue != None): + self.resetValue = resetValue + elif (hi!=None and lo==None and resetValue==None): + self.resetValue = hi def set(self, hi=0, lo=None, useCycles=True): if (lo is None): @@ -46,6 +53,10 @@ self.setHi(hi, useCycles) self.setLo(lo, useCycles) + + def reset(self): + self.set(self.resetValue, None, False) + def setHi(self, hi=0, useCycles=True): self.hi.set(hi, useCycles) @@ -102,31 +113,37 @@ self.ime = False self.halted = False self.cycles = 0 - self.bc = DoubleRegister(self) - self.b = self.bc.hi - self.c = self.bc.lo - self.de = DoubleRegister(self) - self.d = self.de.hi - self.e = self.de.lo - self.hl = DoubleRegister(self) - self.h = self.hl.hi - self.l = self.hl.lo + + self.b = Register(self) + self.c = Register(self) + self.bc = DoubleRegister(self, self.b, self.c, constants.RESET_BC) + + self.d = Register(self) + self.e = Register(self) + self.de = DoubleRegister(self, self.d, self.e, constants.RESET_DE) + + self.h = Register(self) + self.l = Register(self) + self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) + self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self) - self.sp = DoubleRegister(self) - self.af = DoubleRegister(self) - self.a = self.af.hi - self.f = self.af.lo + self.pc = DoubleRegister(self, constants.RESET_PC) + self.sp = DoubleRegister(self, constants.RESET_SP) + + self.a = Register(self, constants.RESET_A) + self.f = Register(self, constants.RESET_F) + self.af = DoubleRegister(self, self.a, self.f) + self.reset() def reset(self): - self.a.set(constants.RESET_A) - self.f.set(constants.RESET_F) - self.bc.set(constants.RESET_BC) - self.de.set(constants.RESET_DE) - self.hl.set(constants.RESET_HL) - self.sp.set(constants.RESET_SP) - self.pc.set(constants.RESET_PC) + self.a.reset(); + self.f.reset(); + self.bc.reset(); + self.de.reset(); + self.hl.reset(); + self.sp.reset(); + self.pc.reset(); self.ime = False self.halted = False self.cycles = 0 @@ -180,6 +197,10 @@ if self.halted: val += 0x80 return val + + # Flags ............................................ + + def setROM(self, banks): self.rom = banks @@ -204,7 +225,7 @@ # Interrupts def interrupt(self, address=None): - if address is not None: + if address != None: self.ime = False self.call(address) return @@ -307,7 +328,7 @@ self.ld(self.fetch, register.set) # LD PC,HL, 1 cycle - def ld_pc_hl(self): + def storeHlInPC(self): self.ld(self.hl.get, self.pc.set) def fetchLoad(self, getter, setter): @@ -510,22 +531,22 @@ setter(getter() & (~(1 << n))) # 1 cycle # LD A,(nnnn), 4 cycles - def ld_A_mem(self): + def storeFetchedMemoryInA(self): lo = self.fetch() # 1 cycle hi = self.fetch() # 1 cycle self.a.set(self.read(hi, lo)) # 1+1 cycles # 2 cycles - def ld_BCi_A(self): + def writeAAtBCAddress(self): self.write(self.bc.get(), self.a.get()) - def ld_DEi_A(self): + def writeAAtDEAddress(self): self.write(self.de.get(), self.a.get()) - def ld_A_BCi(self): + def storeMemoryAtBCInA(self): self.a.set(self.read(self.bc.get())) - def load_A_DEi(self): + def storeMemoryAtDEInA(self): self.a.set(self.read(self.de.get())) # LD (rr),A 2 cycles @@ -542,17 +563,17 @@ self.cycles += 1 # LD (nnnn),A 4 cycles - def ld_mem_A(self): + def storeAatFetchedAddress(self): lo = self.fetch() # 1 cycle hi = self.fetch() # 1 cycle self.write((hi << 8) + lo, self.a.get()) # 2 cycles # LDH A,(nn) 3 cycles - def ldh_A_mem(self): + def storeMemoryAtExpandedFetchAddressInA(self): self.a.set(self.read(0xFF00 + self.fetch())) # 1+1+1 cycles # LDH A,(C) 2 cycles - def ldh_A_Ci(self): + def storeExpandedCinA(self): self.a.set(self.read(0xFF00 + self.bc.getLo())) # 1+2 cycles # loadAndIncrement A,(HL) 2 cycles @@ -568,11 +589,11 @@ self.cycles += 2 # LDH (nn),A 3 cycles - def ldh_mem_A(self): + def writeAatExpandedFetchAddress(self): self.write(0xFF00 + self.fetch(), self.a.get()) # 2 + 1 cycles # LDH (C),A 2 cycles - def ldh_Ci_A(self): + def writeAAtExpandedCAddress(self): self.write(0xFF00 + self.bc.getLo(), self.a.get()) # 2 cycles # loadAndIncrement (HL),A 2 cycles @@ -588,7 +609,7 @@ self.cycles += 2 # LD SP,HL 2 cycles - def ld_SP_HL(self): + def storeHlInSp(self): self.sp.set(self.hl.get()) # 1 cycle self.cycles -= 1 @@ -597,7 +618,7 @@ self.f.set(self.f.get() | (constants.N_FLAG + constants.H_FLAG)) # DAA 1 cycle - def daa(self): + def decimalAdjustAccumulator(self): delta = 0 if self.isH(): delta |= 0x06 @@ -627,17 +648,17 @@ register.dec() # ADD SP,nn 4 cycles - def add_SP_nn(self): - self.sp.set(self.SP_nn()) # 1+1 cycle + def incrementSPByFetch(self): + self.sp.set(self.getFetchAddedSP()) # 1+1 cycle self.cycles -= 2 # LD HL,SP+nn 3 cycles - def ld_HL_SP_nn(self): - self.hl.set(self.SP_nn()) # 1+1 cycle + def storeFetchAddedSPInHL(self): + self.hl.set(self.getFetchAddedSP()) # 1+1 cycle self.cycles -= 1 # 1 cycle - def SP_nn(self): + def getFetchAddedSP(self): offset = self.fetch() # 1 cycle s = (self.sp.get() + offset) & 0xFFFF self.f.set(0, False) @@ -654,11 +675,11 @@ return s # CCF/SCF - def ccf(self): + def complementCarryFlag(self): # Flip C-flag and keep Z-flag self.f.set((self.f.get() & (constants.Z_FLAG | constants.C_FLAG)) ^ constants.C_FLAG, False) - def scf(self): + def setCarryFlag(self): # Set C-flag to true and keep Z-flag self.f.set((self.f.get() & constants.Z_FLAG) | constants.C_FLAG, False) @@ -667,40 +688,40 @@ self.cycles -= 1 # JP nnnn, 4 cycles - def jp_nnnn(self): + def unconditionalJump(self): lo = self.fetch() # 1 cycle hi = self.fetch() # 1 cycle self.pc.set(hi,lo) # 2 cycles # JP cc,nnnn 3,4 cycles - def jp_cc_nnnn(self, cc): + def conditionalJump(self, cc): if cc: - self.jp_nnnn() # 4 cycles + self.unconditionalJump() # 4 cycles else: self.pc.add(2) # 3 cycles # JR +nn, 3 cycles - def jr_nn(self): + def relativeUnconditionalJump(self): self.pc.add(self.fetch()) # 3 + 1 cycles self.cycles += 1 # JR cc,+nn, 2,3 cycles - def jr_cc_nn(self, cc): + def relativeConditionalJump(self, cc): if cc: - self.jr_nn() # 3 cycles + self.relativeUnconditionalJump() # 3 cycles else: self.pc.inc() # 2 cycles # CALL nnnn, 6 cycles - def call_nnnn(self): + def unconditionalCall(self): lo = self.fetch() # 1 cycle hi = self.fetch() # 1 cycle self.call((hi << 8) + lo) # 4 cycles # CALL cc,nnnn, 3,6 cycles - def call_cc_nnnn(self, getter): + def conditionalCall(self, getter): if getter(): - self.call_nnnn() # 6 cycles + self.unconditionalCall() # 6 cycles else: self.pc.add(2) # 3 cycles @@ -855,41 +876,41 @@ (0x00, CPU.nop), (0x08, CPU.load_mem_SP), (0x10, CPU.stop), - (0x18, CPU.jr_nn), - (0x02, CPU.ld_BCi_A), - (0x12, CPU.ld_DEi_A), + (0x18, CPU.relativeUnconditionalJump), + (0x02, CPU.writeAAtBCAddress), + (0x12, CPU.writeAAtDEAddress), (0x22, CPU.loadAndIncrement_HLi_A), (0x32, CPU.loadAndDecrement_HLi_A), - (0x0A, CPU.ld_A_BCi), - (0x1A, CPU.load_A_DEi), + (0x0A, CPU.storeMemoryAtBCInA), + (0x1A, CPU.storeMemoryAtDEInA), (0x2A, CPU.loadAndIncrement_A_HLi), (0x3A, CPU.loadAndDecrement_A_HLi), (0x07, CPU.rotateLeftCircularA), (0x0F, CPU.rotateRightCircularA), (0x17, CPU.rotateLeftA), (0x1F, CPU.rotateRightA), - (0x27, CPU.daa), + (0x27, CPU.decimalAdjustAccumulator), (0x2F, CPU.complementA), - (0x37, CPU.scf), - (0x3F, CPU.ccf), + (0x37, CPU.setCarryFlag), + (0x3F, CPU.complementCarryFlag), (0x76, CPU.halt), (0xF3, CPU.disableInterrupts), (0xFB, CPU.enableInterrupts), - (0xE2, CPU.ldh_Ci_A), - (0xEA, CPU.ld_mem_A), - (0xF2, CPU.ldh_A_Ci), - (0xFA, CPU.ld_A_mem), - (0xC3, CPU.jp_nnnn), + (0xE2, CPU.writeAAtExpandedCAddress), + (0xEA, CPU.storeAatFetchedAddress), + (0xF2, CPU.storeExpandedCinA), + (0xFA, CPU.storeFetchedMemoryInA), + (0xC3, CPU.unconditionalJump), (0xC9, CPU.ret), (0xD9, CPU.returnFormInterrupt), - (0xE9, CPU.ld_pc_hl), - (0xF9, CPU.ld_SP_HL), - (0xE0, CPU.ldh_mem_A), - (0xE8, CPU.add_SP_nn), - (0xF0, CPU.ldh_A_mem), - (0xF8, CPU.ld_HL_SP_nn), + (0xE9, CPU.storeHlInPC), + (0xF9, CPU.storeHlInSp), + (0xE0, CPU.writeAatExpandedFetchAddress), + (0xE8, CPU.incrementSPByFetch), + (0xF0, CPU.storeMemoryAtExpandedFetchAddressInA), + (0xF8, CPU.storeFetchAddedSPInHL), (0xCB, CPU.fetchExecute), - (0xCD, CPU.call_nnnn), + (0xCD, CPU.unconditionalCall), (0xC6, lambda s: CPU.addA(s, s.fetch)), (0xCE, lambda s: CPU.addWithCarry(s, s.fetch)), (0xD6, lambda s: CPU.subtract(s, s.fetch)), @@ -926,19 +947,19 @@ REGISTER_SET_A = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getSP] -REGISTER_SET_B = [CPU.isNZ, CPU.isZ, CPU.isNC, CPU.isC] -REGISTER_SET_C = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getAF] +REGISTER_SET_B = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getAF] +FLAG_REGISTER_SET = [CPU.isNZ, CPU.isZ, CPU.isNC, CPU.isC] REGISTER_OP_CODES = [ - (0x01, 0x10, CPU.fetchDoubleRegister, REGISTER_SET_A), - (0x09, 0x10, CPU.addHL, REGISTER_SET_A), - (0x03, 0x10, CPU.incDoubleRegister, REGISTER_SET_A), - (0x0B, 0x10, CPU.decDoubleRegister, REGISTER_SET_A), - (0xC0, 0x08, CPU.conditionalReturn, REGISTER_SET_B), - (0xC2, 0x08, CPU.jp_cc_nnnn, REGISTER_SET_B), - (0xC4, 0x08, CPU.call_cc_nnnn, REGISTER_SET_B), - (0x20, 0x08, CPU.jr_cc_nn, REGISTER_SET_B), - (0xC1, 0x10, CPU.popDoubleRegister, REGISTER_SET_C), - (0xC5, 0x10, CPU.pushDoubleRegister, REGISTER_SET_C) + (0x01, 0x10, CPU.fetchDoubleRegister, REGISTER_SET_A), + (0x09, 0x10, CPU.addHL, REGISTER_SET_A), + (0x03, 0x10, CPU.incDoubleRegister, REGISTER_SET_A), + (0x0B, 0x10, CPU.decDoubleRegister, REGISTER_SET_A), + (0xC0, 0x08, CPU.conditionalReturn, FLAG_REGISTER_SET), + (0xC2, 0x08, CPU.conditionalJump, FLAG_REGISTER_SET), + (0xC4, 0x08, CPU.conditionalCall, FLAG_REGISTER_SET), + (0x20, 0x08, CPU.relativeConditionalJump, FLAG_REGISTER_SET), + (0xC1, 0x10, CPU.popDoubleRegister, REGISTER_SET_B), + (0xC5, 0x10, CPU.pushDoubleRegister, REGISTER_SET_B) ] SECOND_ORDER_REGISTER_GROUP_OP_CODES = [ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Thu Apr 3 00:11:33 2008 @@ -41,6 +41,14 @@ register.set(value) assert register.get() == 0xFF +def test_reset(): + value = 0x12 + register = Register(get_cpu(), value) + register.set(value+1) + assert register.get() == value+1 + register.reset() + assert register.get() == value + # ------------------------------------------------------------ # TEST DOUBLE REGISTER @@ -123,7 +131,15 @@ assert oldCycles-register.cpu.cycles == 3 assert register.get() == value+addValue - + +def test_double_register_reset(): + value = 0x1234; + + register = DoubleRegister(get_cpu(), value) + register.set(value+1) + assert register.get() == value+1; + register.reset() + assert register.get() == value # ------------------------------------------------------------ # TEST CPU @@ -186,20 +202,20 @@ assert cpu.read(address) == value -def test_jr_cc_nn(): +def test_relativeConditionalJump(): cpu = get_cpu() pc = cpu.pc.get() value = 0x12 cpu.rom[constants.RESET_PC] = value # test jr_nn startCycles = cpu.cycles - cpu.jr_cc_nn(True) + cpu.relativeConditionalJump(True) assert startCycles-cpu.cycles == 3 assert_registers(cpu, pc=pc+value+1) # test pc.inc startCycles = cpu.cycles pc = cpu.pc.get() - cpu.jr_cc_nn(False) + cpu.relativeConditionalJump(False) assert startCycles-cpu.cycles == 2 assert cpu.pc.get() == pc+1 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py Thu Apr 3 00:11:33 2008 @@ -28,7 +28,6 @@ str += ("1") else: str += ("0") - print i, str, binNumber assert number == i def number_to_bool_bin(number, size=None): From fijal at codespeak.net Thu Apr 3 03:32:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 03:32:48 +0200 (CEST) Subject: [pypy-svn] r53266 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080403013248.D51F2169FC5@codespeak.net> Author: fijal Date: Thu Apr 3 03:32:47 2008 New Revision: 53266 Modified: pypy/dist/pypy/lib/_ctypes/function.py Log: This fixes non-working pyglet examples, but I still don't completely get what should be here in the first place Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Thu Apr 3 03:32:47 2008 @@ -114,8 +114,8 @@ argtypes = argtypes[:] + self._guess_argtypes(args[cut:]) restype = self._restype_ funcptr = self._getfuncptr(argtypes, restype) - args = self._wrap_args(argtypes, args) - resbuffer = funcptr(*[arg._buffer for obj, arg in args]) + argsandobjs = self._wrap_args(argtypes, args) + resbuffer = funcptr(*[arg._buffer for _, arg in argsandobjs]) if restype is not None: if not isinstance(restype, _CDataMeta): return restype(resbuffer[0]) @@ -147,8 +147,8 @@ res.append(type(arg)) elif arg is None: res.append(c_void_p) - elif arg == 0: - res.append(c_void_p) + #elif arg == 0: + # res.append(c_void_p) elif isinstance(arg, (int, long)): res.append(c_int) else: From fijal at codespeak.net Thu Apr 3 05:03:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 05:03:32 +0200 (CEST) Subject: [pypy-svn] r53267 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403030332.2C11F16A016@codespeak.net> Author: fijal Date: Thu Apr 3 05:03:30 2008 New Revision: 53267 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: * skip one test * fix remaining errors Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 05:03:30 2008 @@ -9,6 +9,7 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import rffi +from pypy.jit.codegen.emit_moves import emit_moves, emit_moves_safe WORD = 4 DEBUG_CALL_ALIGN = True @@ -39,7 +40,7 @@ return self.operand(builder) def __repr__(self): - return 'var@%d' % (self.stackpos,) + return self.token + 'var@%d' % (self.stackpos,) repr = __repr__ @@ -269,7 +270,7 @@ mc.CMP(eax, gv_case.operand(None)) self._je_key = targetbuilder.come_from(mc, 'JE', self._je_key) pos = mc.tell() - assert self.defaultcaseaddr != 0 + assert self.default_case_builder self.default_case_key = self.default_case_builder.come_from( mc, 'JMP', self.default_case_key) mc.done() @@ -630,7 +631,10 @@ return res def returnboolvar(self, op): - self.mc.MOVZX(eax, op) + if isinstance(op, IMM8): + self.mc.MOV(eax, op) + else: + self.mc.MOVZX(eax, op) res = BoolVar(self.stackdepth) self.push(eax) return res @@ -1008,6 +1012,29 @@ # ____________________________________________________________ +def _remap_bigger_values(args_gv, arg_positions): + """ This function cheates and changes all FloatVars into double + IntVars. This might be probably optimized in some way in order + to provide greater performance, but should be enough for now + """ + res_gv = [] + res_positions = [] + for i in range(len(args_gv)): + gv = args_gv[i] + pos = arg_positions[i] + if gv.SIZE == 1: + res_gv.append(gv) + res_positions.append(pos) + else: + assert gv.SIZE == 2 + res_gv.append(IntVar(gv.stackpos)) + res_gv.append(IntVar(gv.stackpos - 1)) + res_positions.append(pos) + res_positions.append(pos - 1) + # no repeats please + assert sorted(dict.fromkeys(res_positions).keys()) == sorted(res_positions) + return res_gv, res_positions + def remap_stack_layout(builder, outputargs_gv, target): ## import os ## s = ', '.join([gv.repr() for gv in outputargs_gv]) @@ -1026,8 +1053,10 @@ builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth))) builder.stackdepth = N - M = len(outputargs_gv) + #outputargs_gv, arg_positions = _remap_bigger_values(outputargs_gv, + # target.arg_positions) arg_positions = target.arg_positions + M = len(outputargs_gv) assert M == len(arg_positions) targetlayout = [None] * N srccount = [-N] * N Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 05:03:30 2008 @@ -35,6 +35,9 @@ # lltype.Address in function arguments test_demo_f1_direct = skipped + # float stack remap + test_float_loop_direct = skipped + class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked From fijal at codespeak.net Thu Apr 3 06:18:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 06:18:48 +0200 (CEST) Subject: [pypy-svn] r53268 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403041848.935D6168563@codespeak.net> Author: fijal Date: Thu Apr 3 06:18:46 2008 New Revision: 53268 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: Obscure hack to have stack remapping work. There are few issues with it, but seems to work more or less (one important issue is "how to move floats around") Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 06:18:46 2008 @@ -153,10 +153,14 @@ return "const=$%s" % (self.value,) class IntConst(Const): + SIZE = 1 + def newvar(self, builder): return builder.returnintvar(self.operand(builder)) class FloatConst(Const): + SIZE = 2 + def __init__(self, floatval): # XXX we should take more care who is creating this and # eventually release this buffer @@ -166,12 +170,14 @@ self.rawbuf[0] = floatval def newvar(self, builder): - return builder.returnfloatvar(self.operand(builder)) + return builder.newfloatfrommem(self.rawbuf) def operand(self, builder): return heap64(rffi.cast(rffi.INT, self.rawbuf)) class BoolConst(Const): + SIZE = 1 + def newvar(self, builder): return builder.returnboolvar(self.operand(builder)) @@ -524,6 +530,7 @@ final_depth = self.stackdepth + numargs delta = ((final_depth+MASK)&~MASK)-final_depth if delta: + xxx self.mc.SUB(esp, imm(delta*WORD)) self.stackdepth += delta for i in range(numargs-1, -1, -1): @@ -620,7 +627,7 @@ self.mc.PUSH(op) self.stackdepth += 1 - def pushfloat(self, op): + def pushfloatfromst0(self, op): self.mc.SUB(esp, imm(WORD * FloatVar.SIZE)) self.stackdepth += 2 self.mc.FSTPL(op.operand(self)) @@ -641,7 +648,19 @@ def returnfloatvar(self, op): res = FloatVar(self.stackdepth + 1) - self.pushfloat(res) + if op is st0: + self.pushfloatfromst0(res) + else: + raise NotImplementedError("Return float var not on fp stack") + return res + + def newfloatfrommem(self, rawbuf): + # XXX obscure pointer arithmetics on ints. Think how do to it + # better + res = FloatVar(self.stackdepth + 1) + self.mc.PUSH(heap(rffi.cast(rffi.INT, rawbuf))) + self.mc.PUSH(heap(rffi.cast(rffi.INT, rawbuf) + WORD)) + self.stackdepth += 2 return res @staticmethod @@ -1027,6 +1046,7 @@ res_positions.append(pos) else: assert gv.SIZE == 2 + assert isinstance(gv, FloatVar) res_gv.append(IntVar(gv.stackpos)) res_gv.append(IntVar(gv.stackpos - 1)) res_positions.append(pos) @@ -1053,9 +1073,8 @@ builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth))) builder.stackdepth = N - #outputargs_gv, arg_positions = _remap_bigger_values(outputargs_gv, - # target.arg_positions) - arg_positions = target.arg_positions + outputargs_gv, arg_positions = _remap_bigger_values(outputargs_gv, + target.arg_positions) M = len(outputargs_gv) assert M == len(arg_positions) targetlayout = [None] * N Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 06:18:46 2008 @@ -36,7 +36,6 @@ test_demo_f1_direct = skipped # float stack remap - test_float_loop_direct = skipped class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp From fijal at codespeak.net Thu Apr 3 07:17:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 07:17:00 +0200 (CEST) Subject: [pypy-svn] r53269 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080403051700.D8D8616A034@codespeak.net> Author: fijal Date: Thu Apr 3 07:16:58 2008 New Revision: 53269 Added: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py (contents, props changed) Log: Add a test for guessing argtypes. Added: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py Thu Apr 3 07:16:58 2008 @@ -0,0 +1,29 @@ + +""" This test checks whether args wrapping behavior is correct +""" + +import sys + +from ctypes import * + +def test_wrap_args(): + if not hasattr(sys, 'pypy_translation_info'): + py.test.skip("whitebox test") + from _ctypes.function import CFuncPtr + + guess = CFuncPtr._guess_argtypes + + assert guess([13]) == [c_int] + assert guess([0]) == [c_int] + assert guess(['xca']) == [c_char_p] + assert guess([None]) == [c_void_p] + assert guess([c_int(3)]) == [c_int] + + class Stuff: + pass + s = Stuff() + s._as_parameter_ = None + + assert guess([s]) == [c_void_p] + + # not sure what else.... From fijal at codespeak.net Thu Apr 3 07:25:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 07:25:01 +0200 (CEST) Subject: [pypy-svn] r53270 - pypy/dist/pypy/doc Message-ID: <20080403052501.794A916A044@codespeak.net> Author: fijal Date: Thu Apr 3 07:25:00 2008 New Revision: 53270 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: update Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Thu Apr 3 07:25:00 2008 @@ -79,6 +79,9 @@ - events.py - window_platform_event.py - fixed_resolution.py + - html_label.py + - media_player.py + - timer.py The following don't work: @@ -88,13 +91,6 @@ - astraea/astraea.py needs PIL - video.py (but didn't work for me on CPython either) - soundscape needs avbin - -XXX the following all show a bug ctypes (all the same, somewhere in the font -stuff of pyglet), should be fixed: - - - html_label.py - - media_player.py - - timer.py The `stress tests`_ of Johnathan Hartley is also working. From fijal at codespeak.net Thu Apr 3 07:31:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 07:31:26 +0200 (CEST) Subject: [pypy-svn] r53271 - pypy/dist/pypy/doc Message-ID: <20080403053126.4792316A026@codespeak.net> Author: fijal Date: Thu Apr 3 07:31:25 2008 New Revision: 53271 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: More info. Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Thu Apr 3 07:31:25 2008 @@ -56,13 +56,35 @@ * It's not supposed to work on other platform than linux -* ... +* We copy strings instead of having pointers to raw buffers, which + changes keepalive logic a bit + +* Custom alignment is not supported + +* Callbacks with structures and arrays by-value are unsupported + +Minor unsupported features: +=========================== + +* \_check\_retval\_ is not supported + +* \_abstract\_ is not supported + +* reprs are different Speed ===== Our ctypes implementation was created without putting to much effort into -making it fast. XXX finish improvement part +making it fast. First of all most of it is written as pure-python code which +makes it slow. Obvious optimization would be to reimplement certain parts +of it at interp-level. Other, also very important, issue is that pypy's I/O +operations are generally slow. This is mostly due to model in which +unmanaged memory (outside of gc scope) must be the only one that goes to C +level. This is a huge simplifaction which allowed us to not worry about +that when developing moving gcs. At some point we will improve C-level +operations by either introducing pinning or by some other, yet undecided +means. Running example code ==================== From fijal at codespeak.net Thu Apr 3 07:50:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 07:50:07 +0200 (CEST) Subject: [pypy-svn] r53272 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403055007.6EEDD16A055@codespeak.net> Author: fijal Date: Thu Apr 3 07:50:06 2008 New Revision: 53272 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: * put a clear error marker * easy test :) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 07:50:06 2008 @@ -72,6 +72,7 @@ return builder.stack_access64(self.stackpos) def newvar(self, builder): + raise NotImplementedError("This requires moving around float mem") return builder.returnfloatvar(self.operand(builder)) ll_type = lltype.Float @@ -558,6 +559,9 @@ def genop_debug_pdb(self): # may take an args_gv later self.mc.BREAKPOINT() + def genop_cast_int_to_ptr(self, kind, gv_int): + return gv_int # identity + def enter_next_block(self, args_gv): self._open() arg_positions = [] Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 07:50:06 2008 @@ -30,7 +30,7 @@ test_ovfcheck2_direct = skipped # casts - test_cast_direct = skipped + #test_cast_direct = skipped # lltype.Address in function arguments test_demo_f1_direct = skipped From fijal at codespeak.net Thu Apr 3 07:57:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 07:57:28 +0200 (CEST) Subject: [pypy-svn] r53273 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403055728.E658F16A05C@codespeak.net> Author: fijal Date: Thu Apr 3 07:57:26 2008 New Revision: 53273 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: Not sure if this test is still valid, but passes Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 07:57:26 2008 @@ -1338,6 +1338,11 @@ @staticmethod @specialize.memo() + def kindToken(T): + return None + + @staticmethod + @specialize.memo() def varsizeAllocToken(T): if isinstance(T, lltype.Array): return RI386GenOp.arrayToken(T) @@ -1361,11 +1366,6 @@ @staticmethod @specialize.memo() - def kindToken(T): - return None # for now - - @staticmethod - @specialize.memo() def sigToken(FUNCTYPE): return ([LL_TO_GENVAR[arg] for arg in FUNCTYPE.ARGS if arg is not lltype.Void], LL_TO_GENVAR[FUNCTYPE.RESULT]) @@ -1381,5 +1381,12 @@ else: assert 0, "XXX not implemented" + @staticmethod + @specialize.arg(1) + def genzeroconst(kind): + # XXX kind probably goes away + return zero_const + global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst +zero_const = AddrConst(llmemory.NULL) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 07:57:26 2008 @@ -22,16 +22,13 @@ test_frame_vars_like_the_frontend_direct = skipped # unsupported operations - test_genzeroconst = skipped + #test_genzeroconst = skipped # overflow test_ovfcheck_adder_direct = skipped test_ovfcheck1_direct = skipped test_ovfcheck2_direct = skipped - # casts - #test_cast_direct = skipped - # lltype.Address in function arguments test_demo_f1_direct = skipped From fijal at codespeak.net Thu Apr 3 08:33:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 08:33:43 +0200 (CEST) Subject: [pypy-svn] r53274 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080403063343.184C516A032@codespeak.net> Author: fijal Date: Thu Apr 3 08:33:41 2008 New Revision: 53274 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: test same_as, just because (passes) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Thu Apr 3 08:33:41 2008 @@ -197,7 +197,8 @@ gv_y1 = bodybuilder.genop1("float_neg", gv_y) gv_i1 = bodybuilder.genop1("cast_int_to_float", gv_i) gv_v0 = bodybuilder.genop2("float_mul", gv_y1, gv_i1) - gv_res0 = bodybuilder.genop2("float_sub", gv_res, gv_v0) + gv_v1 = bodybuilder.genop_same_as(gv_v0) + gv_res0 = bodybuilder.genop2("float_sub", gv_res, gv_v1) gv_i2 = bodybuilder.genop2("int_add", gv_i, rgenop.genconst(1)) bodybuilder.finish_and_goto([gv_x, gv_y, gv_i2, gv_res0], loopblock) builder.end() From fijal at codespeak.net Thu Apr 3 08:35:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 08:35:13 +0200 (CEST) Subject: [pypy-svn] r53275 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403063513.74DB316A045@codespeak.net> Author: fijal Date: Thu Apr 3 08:35:12 2008 New Revision: 53275 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: first overflow test passes Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 08:35:12 2008 @@ -421,6 +421,11 @@ genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg1, gv_arg2) + @specialize.arg(1) + def genraisingop2(self, opname, gv_arg1, gv_arg2): + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg1, gv_arg2) + def genop_getfield(self, (offset, fieldsize), gv_ptr): self.mc.MOV(edx, gv_ptr.operand(self)) if fieldsize == WORD: @@ -642,7 +647,9 @@ return res def returnboolvar(self, op): - if isinstance(op, IMM8): + if op is eax: + pass + elif isinstance(op, IMM8): self.mc.MOV(eax, op) else: self.mc.MOVZX(eax, op) @@ -686,6 +693,12 @@ self.mc.ADD(eax, gv_y.operand(self)) return self.returnintvar(eax) + def op_int_add_ovf(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.ADD(eax, gv_y.operand(self)) + self.mc.SETO(dl) + return self.returnintvar(eax), self.returnboolvar(dl) + def op_int_sub(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.SUB(eax, gv_y.operand(self)) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 08:35:12 2008 @@ -21,11 +21,7 @@ test_read_frame_place_direct = skipped test_frame_vars_like_the_frontend_direct = skipped - # unsupported operations - #test_genzeroconst = skipped - # overflow - test_ovfcheck_adder_direct = skipped test_ovfcheck1_direct = skipped test_ovfcheck2_direct = skipped From fijal at codespeak.net Thu Apr 3 08:46:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 08:46:36 +0200 (CEST) Subject: [pypy-svn] r53276 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403064636.A969D16A06D@codespeak.net> Author: fijal Date: Thu Apr 3 08:46:36 2008 New Revision: 53276 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: Overflow support Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 08:46:36 2008 @@ -295,6 +295,22 @@ targetbuilder._open() return targetbuilder +def _create_ovf_one_version(opname, flag): + def op_ovf(self, gv_x): + gv = getattr(self, opname)(gv_x) + getattr(self.mc, 'SET' + flag)(al) + return gv, self.returnboolvar(al) + op_ovf.func_name = opname + '_ovf' + return op_ovf + +def _create_ovf_two_version(opname, flag): + def op_ovf(self, gv_x, gv_y): + gv = getattr(self, opname)(gv_x, gv_y) + getattr(self.mc, 'SET' + flag)(al) + return gv, self.returnboolvar(al) + op_ovf.func_name = opname + '_ovf' + return op_ovf + class Builder(GenBuilder): def __init__(self, rgenop, stackdepth): @@ -426,6 +442,11 @@ genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg1, gv_arg2) + @specialize.arg(1) + def genraisingop1(self, opname, gv_arg): + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg) + def genop_getfield(self, (offset, fieldsize), gv_ptr): self.mc.MOV(edx, gv_ptr.operand(self)) if fieldsize == WORD: @@ -693,22 +714,22 @@ self.mc.ADD(eax, gv_y.operand(self)) return self.returnintvar(eax) - def op_int_add_ovf(self, gv_x, gv_y): - self.mc.MOV(eax, gv_x.operand(self)) - self.mc.ADD(eax, gv_y.operand(self)) - self.mc.SETO(dl) - return self.returnintvar(eax), self.returnboolvar(dl) + op_int_add_ovf = _create_ovf_two_version('op_int_add', 'O') def op_int_sub(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.SUB(eax, gv_y.operand(self)) return self.returnintvar(eax) + op_int_sub_ovf = _create_ovf_two_version('op_int_sub', 'O') + def op_int_mul(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.IMUL(eax, gv_y.operand(self)) return self.returnintvar(eax) + op_int_mul_ovf = _create_ovf_two_version('op_int_mul', 'O') + def op_int_floordiv(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CDQ() @@ -777,7 +798,10 @@ self.mc.NEG(eax) return self.returnintvar(eax) + op_int_neg_ovf = _create_ovf_one_version('op_int_neg', 'O') + def op_int_abs(self, gv_x): + # XXX cannot we employ fp unit to do that for us? :) self.mc.MOV(eax, gv_x.operand(self)) # ABS-computing code from Psyco, found by exhaustive search # on *all* short sequences of operations :-) @@ -787,6 +811,8 @@ self.mc.XOR(eax, edx) return self.returnintvar(eax) + op_int_abs_ovf = _create_ovf_one_version('op_int_abs', 'L') + def op_int_invert(self, gv_x): self.mc.MOV(eax, gv_x.operand(self)) self.mc.NOT(eax) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 08:46:36 2008 @@ -21,10 +21,6 @@ test_read_frame_place_direct = skipped test_frame_vars_like_the_frontend_direct = skipped - # overflow - test_ovfcheck1_direct = skipped - test_ovfcheck2_direct = skipped - # lltype.Address in function arguments test_demo_f1_direct = skipped From fijal at codespeak.net Thu Apr 3 08:48:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 08:48:47 +0200 (CEST) Subject: [pypy-svn] r53277 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403064847.54A47168537@codespeak.net> Author: fijal Date: Thu Apr 3 08:48:47 2008 New Revision: 53277 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: support for address in function arguments. Still frame access left Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 08:48:47 2008 @@ -45,15 +45,19 @@ repr = __repr__ class IntVar(Var): + ll_type = lltype.Signed + token = 'i' + SIZE = 1 + def operand(self, builder): return builder.stack_access(self.stackpos) def newvar(self, builder): return builder.returnintvar(self.operand(builder)) - ll_type = lltype.Signed - token = 'i' - SIZE = 1 +class AddressVar(IntVar): + ll_type = llmemory.Address + token = 'a' class BoolVar(Var): # represents a boolean as an integer which *must* be exactly 0 or 1 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 08:48:47 2008 @@ -20,12 +20,8 @@ test_write_lots_of_frame_places_direct = skipped test_read_frame_place_direct = skipped test_frame_vars_like_the_frontend_direct = skipped - - # lltype.Address in function arguments test_demo_f1_direct = skipped - # float stack remap - class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked From jared.grubb at codespeak.net Thu Apr 3 09:36:52 2008 From: jared.grubb at codespeak.net (jared.grubb at codespeak.net) Date: Thu, 3 Apr 2008 09:36:52 +0200 (CEST) Subject: [pypy-svn] r53278 - in pypy/dist/pypy/rlib/parsing: . test Message-ID: <20080403073652.2FCB716A076@codespeak.net> Author: jared.grubb Date: Thu Apr 3 09:36:51 2008 New Revision: 53278 Added: pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle Modified: pypy/dist/pypy/rlib/parsing/regexparse.py pypy/dist/pypy/rlib/parsing/test/test_deterministic.py pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py pypy/dist/pypy/rlib/parsing/test/testoutput1.pickle Log: Fixed test_deterministic.py failure assertion; added DFA PCRE tests (need to still adapt them to exercise our DFA, skipped for now) Updated regexparse.py with expanded parsing, allowing the following base cases '()', '(a|)', '{', ']', '}', '[]]', '[.?*+[-]' Modified: pypy/dist/pypy/rlib/parsing/regexparse.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/regexparse.py (original) +++ pypy/dist/pypy/rlib/parsing/regexparse.py Thu Apr 3 09:36:51 2008 @@ -80,7 +80,7 @@ | concatenation; concatenation: - l = repetition+ + l = repetition* return {reduce(operator.add, l, regex.StringExpression(""))}; repetition: @@ -103,6 +103,8 @@ n = numrange '}' return {r1 * n[0] + reduce(operator.or_, [r1 * i for i in range(n[1] - n[0] + 1)], regex.StringExpression(""))} + | '{' + return {regex.StringExpression("{")} | primary; primary: @@ -113,7 +115,9 @@ | c = char return {regex.StringExpression(c)} | '.' - return {regex.RangeExpression(chr(0), chr(255))}; + return {regex.RangeExpression(chr(0), chr(255))} + | ']' + return {regex.StringExpression(']')}; char: c = QUOTEDCHAR @@ -125,7 +129,7 @@ `(\\x[0-9a-fA-F]{2})|(\\[0-3]?[0-7][0-7])|(\\c.)|(\\.)`; CHAR: - `[^\*\+\(\)\[\]\{\}\|\.\-\?\,\^]`; + `[^\*\+\(\)\[\]\{\|\.\-\?\^]`; range: '[' @@ -141,7 +145,7 @@ subrange: ']' - l = rangeelement+ + l = rangeelement* return {reduce(operator.or_, [set(["]"])] + l)} | l = rangeelement+ return {reduce(operator.or_, l)}; @@ -152,8 +156,20 @@ '-' c2 = char return {set([chr(i) for i in range(ord(c1), ord(c2) + 1)])} + | '.' + return { set(['.']) } + | '*' + return { set(['*']) } + | '+' + return { set(['+']) } + | '?' + return { set(['?']) } + | '-' + return { set(['-']) } + | '[' + return { set(['[']) } | c = char - return {set([c])}; + return { set([c]) }; numrange: n1 = NUM @@ -458,16 +474,12 @@ _result = None _error = None _all0 = [] - _call_status = self._repetition() - _result = _call_status.result - _error = _call_status.error - _all0.append(_result) while 1: _choice1 = self._pos try: _call_status = self._repetition() _result = _call_status.result - _error = self._combine_errors(_error, _call_status.error) + _error = _call_status.error _all0.append(_result) except BacktrackException, _exc: _error = self._combine_errors(_error, _exc.error) @@ -601,13 +613,21 @@ self._pos = _choice4 _choice5 = self._pos try: + _result = self.__chars__('{') + _result = (regex.StringExpression("{")) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice5 + _choice6 = self._pos + try: _call_status = self._primary() _result = _call_status.result _error = self._combine_errors(_error, _call_status.error) break except BacktrackException, _exc: _error = self._combine_errors(_error, _exc.error) - self._pos = _choice5 + self._pos = _choice6 raise BacktrackException(_error) _call_status = self._primary() _result = _call_status.result @@ -720,9 +740,17 @@ except BacktrackException, _exc: _error = self._combine_errors(_error, _exc.error) self._pos = _choice6 + _choice7 = self._pos + try: + _result = self.__chars__(']') + _result = (regex.StringExpression(']')) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice7 raise BacktrackException(_error) - _result = self.__chars__('.') - _result = (regex.RangeExpression(chr(0), chr(255))) + _result = self.__chars__(']') + _result = (regex.StringExpression(']')) break if _status.status == _status.LEFTRECURSION: if _status.result is not None: @@ -880,7 +908,7 @@ try: _result = None _error = None - _result = self._regex1323868075() + _result = self._regex100349762() assert _status.status != _status.LEFTRECURSION _status.status = _status.NORMAL _status.pos = self._pos @@ -1065,16 +1093,12 @@ try: _result = self.__chars__(']') _all1 = [] - _call_status = self._rangeelement() - _result = _call_status.result - _error = _call_status.error - _all1.append(_result) while 1: _choice2 = self._pos try: _call_status = self._rangeelement() _result = _call_status.result - _error = self._combine_errors(_error, _call_status.error) + _error = _call_status.error _all1.append(_result) except BacktrackException, _exc: _error = self._combine_errors(_error, _exc.error) @@ -1213,21 +1237,69 @@ self._pos = _choice1 _choice2 = self._pos try: + _result = self.__chars__('.') + _result = ( set(['.']) ) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice2 + _choice3 = self._pos + try: + _result = self.__chars__('*') + _result = ( set(['*']) ) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice3 + _choice4 = self._pos + try: + _result = self.__chars__('+') + _result = ( set(['+']) ) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice4 + _choice5 = self._pos + try: + _result = self.__chars__('?') + _result = ( set(['?']) ) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice5 + _choice6 = self._pos + try: + _result = self.__chars__('-') + _result = ( set(['-']) ) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice6 + _choice7 = self._pos + try: + _result = self.__chars__('[') + _result = ( set(['[']) ) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice7 + _choice8 = self._pos + try: _call_status = self._char() _result = _call_status.result _error = self._combine_errors(_error, _call_status.error) c = _result - _result = (set([c])) + _result = ( set([c]) ) break except BacktrackException, _exc: _error = self._combine_errors(_error, _exc.error) - self._pos = _choice2 + self._pos = _choice8 raise BacktrackException(_error) _call_status = self._char() _result = _call_status.result _error = self._combine_errors(_error, _call_status.error) c = _result - _result = (set([c])) + _result = ( set([c]) ) break if _status.status == _status.LEFTRECURSION: if _status.result is not None: @@ -1543,10 +1615,10 @@ self._dict_NUM = {} self._pos = 0 self._inputstream = inputstream - def _regex1166214427(self): + def _regex100349762(self): _choice0 = self._pos _runner = self._Runner(self._inputstream, self._pos) - _i = _runner.recognize_1166214427(self._pos) + _i = _runner.recognize_100349762(self._pos) if _runner.last_matched_state == -1: self._pos = _choice0 raise BacktrackException @@ -1571,10 +1643,10 @@ _result = self._inputstream[_pos: _upto] self._pos = _upto return _result - def _regex1323868075(self): + def _regex1166214427(self): _choice2 = self._pos _runner = self._Runner(self._inputstream, self._pos) - _i = _runner.recognize_1323868075(self._pos) + _i = _runner.recognize_1166214427(self._pos) if _runner.last_matched_state == -1: self._pos = _choice2 raise BacktrackException @@ -1592,7 +1664,7 @@ self.last_matched_state = -1 self.last_matched_index = -1 self.state = -1 - def recognize_1166214427(runner, i): + def recognize_100349762(runner, i): #auto-generated code, don't edit assert i >= 0 input = runner.text @@ -1605,24 +1677,20 @@ except IndexError: runner.state = 0 return ~i - if char == '0': + if '}' <= char <= '\xff': + state = 1 + elif '\x00' <= char <= "'": + state = 1 + elif '_' <= char <= 'z': + state = 1 + elif '@' <= char <= 'Z': + state = 1 + elif '/' <= char <= '>': + state = 1 + elif char == ',': + state = 1 + elif char == '\\': state = 1 - elif '1' <= char <= '9': - state = 2 - else: - break - if state == 2: - runner.last_matched_index = i - 1 - runner.last_matched_state = state - try: - char = input[i] - i += 1 - except IndexError: - runner.state = 2 - return i - if '0' <= char <= '9': - state = 2 - continue else: break runner.last_matched_state = state @@ -1762,7 +1830,7 @@ break runner.state = state return ~i - def recognize_1323868075(runner, i): + def recognize_1166214427(runner, i): #auto-generated code, don't edit assert i >= 0 input = runner.text @@ -1775,18 +1843,24 @@ except IndexError: runner.state = 0 return ~i - if '~' <= char <= '\xff': - state = 1 - elif '\x00' <= char <= "'": - state = 1 - elif '_' <= char <= 'z': - state = 1 - elif '@' <= char <= 'Z': - state = 1 - elif '/' <= char <= '>': - state = 1 - elif char == '\\': + if char == '0': state = 1 + elif '1' <= char <= '9': + state = 2 + else: + break + if state == 2: + runner.last_matched_index = i - 1 + runner.last_matched_state = state + try: + char = input[i] + i += 1 + except IndexError: + runner.state = 2 + return i + if '0' <= char <= '9': + state = 2 + continue else: break runner.last_matched_state = state @@ -1847,6 +1921,16 @@ + + + + + + + + + + def test_generate(): f = py.magic.autopath() oldcontent = f.read() Modified: pypy/dist/pypy/rlib/parsing/test/test_deterministic.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_deterministic.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_deterministic.py Thu Apr 3 09:36:51 2008 @@ -170,6 +170,11 @@ assert make_nice_charset_repr("ABCabc") == 'A-Ca-c' assert make_nice_charset_repr("zycba") == 'a-cyz' assert make_nice_charset_repr(string.ascii_letters) == 'A-Za-z' - # this next one is ugly... need to clean it up (sometimes it fails because it's - # being generated from a dict, so the order is funky) - assert make_nice_charset_repr(string.printable) == 'A-Za-z0-9\\t\\x0b\\n\\r\\x0c! #"%$\'&)(+*,/.;:=@[\\\\_^`{}|~\\-\\]' \ No newline at end of file + + # this next one is ugly because it's being generated from a dict, so the order is not stable + nice = make_nice_charset_repr(string.printable) + chunks = ['A-Z','a-z','0-9','\\t','\\x0b','\\n','\\r','\\x0c','\\\\','\\-'] + chunks += list('! #"%$\'&)(+*,/.;:=@[]_^`{}|~') + assert all([chunk in nice for chunk in chunks]) # make sure every unit is in there, in some order + assert len(''.join(chunks))==len(nice) # make sure that's all that's in there + \ No newline at end of file Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Thu Apr 3 09:36:51 2008 @@ -1,5 +1,10 @@ """This test can read and parse PCRE regression tests to try out -on our regular expression library.""" +on our regular expression library. + +We currently only test against testoutput7 (DFA tests). We were doing +testoutput1, but that was PCRE matching, which was inconsistent with +our matching on strings like "[ab]{1,3}(ab*|b)" against 'aabbbb'. +""" # The PCRE library is distributed under the BSD license. We have borrowed some # of the regression tests (the ones that fit under the DFA scope) in order to @@ -80,6 +85,11 @@ py.test.skip("Still in progress") def create_pcre_pickle(file, picklefile): + """Create a filtered PCRE test file for the test. + + The pickle file was created by: + create_pcre_pickle(open('testoutput1','r'), open('testoutput1.pickle','w')) + """ import pickle lines = [line for line in file.readlines()] @@ -88,6 +98,11 @@ no_escape = r'(^|[^\\])(\\\\)*' # Make sure there's no escaping \ greedy_ops = re.compile(no_escape + r'[*?+}\(]\?') # Look for *? +? }? (? back_refs = re.compile(no_escape + r'\(.*' + no_escape + r'\\1') # find a \1 + caret_in_middle = re.compile(no_escape + r'[^\[\\]\^') + substr_quotes = re.compile(no_escape + r'(\\Q|\\E)') # PCRE allows \Q.....\E to quote substrings, we dont. + + # Perl allows single-digit hex escapes. Change \x0 -> \x00, for example + expand_perl_hex = re.compile(r'\\x([0-9a-fA-F]{1})(?=[^0-9a-fA-F]|$)') # suite = [ # [regex, flags, [(test,result),(test,result),...]] @@ -123,14 +138,19 @@ regex += matches[0][-2] # Add the backslash, if we gotta flags = matches[0][-1] # Get the flags for the regex - tests = [] + regex = expand_perl_hex.sub(lambda m: r'\x0'+m.group(1), regex) + tests = [] if greedy_ops.search(regex) or back_refs.search(regex): # Suppress complex features we can't do pass elif flags: # Suppress any test that requires PCRE flags pass + elif caret_in_middle.search(regex): + pass + elif substr_quotes.search(regex): + pass else: # In any other case, we're going to add the test # All the above test fall through and DONT get appended @@ -145,27 +165,34 @@ assert not test.endswith('\\\\\\') # Make sure not three \'s. otherwise this check will get ridiculous if not test.endswith('\\\\'): # Two \'s means a real \ test = test[:-1] - test = unescape(test) + test = expand_perl_hex.sub(lambda m: r'\x0'+m.group(1), test) + try: + test = unescape(test) + except Exception: + print "Warning: could not unescape %r" % test # Third line in the OUTPUT is the result, either: # ' 0: ...' for a match (but this is ONLY escaped by \x__ types) # 'No match' for no match - match = lines.pop(0).rstrip('\r\n') - match = re.sub(r'\\x([0-9a-fA-F]{2})', lambda m: chr(int(m.group(1),16)), match) - if match.startswith('No match'): - pass - elif match.startswith(' 0:'): - # Now we need to eat any further lines like: - # ' 1: ....' a subgroup match - while lines[0].strip(): - # ' 0+ ...' is also possible here - if lines[0][2] in [':','+']: - lines.pop(0) - else: - break - else: - print " *** %r ***" % match - raise Exception("Lost sync in output.") + # (other kinds exist, but we ignore them) + while lines: + match = lines.pop(0).rstrip('\r\n') + match = re.sub(r'\\x([0-9a-fA-F]{2})', lambda m: chr(int(m.group(1),16)), match) + if match.startswith('No match') or match.startswith('Error'): + break + elif match.startswith(' 0:'): + # Now we need to eat any further lines like: + # ' 1: ....' a subgroup match + while lines[0].strip(): + # ' 0+ ...' is also possible here + if lines[0][2] in [':','+']: + lines.pop(0) + else: + break + break + elif not match: + print " *** %r ***" % match + raise Exception("Lost sync in output.") tests.append((test,match)) pickle.dump(suite, picklefile) @@ -187,10 +214,14 @@ if not regex_to_use: #print " SKIPPED (Cant do blank regex)" return - - runner = make_runner(regex) + + print "%s:" % regex_to_use + + runner = make_runner(regex_to_use) # Now run the test expressions against the Regex for test, match in tests: + expect_match = (match != 'No match') + # Create possible subsequences that we should test if anchor_left: start_range = [0] @@ -206,25 +237,11 @@ # Search the possibilities for a match... for start, end in subseq_gen: attempt = test[start:end] - matched = runner.recognize(attempt) - if matched: + if runner.recognize(attempt): + assert expect_match and attempt==match[4:] break - - # Did we get what we expected? - if match == 'No match': - if matched: - assert "FALSE MATCH: regex==%r test==%r" % (regex, test) - else: - pass - #print " pass: regex==%r test==%r" % (regex, test) - elif match.startswith(' 0: '): - if not matched: - assert "MISSED: regex==%r test==%r" % (regex, test) - elif not attempt==match[4:]: - assert "BAD MATCH: regex==%r test==%r found==%r expect==%r" % (regex, test, attempt, match[4:]) - else: - pass - #print " pass: regex==%r test==%r" % (regex, test) + else: + assert not expect_match def run_pcre_tests(suite): """Run PCRE tests as given in suite.""" @@ -232,9 +249,15 @@ regex, flags, tests = suite.pop(0) yield run_individual_test, regex, tests - -def test_output1(): - suite = get_pcre_pickle(open('testoutput1.pickle','r')) +def test_output7(): + suite = get_pcre_pickle(open('testoutput7.pickle','r')) for test in run_pcre_tests(suite): yield test - \ No newline at end of file + +def generate_output7(): + """Create the testoutput1.pickle file from the PCRE file testoutput1""" + create_pcre_pickle(open('testoutput7','r'), open('testoutput7.pickle','w')) + +if __name__=="__main__": + for fcn, regex, tests in test_output7(): + fcn(regex,tests) \ No newline at end of file Modified: pypy/dist/pypy/rlib/parsing/test/testoutput1.pickle ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/testoutput1.pickle (original) +++ pypy/dist/pypy/rlib/parsing/test/testoutput1.pickle Thu Apr 3 09:36:51 2008 @@ -2318,632 +2318,632 @@ p1389 tp1390 aaa(lp1391 -S'(.*X|^B)' +S'^.*B' p1392 ag3 a(lp1393 -(S'abcde\n1234Xyz' +(S'**** Failers' p1394 -S' 0: 1234X' +S'No match' p1395 tp1396 -a(S'BarFoo' +a(S'abc\nB' p1397 -S' 0: B' +S'No match' p1398 tp1399 -a(S'*** Failers' -p1400 -S'No match' +aaa(lp1400 +S'^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' p1401 -tp1402 -a(S'abcde\nBar' +ag3 +a(lp1402 +(S'123456654321' p1403 -S'No match' +S' 0: 123456654321' p1404 tp1405 aaa(lp1406 -S'^.*B' +S'^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d' p1407 ag3 a(lp1408 -(S'**** Failers' +(S'123456654321' p1409 -S'No match' +S' 0: 123456654321' p1410 tp1411 -a(S'abc\nB' -p1412 -S'No match' -p1413 -tp1414 -aaa(lp1415 -S'^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' -p1416 -ag3 -a(lp1417 -(S'123456654321' -p1418 -S' 0: 123456654321' -p1419 -tp1420 -aaa(lp1421 -S'^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d' -p1422 -ag3 -a(lp1423 -(S'123456654321' -p1424 -S' 0: 123456654321' -p1425 -tp1426 -aaa(lp1427 +aaa(lp1412 S'^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]' -p1428 +p1413 ag3 -a(lp1429 +a(lp1414 (S'123456654321' -p1430 +p1415 S' 0: 123456654321' -p1431 -tp1432 -aaa(lp1433 +p1416 +tp1417 +aaa(lp1418 S'^[abc]{12}' -p1434 +p1419 ag3 -a(lp1435 +a(lp1420 (S'abcabcabcabc' -p1436 +p1421 S' 0: abcabcabcabc' -p1437 -tp1438 -aaa(lp1439 +p1422 +tp1423 +aaa(lp1424 S'^[a-c]{12}' -p1440 +p1425 ag3 -a(lp1441 +a(lp1426 (S'abcabcabcabc' -p1442 +p1427 S' 0: abcabcabcabc' -p1443 -tp1444 -aaa(lp1445 +p1428 +tp1429 +aaa(lp1430 S'^(a|b|c){12}' -p1446 +p1431 ag3 -a(lp1447 +a(lp1432 (S'abcabcabcabc' -p1448 +p1433 S' 0: abcabcabcabc' -p1449 -tp1450 -aaa(lp1451 +p1434 +tp1435 +aaa(lp1436 S'^[abcdefghijklmnopqrstuvwxy0123456789]' -p1452 +p1437 ag3 -a(lp1453 +a(lp1438 (S'n' -p1454 +p1439 S' 0: n' -p1455 -tp1456 +p1440 +tp1441 a(S'*** Failers' -p1457 +p1442 S'No match' -p1458 -tp1459 +p1443 +tp1444 a(g583 S'No match' -p1460 -tp1461 -aaa(lp1462 +p1445 +tp1446 +aaa(lp1447 S'abcde{0,0}' -p1463 +p1448 ag3 -a(lp1464 +a(lp1449 (S'abcd' -p1465 +p1450 S' 0: abcd' -p1466 -tp1467 +p1451 +tp1452 a(S'*** Failers' -p1468 +p1453 S'No match' -p1469 -tp1470 +p1454 +tp1455 a(S'abce' -p1471 +p1456 S'No match' -p1472 -tp1473 -aaa(lp1474 +p1457 +tp1458 +aaa(lp1459 S'ab[cd]{0,0}e' -p1475 +p1460 ag3 -a(lp1476 +a(lp1461 (S'abe' -p1477 +p1462 S' 0: abe' -p1478 -tp1479 +p1463 +tp1464 a(S'*** Failers' -p1480 +p1465 S'No match' -p1481 -tp1482 +p1466 +tp1467 a(S'abcde' -p1483 +p1468 S'No match' -p1484 -tp1485 -aaa(lp1486 +p1469 +tp1470 +aaa(lp1471 S'ab(c){0,0}d' -p1487 +p1472 ag3 -a(lp1488 +a(lp1473 (S'abd' -p1489 +p1474 S' 0: abd' -p1490 -tp1491 +p1475 +tp1476 a(S'*** Failers' -p1492 +p1477 S'No match' -p1493 -tp1494 +p1478 +tp1479 a(S'abcd' -p1495 +p1480 S'No match' -p1496 -tp1497 -aaa(lp1498 +p1481 +tp1482 +aaa(lp1483 S'a(b*)' -p1499 +p1484 ag3 -a(lp1500 +a(lp1485 (g592 S' 0: a' -p1501 -tp1502 +p1486 +tp1487 a(S'ab' -p1503 +p1488 S' 0: ab' -p1504 -tp1505 +p1489 +tp1490 a(S'abbbb' -p1506 +p1491 S' 0: abbbb' -p1507 -tp1508 +p1492 +tp1493 a(S'*** Failers' -p1509 +p1494 S' 0: a' -p1510 -tp1511 +p1495 +tp1496 a(S'bbbbb' -p1512 +p1497 S'No match' -p1513 -tp1514 -aaa(lp1515 +p1498 +tp1499 +aaa(lp1500 S'ab\\d{0}e' -p1516 +p1501 ag3 -a(lp1517 +a(lp1502 (S'abe' -p1518 +p1503 S' 0: abe' -p1519 -tp1520 +p1504 +tp1505 a(S'*** Failers' -p1521 +p1506 S'No match' -p1522 -tp1523 +p1507 +tp1508 a(S'ab1e' -p1524 +p1509 S'No match' -p1525 -tp1526 -aaa(lp1527 +p1510 +tp1511 +aaa(lp1512 S'"([^\\\\"]+|\\\\.)*"' -p1528 +p1513 ag3 -a(lp1529 +a(lp1514 (S'the "quick" brown fox' -p1530 +p1515 S' 0: "quick"' -p1531 -tp1532 +p1516 +tp1517 a(S'"the \\"quick\\" brown fox"' -p1533 +p1518 S' 0: "the \\"quick\\" brown fox"' -p1534 -tp1535 -aaa(lp1536 +p1519 +tp1520 +aaa(lp1521 S'a[^a]b' -p1537 +p1522 ag3 -a(lp1538 +a(lp1523 (S'acb' -p1539 +p1524 S' 0: acb' -p1540 -tp1541 +p1525 +tp1526 a(S'a\nb' -p1542 +p1527 S' 0: a\nb' -p1543 -tp1544 -aaa(lp1545 +p1528 +tp1529 +aaa(lp1530 S'a.b' -p1546 +p1531 ag3 -a(lp1547 +a(lp1532 (S'acb' -p1548 +p1533 S' 0: acb' -p1549 -tp1550 +p1534 +tp1535 a(S'*** Failers' -p1551 +p1536 S'No match' -p1552 -tp1553 +p1537 +tp1538 a(S'a\nb' -p1554 +p1539 S'No match' -p1555 -tp1556 -aaa(lp1557 -S'\\x0{ab}' -p1558 +p1540 +tp1541 +aaa(lp1542 +S'\\\\x00{ab}' +p1543 ag3 -a(lp1559 +a(lp1544 (S'\x00{ab}' -p1560 +p1545 S' 0: \x00{ab}' -p1561 -tp1562 -aaa(lp1563 +p1546 +tp1547 +aaa(lp1548 S'(A|B)*CD' -p1564 +p1549 ag3 -a(lp1565 +a(lp1550 (S'CD' -p1566 +p1551 S' 0: CD' -p1567 -tp1568 -aaa(lp1569 +p1552 +tp1553 +aaa(lp1554 S'(\\d+)(\\w)' -p1570 +p1555 ag3 -a(lp1571 +a(lp1556 (S'12345a' -p1572 +p1557 S' 0: 12345a' -p1573 -tp1574 +p1558 +tp1559 a(S'12345+' -p1575 +p1560 S' 0: 12345' -p1576 -tp1577 -aaa(lp1578 +p1561 +tp1562 +aaa(lp1563 S'(abc|)+' -p1579 +p1564 ag3 -a(lp1580 +a(lp1565 (S'abc' -p1581 +p1566 S' 0: abc' -p1582 -tp1583 +p1567 +tp1568 a(S'abcabc' -p1584 +p1569 S' 0: abcabc' -p1585 -tp1586 +p1570 +tp1571 a(S'abcabcabc' -p1587 +p1572 S' 0: abcabcabc' -p1588 -tp1589 +p1573 +tp1574 a(S'xyz' -p1590 +p1575 S' 0: ' -p1591 -tp1592 -aaa(lp1593 +p1576 +tp1577 +aaa(lp1578 S'([a]*)*' -p1594 +p1579 ag3 -a(lp1595 +a(lp1580 (g592 S' 0: a' -p1596 -tp1597 +p1581 +tp1582 a(S'aaaaa' -p1598 +p1583 S' 0: aaaaa' -p1599 -tp1600 -aaa(lp1601 +p1584 +tp1585 +aaa(lp1586 S'([ab]*)*' -p1602 +p1587 ag3 -a(lp1603 +a(lp1588 (g592 S' 0: a' -p1604 -tp1605 +p1589 +tp1590 a(g835 S' 0: b' -p1606 -tp1607 +p1591 +tp1592 a(S'ababab' -p1608 +p1593 S' 0: ababab' -p1609 -tp1610 +p1594 +tp1595 a(S'aaaabcde' -p1611 +p1596 S' 0: aaaab' -p1612 -tp1613 +p1597 +tp1598 a(S'bbbb' -p1614 +p1599 S' 0: bbbb' -p1615 -tp1616 -aaa(lp1617 +p1600 +tp1601 +aaa(lp1602 S'([^a]*)*' -p1618 +p1603 ag3 -a(lp1619 +a(lp1604 (g835 S' 0: b' -p1620 -tp1621 +p1605 +tp1606 a(S'bbbb' -p1622 +p1607 S' 0: bbbb' -p1623 -tp1624 +p1608 +tp1609 a(S'aaa' -p1625 +p1610 S' 0: ' -p1626 -tp1627 -aaa(lp1628 +p1611 +tp1612 +aaa(lp1613 S'([^ab]*)*' -p1629 +p1614 ag3 -a(lp1630 +a(lp1615 (S'cccc' -p1631 +p1616 S' 0: cccc' -p1632 -tp1633 +p1617 +tp1618 a(S'abab' -p1634 +p1619 S' 0: ' -p1635 -tp1636 -aaa(lp1637 +p1620 +tp1621 +aaa(lp1622 S'The case of aaaaaa is missed out below because I think Perl 5.005_02 gets' -p1638 +p1623 ag3 -a(lp1639 +a(lp1624 (S'/it wrong; it sets $1 to aaa rather than aa. Compare the following test,/' -p1640 +p1625 S'No match' -p1641 -tp1642 +p1626 +tp1627 a(S'/where it does set $1 to aa when matching aaaaaa./' -p1643 +p1628 S'No match' -p1644 -tp1645 -aaa(lp1646 +p1629 +tp1630 +aaa(lp1631 S'The following tests are taken from the Perl 5.005 test suite; some of them' -p1647 +p1632 ag3 -a(lp1648 +a(lp1633 (S"/are compatible with 5.004, but I'd rather not have to sort them out./" -p1649 +p1634 S'No match' -p1650 -tp1651 -aaa(lp1652 +p1635 +tp1636 +aaa(lp1637 S'abc' -p1653 +p1638 ag3 -a(lp1654 +a(lp1639 (S'abc' -p1655 +p1640 S' 0: abc' -p1656 -tp1657 +p1641 +tp1642 a(S'xabcy' -p1658 +p1643 S' 0: abc' -p1659 -tp1660 +p1644 +tp1645 a(S'ababc' -p1661 +p1646 S' 0: abc' -p1662 -tp1663 +p1647 +tp1648 a(S'*** Failers' -p1664 +p1649 S'No match' -p1665 -tp1666 +p1650 +tp1651 a(S'xbc' -p1667 +p1652 S'No match' -p1668 -tp1669 +p1653 +tp1654 a(S'axc' -p1670 +p1655 S'No match' -p1671 -tp1672 +p1656 +tp1657 a(S'abx' -p1673 +p1658 S'No match' -p1674 -tp1675 -aaa(lp1676 +p1659 +tp1660 +aaa(lp1661 S'ab*c' -p1677 +p1662 ag3 -a(lp1678 +a(lp1663 (S'abc' -p1679 +p1664 S' 0: abc' -p1680 -tp1681 -aaa(lp1682 +p1665 +tp1666 +aaa(lp1667 S'ab*bc' -p1683 +p1668 ag3 -a(lp1684 +a(lp1669 (S'abc' -p1685 +p1670 S' 0: abc' -p1686 -tp1687 +p1671 +tp1672 a(S'abbc' -p1688 +p1673 S' 0: abbc' -p1689 -tp1690 +p1674 +tp1675 a(S'abbbbc' -p1691 +p1676 S' 0: abbbbc' -p1692 -tp1693 -aaa(lp1694 +p1677 +tp1678 +aaa(lp1679 S'.{1}' -p1695 +p1680 ag3 -a(lp1696 +a(lp1681 (S'abbbbc' -p1697 +p1682 S' 0: a' -p1698 -tp1699 -aaa(lp1700 +p1683 +tp1684 +aaa(lp1685 S'.{3,4}' -p1701 +p1686 ag3 -a(lp1702 +a(lp1687 (S'abbbbc' -p1703 +p1688 S' 0: abbb' -p1704 -tp1705 -aaa(lp1706 +p1689 +tp1690 +aaa(lp1691 S'ab{0,}bc' -p1707 +p1692 ag3 -a(lp1708 +a(lp1693 (S'abbbbc' -p1709 +p1694 S' 0: abbbbc' +p1695 +tp1696 +aaa(lp1697 +S'ab+bc' +p1698 +ag3 +a(lp1699 +(S'abbc' +p1700 +S' 0: abbc' +p1701 +tp1702 +a(S'*** Failers' +p1703 +S'No match' +p1704 +tp1705 +a(S'abc' +p1706 +S'No match' +p1707 +tp1708 +a(S'abq' +p1709 +S'No match' p1710 tp1711 aaa(lp1712 -S'ab+bc' +S'ab{1,}bc' p1713 ag3 a(lp1714 -(S'abbc' -p1715 -S' 0: abbc' +aa(lp1715 +S'ab+bc' p1716 -tp1717 -a(S'*** Failers' +ag3 +a(lp1717 +(S'abbbbc' p1718 -S'No match' +S' 0: abbbbc' p1719 tp1720 -a(S'abc' -p1721 -S'No match' +aaa(lp1721 +S'ab{1,}bc' p1722 -tp1723 -a(S'abq' +ag3 +a(lp1723 +(S'abbbbc' p1724 -S'No match' +S' 0: abbbbc' p1725 tp1726 aaa(lp1727 -S'ab{1,}bc' +S'ab{1,3}bc' p1728 ag3 a(lp1729 -aa(lp1730 -S'ab+bc' -p1731 -ag3 -a(lp1732 (S'abbbbc' -p1733 +p1730 S' 0: abbbbc' +p1731 +tp1732 +aaa(lp1733 +S'ab{3,4}bc' p1734 -tp1735 -aaa(lp1736 -S'ab{1,}bc' -p1737 ag3 -a(lp1738 +a(lp1735 (S'abbbbc' -p1739 +p1736 S' 0: abbbbc' +p1737 +tp1738 +aaa(lp1739 +S'ab{4,5}bc' p1740 -tp1741 -aaa(lp1742 -S'ab{1,3}bc' -p1743 ag3 -a(lp1744 -(S'abbbbc' +a(lp1741 +(S'*** Failers' +p1742 +S'No match' +p1743 +tp1744 +a(S'abq' p1745 -S' 0: abbbbc' +S'No match' p1746 tp1747 -aaa(lp1748 -S'ab{3,4}bc' +a(S'abbbbc' +p1748 +S'No match' p1749 -ag3 -a(lp1750 -(S'abbbbc' -p1751 -S' 0: abbbbc' +tp1750 +aaa(lp1751 +S'ab?bc' p1752 -tp1753 -aaa(lp1754 -S'ab{4,5}bc' -p1755 ag3 -a(lp1756 -(S'*** Failers' +a(lp1753 +(S'abbc' +p1754 +S' 0: abbc' +p1755 +tp1756 +a(S'abc' p1757 -S'No match' +S' 0: abc' p1758 tp1759 -a(S'abq' -p1760 -S'No match' +aaa(lp1760 +S'ab{0,1}bc' p1761 -tp1762 -a(S'abbbbc' +ag3 +a(lp1762 +(S'abc' p1763 -S'No match' +S' 0: abc' p1764 tp1765 aaa(lp1766 @@ -2951,18 +2951,18 @@ p1767 ag3 a(lp1768 -(S'abbc' -p1769 -S' 0: abbc' +aa(lp1769 +S'ab?c' p1770 -tp1771 -a(S'abc' +ag3 +a(lp1771 +(S'abc' p1772 S' 0: abc' p1773 tp1774 aaa(lp1775 -S'ab{0,1}bc' +S'ab{0,1}c' p1776 ag3 a(lp1777 @@ -2972,2109 +2972,1852 @@ p1779 tp1780 aaa(lp1781 -S'ab?bc' +S'^abc$' p1782 ag3 a(lp1783 -aa(lp1784 -S'ab?c' -p1785 -ag3 -a(lp1786 (S'abc' -p1787 +p1784 S' 0: abc' +p1785 +tp1786 +a(S'*** Failers' +p1787 +S'No match' p1788 tp1789 -aaa(lp1790 -S'ab{0,1}c' +a(S'abbbbc' +p1790 +S'No match' p1791 -ag3 -a(lp1792 -(S'abc' +tp1792 +a(S'abcc' p1793 -S' 0: abc' +S'No match' p1794 tp1795 aaa(lp1796 -S'^abc$' +S'^abc' p1797 ag3 a(lp1798 -(S'abc' +(S'abcc' p1799 S' 0: abc' p1800 tp1801 -a(S'*** Failers' -p1802 -S'No match' +aaa(lp1802 +S'^abc$' p1803 -tp1804 -a(S'abbbbc' -p1805 -S'No match' +ag3 +a(lp1804 +aa(lp1805 +S'abc$' p1806 -tp1807 -a(S'abcc' +ag3 +a(lp1807 +(S'aabc' p1808 -S'No match' +S' 0: abc' p1809 tp1810 -aaa(lp1811 -S'^abc' +a(S'*** Failers' +p1811 +S'No match' p1812 -ag3 -a(lp1813 -(S'abcc' +tp1813 +a(S'aabc' p1814 S' 0: abc' p1815 tp1816 -aaa(lp1817 -S'^abc$' +a(S'aabcd' +p1817 +S'No match' p1818 -ag3 -a(lp1819 -aa(lp1820 -S'abc$' +tp1819 +aaa(lp1820 +S'^' p1821 ag3 a(lp1822 -(S'aabc' +(S'abc' p1823 -S' 0: abc' +S' 0: ' p1824 tp1825 -a(S'*** Failers' -p1826 -S'No match' +aaa(lp1826 +S'$' p1827 -tp1828 -a(S'aabc' +ag3 +a(lp1828 +(S'abc' p1829 -S' 0: abc' +S' 0: ' p1830 tp1831 -a(S'aabcd' -p1832 -S'No match' +aaa(lp1832 +S'a.c' p1833 -tp1834 -aaa(lp1835 -S'^' -p1836 ag3 -a(lp1837 +a(lp1834 (S'abc' +p1835 +S' 0: abc' +p1836 +tp1837 +a(S'axc' p1838 -S' 0: ' +S' 0: axc' p1839 tp1840 aaa(lp1841 -S'$' +S'a.*c' p1842 ag3 a(lp1843 -(S'abc' +(S'axyzc' p1844 -S' 0: ' +S' 0: axyzc' p1845 tp1846 aaa(lp1847 -S'a.c' +S'a[bc]d' p1848 ag3 a(lp1849 -(S'abc' +(S'abd' p1850 -S' 0: abc' +S' 0: abd' p1851 tp1852 -a(S'axc' +a(S'*** Failers' p1853 -S' 0: axc' +S'No match' p1854 tp1855 -aaa(lp1856 -S'a.*c' +a(S'axyzd' +p1856 +S'No match' p1857 -ag3 -a(lp1858 -(S'axyzc' +tp1858 +a(S'abc' p1859 -S' 0: axyzc' +S'No match' p1860 tp1861 aaa(lp1862 -S'a[bc]d' +S'a[b-d]e' p1863 ag3 a(lp1864 -(S'abd' +(S'ace' p1865 -S' 0: abd' +S' 0: ace' p1866 tp1867 -a(S'*** Failers' -p1868 -S'No match' -p1869 -tp1870 -a(S'axyzd' -p1871 -S'No match' -p1872 -tp1873 -a(S'abc' -p1874 -S'No match' -p1875 -tp1876 -aaa(lp1877 -S'a[b-d]e' -p1878 -ag3 -a(lp1879 -(S'ace' -p1880 -S' 0: ace' -p1881 -tp1882 -aaa(lp1883 +aaa(lp1868 S'a[b-d]' -p1884 +p1869 ag3 -a(lp1885 +a(lp1870 (S'aac' -p1886 +p1871 S' 0: ac' -p1887 -tp1888 -aaa(lp1889 +p1872 +tp1873 +aaa(lp1874 S'a[-b]' -p1890 +p1875 ag3 -a(lp1891 +a(lp1876 (S'a-' -p1892 +p1877 S' 0: a-' -p1893 -tp1894 -aaa(lp1895 +p1878 +tp1879 +aaa(lp1880 S'a[b-]' -p1896 +p1881 ag3 -a(lp1897 +a(lp1882 (S'a-' -p1898 +p1883 S' 0: a-' -p1899 -tp1900 -aaa(lp1901 +p1884 +tp1885 +aaa(lp1886 S'a]' -p1902 +p1887 ag3 -a(lp1903 +a(lp1888 (S'a]' -p1904 +p1889 S' 0: a]' -p1905 -tp1906 -aaa(lp1907 +p1890 +tp1891 +aaa(lp1892 S'a[]]b' -p1908 +p1893 ag3 -a(lp1909 +a(lp1894 (S'a]b' -p1910 +p1895 S' 0: a]b' +p1896 +tp1897 +aaa(lp1898 +S'a[^bc]d' +p1899 +ag3 +a(lp1900 +(S'aed' +p1901 +S' 0: aed' +p1902 +tp1903 +a(S'*** Failers' +p1904 +S'No match' +p1905 +tp1906 +a(S'abd' +p1907 +S'No match' +p1908 +tp1909 +a(S'abd' +p1910 +S'No match' p1911 tp1912 aaa(lp1913 -S'a[^bc]d' +S'a[^-b]c' p1914 ag3 a(lp1915 -(S'aed' +(S'adc' p1916 -S' 0: aed' +S' 0: adc' p1917 tp1918 -a(S'*** Failers' -p1919 -S'No match' +aaa(lp1919 +S'a[^]b]c' p1920 -tp1921 -a(S'abd' +ag3 +a(lp1921 +(S'adc' p1922 -S'No match' +S' 0: adc' p1923 tp1924 -a(S'abd' +a(S'*** Failers' p1925 S'No match' p1926 tp1927 -aaa(lp1928 -S'a[^-b]c' +a(S'a-c' +p1928 +S' 0: a-c' p1929 -ag3 -a(lp1930 -(S'adc' +tp1930 +a(S'a]c' p1931 -S' 0: adc' +S'No match' p1932 tp1933 aaa(lp1934 -S'a[^]b]c' +S'\\ba\\b' p1935 ag3 a(lp1936 -(S'adc' +(S'a-' p1937 -S' 0: adc' +S' 0: a' p1938 tp1939 -a(S'*** Failers' +a(S'-a' p1940 -S'No match' +S' 0: a' p1941 tp1942 -a(S'a-c' +a(S'-a-' p1943 -S' 0: a-c' +S' 0: a' p1944 tp1945 -a(S'a]c' -p1946 -S'No match' +aaa(lp1946 +S'\\by\\b' p1947 -tp1948 -aaa(lp1949 -S'\\ba\\b' -p1950 ag3 -a(lp1951 -(S'a-' +a(lp1948 +(S'*** Failers' +p1949 +S'No match' +p1950 +tp1951 +a(S'xy' p1952 -S' 0: a' +S'No match' p1953 tp1954 -a(S'-a' +a(S'yz' p1955 -S' 0: a' +S'No match' p1956 tp1957 -a(S'-a-' +a(S'xyz' p1958 -S' 0: a' +S'No match' p1959 tp1960 aaa(lp1961 -S'\\by\\b' +S'\\Ba\\B' p1962 ag3 a(lp1963 (S'*** Failers' p1964 -S'No match' +S' 0: a' p1965 tp1966 -a(S'xy' +a(S'a-' p1967 S'No match' p1968 tp1969 -a(S'yz' +a(S'-a' p1970 S'No match' p1971 tp1972 -a(S'xyz' +a(S'-a-' p1973 S'No match' p1974 tp1975 aaa(lp1976 -S'\\Ba\\B' +S'\\By\\b' p1977 ag3 a(lp1978 -(S'*** Failers' +(S'xy' p1979 -S' 0: a' +S' 0: y' p1980 tp1981 -a(S'a-' -p1982 -S'No match' -p1983 -tp1984 -a(S'-a' -p1985 -S'No match' -p1986 -tp1987 -a(S'-a-' -p1988 -S'No match' -p1989 -tp1990 -aaa(lp1991 -S'\\By\\b' -p1992 -ag3 -a(lp1993 -(S'xy' -p1994 -S' 0: y' -p1995 -tp1996 -aaa(lp1997 +aaa(lp1982 S'\\by\\B' -p1998 +p1983 ag3 -a(lp1999 +a(lp1984 (S'yz' -p2000 +p1985 S' 0: y' -p2001 -tp2002 -aaa(lp2003 +p1986 +tp1987 +aaa(lp1988 S'\\By\\B' -p2004 +p1989 ag3 -a(lp2005 +a(lp1990 (S'xyz' -p2006 +p1991 S' 0: y' -p2007 -tp2008 -aaa(lp2009 +p1992 +tp1993 +aaa(lp1994 S'\\w' -p2010 +p1995 ag3 -a(lp2011 +a(lp1996 (g592 S' 0: a' -p2012 -tp2013 -aaa(lp2014 +p1997 +tp1998 +aaa(lp1999 S'\\W' -p2015 +p2000 ag3 -a(lp2016 +a(lp2001 (S'-' -p2017 +p2002 S' 0: -' -p2018 -tp2019 +p2003 +tp2004 a(S'*** Failers' -p2020 +p2005 S' 0: *' -p2021 -tp2022 -a(g2017 +p2006 +tp2007 +a(g2002 S' 0: -' -p2023 -tp2024 +p2008 +tp2009 a(g592 S'No match' -p2025 -tp2026 -aaa(lp2027 +p2010 +tp2011 +aaa(lp2012 S'a\\sb' -p2028 +p2013 ag3 -a(lp2029 +a(lp2014 (S'a b' -p2030 +p2015 S' 0: a b' -p2031 -tp2032 -aaa(lp2033 +p2016 +tp2017 +aaa(lp2018 S'a\\Sb' -p2034 +p2019 ag3 -a(lp2035 +a(lp2020 (S'a-b' -p2036 +p2021 S' 0: a-b' -p2037 -tp2038 +p2022 +tp2023 a(S'*** Failers' -p2039 +p2024 S'No match' -p2040 -tp2041 +p2025 +tp2026 a(S'a-b' -p2042 +p2027 S' 0: a-b' -p2043 -tp2044 +p2028 +tp2029 a(S'a b' -p2045 +p2030 S'No match' -p2046 -tp2047 -aaa(lp2048 +p2031 +tp2032 +aaa(lp2033 S'\\d' -p2049 +p2034 ag3 -a(lp2050 +a(lp2035 (g332 S' 0: 1' -p2051 -tp2052 -aaa(lp2053 +p2036 +tp2037 +aaa(lp2038 S'\\D' -p2054 +p2039 ag3 -a(lp2055 -(g2017 +a(lp2040 +(g2002 S' 0: -' -p2056 -tp2057 +p2041 +tp2042 a(S'*** Failers' -p2058 +p2043 S' 0: *' -p2059 -tp2060 -a(g2017 +p2044 +tp2045 +a(g2002 S' 0: -' -p2061 -tp2062 +p2046 +tp2047 a(g332 S'No match' -p2063 -tp2064 -aaa(lp2065 +p2048 +tp2049 +aaa(lp2050 S'[\\w]' -p2066 +p2051 ag3 -a(lp2067 +a(lp2052 (g592 S' 0: a' -p2068 -tp2069 -aaa(lp2070 +p2053 +tp2054 +aaa(lp2055 S'[\\W]' -p2071 +p2056 ag3 -a(lp2072 -(g2017 +a(lp2057 +(g2002 S' 0: -' -p2073 -tp2074 +p2058 +tp2059 a(S'*** Failers' -p2075 +p2060 S' 0: *' -p2076 -tp2077 -a(g2017 +p2061 +tp2062 +a(g2002 S' 0: -' -p2078 -tp2079 +p2063 +tp2064 a(g592 S'No match' -p2080 -tp2081 -aaa(lp2082 +p2065 +tp2066 +aaa(lp2067 S'a[\\s]b' -p2083 +p2068 ag3 -a(lp2084 +a(lp2069 (S'a b' -p2085 +p2070 S' 0: a b' -p2086 -tp2087 -aaa(lp2088 +p2071 +tp2072 +aaa(lp2073 S'a[\\S]b' -p2089 +p2074 ag3 -a(lp2090 +a(lp2075 (S'a-b' -p2091 +p2076 S' 0: a-b' -p2092 -tp2093 +p2077 +tp2078 a(S'*** Failers' -p2094 +p2079 S'No match' -p2095 -tp2096 +p2080 +tp2081 a(S'a-b' -p2097 +p2082 S' 0: a-b' -p2098 -tp2099 +p2083 +tp2084 a(S'a b' -p2100 +p2085 S'No match' -p2101 -tp2102 -aaa(lp2103 +p2086 +tp2087 +aaa(lp2088 S'[\\d]' -p2104 +p2089 ag3 -a(lp2105 +a(lp2090 (g332 S' 0: 1' -p2106 -tp2107 -aaa(lp2108 +p2091 +tp2092 +aaa(lp2093 S'[\\D]' -p2109 +p2094 ag3 -a(lp2110 -(g2017 +a(lp2095 +(g2002 S' 0: -' -p2111 -tp2112 +p2096 +tp2097 a(S'*** Failers' -p2113 +p2098 S' 0: *' -p2114 -tp2115 -a(g2017 +p2099 +tp2100 +a(g2002 S' 0: -' -p2116 -tp2117 +p2101 +tp2102 a(g332 S'No match' +p2103 +tp2104 +aaa(lp2105 +S'ab|cd' +p2106 +ag3 +a(lp2107 +(S'abc' +p2108 +S' 0: ab' +p2109 +tp2110 +a(S'abcd' +p2111 +S' 0: ab' +p2112 +tp2113 +aaa(lp2114 +S'()ef' +p2115 +ag3 +a(lp2116 +(S'def' +p2117 +S' 0: ef' p2118 tp2119 aaa(lp2120 -S'ab|cd' +S'$b' p2121 ag3 a(lp2122 -(S'abc' -p2123 -S' 0: ab' +aa(lp2123 +S'a\\(b' p2124 -tp2125 -a(S'abcd' +ag3 +a(lp2125 +(S'a(b' p2126 -S' 0: ab' +S' 0: a(b' p2127 tp2128 aaa(lp2129 -S'()ef' +S'a\\(*b' p2130 ag3 a(lp2131 -(S'def' +(S'ab' p2132 -S' 0: ef' +S' 0: ab' p2133 tp2134 -aaa(lp2135 -S'$b' +a(S'a((b' +p2135 +S' 0: a((b' p2136 -ag3 -a(lp2137 -aa(lp2138 -S'a\\(b' +tp2137 +aaa(lp2138 +S'a\\\\b' p2139 ag3 a(lp2140 -(S'a(b' +(S'a\x08' p2141 -S' 0: a(b' +S'No match' p2142 tp2143 aaa(lp2144 -S'a\\(*b' +S'((a))' p2145 ag3 a(lp2146 -(S'ab' +(S'abc' p2147 -S' 0: ab' +S' 0: a' p2148 tp2149 -a(S'a((b' -p2150 -S' 0: a((b' -p2151 -tp2152 -aaa(lp2153 -S'a\\\\b' -p2154 -ag3 -a(lp2155 -(S'a\x08' -p2156 -S'No match' -p2157 -tp2158 -aaa(lp2159 -S'((a))' -p2160 -ag3 -a(lp2161 -(S'abc' -p2162 -S' 0: a' -p2163 -tp2164 -aaa(lp2165 +aaa(lp2150 S'(a)b(c)' -p2166 +p2151 ag3 -a(lp2167 +a(lp2152 (S'abc' -p2168 +p2153 S' 0: abc' -p2169 -tp2170 -aaa(lp2171 +p2154 +tp2155 +aaa(lp2156 S'a+b+c' -p2172 +p2157 ag3 -a(lp2173 +a(lp2158 (S'aabbabc' -p2174 +p2159 S' 0: abc' -p2175 -tp2176 -aaa(lp2177 +p2160 +tp2161 +aaa(lp2162 S'a{1,}b{1,}c' -p2178 +p2163 ag3 -a(lp2179 +a(lp2164 (S'aabbabc' -p2180 +p2165 S' 0: abc' -p2181 -tp2182 -aaa(lp2183 +p2166 +tp2167 +aaa(lp2168 S'(a+|b)*' -p2184 +p2169 ag3 -a(lp2185 +a(lp2170 (S'ab' -p2186 +p2171 S' 0: ab' -p2187 -tp2188 -aaa(lp2189 +p2172 +tp2173 +aaa(lp2174 S'(a+|b){0,}' -p2190 +p2175 ag3 -a(lp2191 +a(lp2176 (S'ab' -p2192 +p2177 S' 0: ab' -p2193 -tp2194 -aaa(lp2195 +p2178 +tp2179 +aaa(lp2180 S'(a+|b)+' -p2196 +p2181 ag3 -a(lp2197 +a(lp2182 (S'ab' -p2198 +p2183 S' 0: ab' -p2199 -tp2200 -aaa(lp2201 +p2184 +tp2185 +aaa(lp2186 S'(a+|b){1,}' -p2202 +p2187 ag3 -a(lp2203 +a(lp2188 (S'ab' -p2204 +p2189 S' 0: ab' -p2205 -tp2206 -aaa(lp2207 +p2190 +tp2191 +aaa(lp2192 S'(a+|b)?' -p2208 +p2193 ag3 -a(lp2209 +a(lp2194 (S'ab' -p2210 +p2195 S' 0: a' -p2211 -tp2212 -aaa(lp2213 +p2196 +tp2197 +aaa(lp2198 S'(a+|b){0,1}' -p2214 +p2199 ag3 -a(lp2215 +a(lp2200 (S'ab' -p2216 +p2201 S' 0: a' -p2217 -tp2218 -aaa(lp2219 +p2202 +tp2203 +aaa(lp2204 S'[^ab]*' -p2220 +p2205 ag3 -a(lp2221 +a(lp2206 (S'cde' -p2222 +p2207 S' 0: cde' -p2223 -tp2224 -aaa(lp2225 +p2208 +tp2209 +aaa(lp2210 S'abc' -p2226 +p2211 ag3 -a(lp2227 +a(lp2212 (S'*** Failers' -p2228 +p2213 S'No match' -p2229 -tp2230 +p2214 +tp2215 a(g835 S'No match' -p2231 -tp2232 -aaa(lp2233 +p2216 +tp2217 +aaa(lp2218 S'a*' -p2234 +p2219 ag3 -a(lp2235 -aa(lp2236 +a(lp2220 +aa(lp2221 S'([abc])*d' -p2237 +p2222 ag3 -a(lp2238 +a(lp2223 (S'abbbcd' -p2239 +p2224 S' 0: abbbcd' -p2240 -tp2241 -aaa(lp2242 +p2225 +tp2226 +aaa(lp2227 S'([abc])*bcd' -p2243 +p2228 ag3 -a(lp2244 +a(lp2229 (S'abcd' -p2245 +p2230 S' 0: abcd' -p2246 -tp2247 -aaa(lp2248 +p2231 +tp2232 +aaa(lp2233 S'a|b|c|d|e' -p2249 +p2234 ag3 -a(lp2250 +a(lp2235 (S'e' -p2251 +p2236 S' 0: e' -p2252 -tp2253 -aaa(lp2254 +p2237 +tp2238 +aaa(lp2239 S'(a|b|c|d|e)f' -p2255 +p2240 ag3 -a(lp2256 +a(lp2241 (S'ef' -p2257 +p2242 S' 0: ef' +p2243 +tp2244 +aaa(lp2245 +S'abcd*efg' +p2246 +ag3 +a(lp2247 +(S'abcdefg' +p2248 +S' 0: abcdefg' +p2249 +tp2250 +aaa(lp2251 +S'ab*' +p2252 +ag3 +a(lp2253 +(S'xabyabbbz' +p2254 +S' 0: ab' +p2255 +tp2256 +a(S'xayabbbz' +p2257 +S' 0: a' p2258 tp2259 aaa(lp2260 -S'abcd*efg' +S'(ab|cd)e' p2261 ag3 a(lp2262 -(S'abcdefg' +(S'abcde' p2263 -S' 0: abcdefg' +S' 0: cde' p2264 tp2265 aaa(lp2266 -S'ab*' +S'[abhgefdc]ij' p2267 ag3 a(lp2268 -(S'xabyabbbz' +(S'hij' p2269 -S' 0: ab' +S' 0: hij' p2270 tp2271 -a(S'xayabbbz' -p2272 -S' 0: a' +aaa(lp2272 +S'^(ab|cd)e' p2273 -tp2274 -aaa(lp2275 -S'(ab|cd)e' +ag3 +a(lp2274 +aa(lp2275 +S'(abc|)ef' p2276 ag3 a(lp2277 -(S'abcde' +(S'abcdef' p2278 -S' 0: cde' +S' 0: ef' p2279 tp2280 aaa(lp2281 -S'[abhgefdc]ij' +S'(a|b)c*d' p2282 ag3 a(lp2283 -(S'hij' +(S'abcd' p2284 -S' 0: hij' +S' 0: bcd' p2285 tp2286 aaa(lp2287 -S'^(ab|cd)e' +S'(ab|ab*)bc' p2288 ag3 a(lp2289 -aa(lp2290 -S'(abc|)ef' -p2291 -ag3 -a(lp2292 -(S'abcdef' -p2293 -S' 0: ef' -p2294 -tp2295 -aaa(lp2296 -S'(a|b)c*d' -p2297 -ag3 -a(lp2298 -(S'abcd' -p2299 -S' 0: bcd' -p2300 -tp2301 -aaa(lp2302 -S'(ab|ab*)bc' -p2303 -ag3 -a(lp2304 (S'abc' -p2305 +p2290 S' 0: abc' -p2306 -tp2307 -aaa(lp2308 +p2291 +tp2292 +aaa(lp2293 S'a([bc]*)c*' -p2309 +p2294 ag3 -a(lp2310 +a(lp2295 (S'abc' -p2311 +p2296 S' 0: abc' -p2312 -tp2313 -aaa(lp2314 +p2297 +tp2298 +aaa(lp2299 S'a([bc]*)(c*d)' -p2315 +p2300 ag3 -a(lp2316 +a(lp2301 (S'abcd' -p2317 +p2302 S' 0: abcd' -p2318 -tp2319 -aaa(lp2320 +p2303 +tp2304 +aaa(lp2305 S'a([bc]+)(c*d)' -p2321 +p2306 ag3 -a(lp2322 +a(lp2307 (S'abcd' -p2323 +p2308 S' 0: abcd' -p2324 -tp2325 -aaa(lp2326 +p2309 +tp2310 +aaa(lp2311 S'a([bc]*)(c+d)' -p2327 +p2312 ag3 -a(lp2328 +a(lp2313 (S'abcd' -p2329 +p2314 S' 0: abcd' -p2330 -tp2331 -aaa(lp2332 +p2315 +tp2316 +aaa(lp2317 S'a[bcd]*dcdcde' -p2333 +p2318 ag3 -a(lp2334 +a(lp2319 (S'adcdcde' -p2335 +p2320 S' 0: adcdcde' -p2336 -tp2337 -aaa(lp2338 +p2321 +tp2322 +aaa(lp2323 S'a[bcd]+dcdcde' -p2339 +p2324 ag3 -a(lp2340 +a(lp2325 (S'*** Failers' -p2341 +p2326 S'No match' -p2342 -tp2343 +p2327 +tp2328 a(S'abcde' -p2344 +p2329 S'No match' -p2345 -tp2346 +p2330 +tp2331 a(S'adcdcde' -p2347 +p2332 S'No match' -p2348 -tp2349 -aaa(lp2350 +p2333 +tp2334 +aaa(lp2335 S'(ab|a)b*c' -p2351 +p2336 ag3 -a(lp2352 +a(lp2337 (S'abc' -p2353 +p2338 S' 0: abc' -p2354 -tp2355 -aaa(lp2356 +p2339 +tp2340 +aaa(lp2341 S'((a)(b)c)(d)' -p2357 +p2342 ag3 -a(lp2358 +a(lp2343 (S'abcd' -p2359 +p2344 S' 0: abcd' -p2360 -tp2361 -aaa(lp2362 +p2345 +tp2346 +aaa(lp2347 S'[a-zA-Z_][a-zA-Z0-9_]*' -p2363 +p2348 ag3 -a(lp2364 +a(lp2349 (S'alpha' -p2365 +p2350 S' 0: alpha' -p2366 -tp2367 -aaa(lp2368 +p2351 +tp2352 +aaa(lp2353 S'^a(bc+|b[eh])g|.h$' -p2369 +p2354 ag3 -a(lp2370 +a(lp2355 (S'abh' -p2371 +p2356 S' 0: bh' -p2372 -tp2373 -aaa(lp2374 +p2357 +tp2358 +aaa(lp2359 S'(bc+d$|ef*g.|h?i(j|k))' -p2375 +p2360 ag3 -a(lp2376 +a(lp2361 (S'effgz' -p2377 +p2362 S' 0: effgz' -p2378 -tp2379 +p2363 +tp2364 a(S'ij' -p2380 +p2365 S' 0: ij' -p2381 -tp2382 -a(S'reffgz' -p2383 +p2366 +tp2367 +a(S'reffgz' +p2368 S' 0: effgz' -p2384 -tp2385 +p2369 +tp2370 a(S'*** Failers' -p2386 +p2371 S'No match' -p2387 -tp2388 +p2372 +tp2373 a(S'effg' -p2389 +p2374 S'No match' -p2390 -tp2391 +p2375 +tp2376 a(S'bcdd' -p2392 +p2377 S'No match' -p2393 -tp2394 -aaa(lp2395 +p2378 +tp2379 +aaa(lp2380 S'((((((((((a))))))))))' -p2396 +p2381 ag3 -a(lp2397 +a(lp2382 (g592 S' 0: a' -p2398 -tp2399 -aaa(lp2400 +p2383 +tp2384 +aaa(lp2385 S'(((((((((a)))))))))' -p2401 +p2386 ag3 -a(lp2402 +a(lp2387 (g592 S' 0: a' -p2403 -tp2404 -aaa(lp2405 +p2388 +tp2389 +aaa(lp2390 S'multiple words of text' -p2406 +p2391 ag3 -a(lp2407 +a(lp2392 (S'*** Failers' -p2408 +p2393 S'No match' -p2409 -tp2410 +p2394 +tp2395 a(S'aa' -p2411 +p2396 S'No match' -p2412 -tp2413 +p2397 +tp2398 a(S'uh-uh' -p2414 +p2399 S'No match' -p2415 -tp2416 -aaa(lp2417 +p2400 +tp2401 +aaa(lp2402 S'multiple words' -p2418 +p2403 ag3 -a(lp2419 +a(lp2404 (S'multiple words, yeah' -p2420 +p2405 S' 0: multiple words' -p2421 -tp2422 -aaa(lp2423 +p2406 +tp2407 +aaa(lp2408 S'(.*)c(.*)' -p2424 +p2409 ag3 -a(lp2425 +a(lp2410 (S'abcde' -p2426 +p2411 S' 0: abcde' -p2427 -tp2428 -aaa(lp2429 +p2412 +tp2413 +aaa(lp2414 S'\\((.*), (.*)\\)' -p2430 +p2415 ag3 -a(lp2431 +a(lp2416 (S'(a, b)' -p2432 +p2417 S' 0: (a, b)' -p2433 -tp2434 -aaa(lp2435 +p2418 +tp2419 +aaa(lp2420 S'[k]' -p2436 +p2421 ag3 -a(lp2437 -aa(lp2438 +a(lp2422 +aa(lp2423 S'abcd' -p2439 +p2424 ag3 -a(lp2440 +a(lp2425 (S'abcd' -p2441 +p2426 S' 0: abcd' -p2442 -tp2443 -aaa(lp2444 +p2427 +tp2428 +aaa(lp2429 S'a(bc)d' -p2445 +p2430 ag3 -a(lp2446 +a(lp2431 (S'abcd' -p2447 +p2432 S' 0: abcd' -p2448 -tp2449 -aaa(lp2450 +p2433 +tp2434 +aaa(lp2435 S'a[-]?c' -p2451 +p2436 ag3 -a(lp2452 +a(lp2437 (S'ac' -p2453 +p2438 S' 0: ac' -p2454 -tp2455 -aaa(lp2456 +p2439 +tp2440 +aaa(lp2441 S'((\\3|b)\\2(a)x)+' -p2457 +p2442 ag3 -a(lp2458 +a(lp2443 (S'aaaxabaxbaaxbbax' -p2459 +p2444 S' 0: bbax' -p2460 -tp2461 -aaa(lp2462 +p2445 +tp2446 +aaa(lp2447 S'((\\3|b)\\2(a)){2,}' -p2463 +p2448 ag3 -a(lp2464 +a(lp2449 (S'bbaababbabaaaaabbaaaabba' -p2465 +p2450 S' 0: bbaaaabba' -p2466 -tp2467 -aaa(lp2468 +p2451 +tp2452 +aaa(lp2453 S'((foo)|(bar))*' -p2469 +p2454 ag3 -a(lp2470 +a(lp2455 (S'foobar' -p2471 +p2456 S' 0: foobar' -p2472 -tp2473 -aaa(lp2474 +p2457 +tp2458 +aaa(lp2459 S'^(.+)?B' -p2475 +p2460 ag3 -a(lp2476 +a(lp2461 (S'AB' -p2477 +p2462 S' 0: AB' -p2478 -tp2479 -aaa(lp2480 +p2463 +tp2464 +aaa(lp2465 S'^([^a-z])|(\\^)$' -p2481 +p2466 ag3 -a(lp2482 +a(lp2467 (S'.' -p2483 +p2468 S' 0: .' -p2484 -tp2485 -aaa(lp2486 +p2469 +tp2470 +aaa(lp2471 S'^[<>]&' -p2487 +p2472 ag3 -a(lp2488 +a(lp2473 (S'<&OUT' -p2489 +p2474 S' 0: <&' -p2490 -tp2491 -aaa(lp2492 +p2475 +tp2476 +aaa(lp2477 S'^(){3,5}' -p2493 +p2478 ag3 -a(lp2494 +a(lp2479 (S'abc' -p2495 +p2480 S' 0: ' -p2496 -tp2497 -aaa(lp2498 +p2481 +tp2482 +aaa(lp2483 S'^(a+)*ax' -p2499 +p2484 ag3 -a(lp2500 +a(lp2485 (S'aax' -p2501 +p2486 S' 0: aax' -p2502 -tp2503 -aaa(lp2504 +p2487 +tp2488 +aaa(lp2489 S'^((a|b)+)*ax' -p2505 +p2490 ag3 -a(lp2506 +a(lp2491 (S'aax' -p2507 +p2492 S' 0: aax' -p2508 -tp2509 -aaa(lp2510 +p2493 +tp2494 +aaa(lp2495 S'^((a|bc)+)*ax' -p2511 +p2496 ag3 -a(lp2512 +a(lp2497 (S'aax' -p2513 +p2498 S' 0: aax' -p2514 -tp2515 -aaa(lp2516 +p2499 +tp2500 +aaa(lp2501 S'(a|x)*ab' -p2517 +p2502 ag3 -a(lp2518 +a(lp2503 (S'cab' -p2519 +p2504 S' 0: ab' -p2520 -tp2521 -aaa(lp2522 +p2505 +tp2506 +aaa(lp2507 S'(a)*ab' +p2508 +ag3 +a(lp2509 +(S'cab' +p2510 +S' 0: ab' +p2511 +tp2512 +aaa(lp2513 +S'foo\\w*\\d{4}baz' +p2514 +ag3 +a(lp2515 +(S'foobar1234baz' +p2516 +S' 0: foobar1234baz' +p2517 +tp2518 +aaa(lp2519 +S'^b' +p2520 +ag3 +a(lp2521 +aa(lp2522 +S'(\\w+:)+' p2523 ag3 a(lp2524 -(S'cab' +(S'one:' p2525 -S' 0: ab' +S' 0: one:' p2526 tp2527 aaa(lp2528 -S'foo\\w*\\d{4}baz' +S'([\\w:]+::)?(\\w+)$' p2529 ag3 a(lp2530 -(S'foobar1234baz' +(S'abcd' p2531 -S' 0: foobar1234baz' +S' 0: abcd' p2532 tp2533 -aaa(lp2534 -S'^b' +a(S'xy:z:::abcd' +p2534 +S' 0: xy:z:::abcd' p2535 -ag3 -a(lp2536 -aa(lp2537 -S'()^b' +tp2536 +aaa(lp2537 +S'^[^bcd]*(c+)' p2538 ag3 a(lp2539 -(S'*** Failers' +(S'aexycd' p2540 -S'No match' +S' 0: aexyc' p2541 tp2542 -a(S'a\nb\nc\n' -p2543 -S'No match' +aaa(lp2543 +S'(a*)b+' p2544 -tp2545 -a(S'a\nb\nc\n' +ag3 +a(lp2545 +(S'caab' p2546 -S'No match' +S' 0: aab' p2547 tp2548 aaa(lp2549 -S'(\\w+:)+' +S'([\\w:]+::)?(\\w+)$' p2550 ag3 a(lp2551 -(S'one:' +(S'abcd' p2552 -S' 0: one:' +S' 0: abcd' p2553 tp2554 -aaa(lp2555 -S'([\\w:]+::)?(\\w+)$' +a(S'xy:z:::abcd' +p2555 +S' 0: xy:z:::abcd' p2556 -ag3 -a(lp2557 -(S'abcd' +tp2557 +a(S'*** Failers' p2558 -S' 0: abcd' +S' 0: Failers' p2559 tp2560 -a(S'xy:z:::abcd' +a(S'abcd:' p2561 -S' 0: xy:z:::abcd' +S'No match' p2562 tp2563 -aaa(lp2564 -S'^[^bcd]*(c+)' +a(S'abcd:' +p2564 +S'No match' p2565 +tp2566 +aaa(lp2567 +S'^[^bcd]*(c+)' +p2568 ag3 -a(lp2566 +a(lp2569 (S'aexycd' -p2567 +p2570 S' 0: aexyc' -p2568 -tp2569 -aaa(lp2570 -S'(a*)b+' p2571 -ag3 -a(lp2572 -(S'caab' -p2573 -S' 0: aab' +tp2572 +aaa(lp2573 +S'(>a+)ab' p2574 -tp2575 -aaa(lp2576 -S'([\\w:]+::)?(\\w+)$' +ag3 +a(lp2575 +aa(lp2576 +S'([[:]+)' p2577 ag3 a(lp2578 -(S'abcd' +(S'a:[b]:' p2579 -S' 0: abcd' +S' 0: :[' p2580 tp2581 -a(S'xy:z:::abcd' -p2582 -S' 0: xy:z:::abcd' +aaa(lp2582 +S'([[=]+)' p2583 -tp2584 -a(S'*** Failers' +ag3 +a(lp2584 +(S'a=[b]=' p2585 -S' 0: Failers' +S' 0: =[' p2586 tp2587 -a(S'abcd:' -p2588 -S'No match' +aaa(lp2588 +S'([[.]+)' p2589 -tp2590 -a(S'abcd:' +ag3 +a(lp2590 +(S'a.[b].' p2591 -S'No match' +S' 0: .[' p2592 tp2593 aaa(lp2594 -S'^[^bcd]*(c+)' +S'a\\Z' p2595 ag3 a(lp2596 -(S'aexycd' +(S'*** Failers' p2597 -S' 0: aexyc' +S'No match' p2598 tp2599 -aaa(lp2600 -S'(>a+)ab' -p2601 -ag3 -a(lp2602 -aa(lp2603 -S'([[:]+)' -p2604 -ag3 -a(lp2605 -(S'a:[b]:' -p2606 -S' 0: :[' -p2607 -tp2608 -aaa(lp2609 -S'([[=]+)' -p2610 -ag3 -a(lp2611 -(S'a=[b]=' -p2612 -S' 0: =[' -p2613 -tp2614 -aaa(lp2615 -S'([[.]+)' -p2616 -ag3 -a(lp2617 -(S'a.[b].' -p2618 -S' 0: .[' -p2619 -tp2620 -aaa(lp2621 -S'a\\Z' -p2622 -ag3 -a(lp2623 -(S'*** Failers' -p2624 -S'No match' -p2625 -tp2626 a(S'aaab' -p2627 +p2600 S'No match' -p2628 -tp2629 +p2601 +tp2602 a(S'a\nb\n' -p2630 +p2603 S'No match' -p2631 -tp2632 -aaa(lp2633 +p2604 +tp2605 +aaa(lp2606 S'b\\Z' -p2634 +p2607 ag3 -a(lp2635 +a(lp2608 (S'a\nb\n' -p2636 +p2609 S' 0: b' -p2637 -tp2638 -aaa(lp2639 +p2610 +tp2611 +aaa(lp2612 S'b\\z' -p2640 +p2613 ag3 -a(lp2641 -aa(lp2642 +a(lp2614 +aa(lp2615 S'b\\Z' -p2643 +p2616 ag3 -a(lp2644 +a(lp2617 (S'a\nb' -p2645 +p2618 S' 0: b' -p2646 -tp2647 -aaa(lp2648 +p2619 +tp2620 +aaa(lp2621 S'b\\z' -p2649 +p2622 ag3 -a(lp2650 +a(lp2623 (S'a\nb' -p2651 +p2624 S' 0: b' -p2652 -tp2653 +p2625 +tp2626 a(S'*** Failers' -p2654 +p2627 S'No match' -p2655 -tp2656 -aaa(lp2657 +p2628 +tp2629 +aaa(lp2630 S'((Z)+|A)*' -p2658 +p2631 ag3 -a(lp2659 +a(lp2632 (S'ZABCDEFG' -p2660 +p2633 S' 0: ZA' -p2661 -tp2662 -aaa(lp2663 +p2634 +tp2635 +aaa(lp2636 S'(Z()|A)*' -p2664 +p2637 ag3 -a(lp2665 +a(lp2638 (S'ZABCDEFG' -p2666 +p2639 S' 0: ZA' -p2667 -tp2668 -aaa(lp2669 +p2640 +tp2641 +aaa(lp2642 S'(Z(())|A)*' -p2670 +p2643 ag3 -a(lp2671 +a(lp2644 (S'ZABCDEFG' -p2672 +p2645 S' 0: ZA' -p2673 -tp2674 -aaa(lp2675 +p2646 +tp2647 +aaa(lp2648 S'^[a-\\d]' -p2676 +p2649 ag3 -a(lp2677 +a(lp2650 (S'abcde' -p2678 +p2651 S' 0: a' -p2679 -tp2680 +p2652 +tp2653 a(S'-things' -p2681 +p2654 S' 0: -' -p2682 -tp2683 +p2655 +tp2656 a(S'0digit' -p2684 +p2657 S' 0: 0' -p2685 -tp2686 +p2658 +tp2659 a(S'*** Failers' -p2687 +p2660 S'No match' -p2688 -tp2689 +p2661 +tp2662 a(S'bcdef' -p2690 +p2663 S'No match' -p2691 -tp2692 -aaa(lp2693 +p2664 +tp2665 +aaa(lp2666 S'^[\\d-a]' -p2694 +p2667 ag3 -a(lp2695 +a(lp2668 (S'abcde' -p2696 +p2669 S' 0: a' -p2697 -tp2698 +p2670 +tp2671 a(S'-things' -p2699 +p2672 S' 0: -' -p2700 -tp2701 +p2673 +tp2674 a(S'0digit' -p2702 +p2675 S' 0: 0' -p2703 -tp2704 +p2676 +tp2677 a(S'*** Failers' -p2705 +p2678 S'No match' -p2706 -tp2707 +p2679 +tp2680 a(S'bcdef' -p2708 +p2681 S'No match' -p2709 -tp2710 -aaa(lp2711 +p2682 +tp2683 +aaa(lp2684 S'[[:space:]]+' -p2712 +p2685 ag3 -a(lp2713 +a(lp2686 (S'> \t\n\x0c\r\x0b<' -p2714 +p2687 S' 0: \t\n\x0c\r\x0b' -p2715 -tp2716 -aaa(lp2717 +p2688 +tp2689 +aaa(lp2690 S'[[:blank:]]+' -p2718 +p2691 ag3 -a(lp2719 +a(lp2692 (S'> \t\n\x0c\r\x0b<' -p2720 +p2693 S' 0: \t' -p2721 -tp2722 -aaa(lp2723 +p2694 +tp2695 +aaa(lp2696 S'[\\s]+' -p2724 +p2697 ag3 -a(lp2725 +a(lp2698 (S'> \t\n\x0c\r\x0b<' -p2726 +p2699 S' 0: \t\n\x0c\r' -p2727 -tp2728 -aaa(lp2729 +p2700 +tp2701 +aaa(lp2702 S'\\s+' -p2730 +p2703 ag3 -a(lp2731 +a(lp2704 (S'> \t\n\x0c\r\x0b<' -p2732 +p2705 S' 0: \t\n\x0c\r' -p2733 -tp2734 -aaa(lp2735 -S'abc\\Qabc\\Eabc' -p2736 -ag3 -a(lp2737 -(S'abcabcabc' -p2738 -S' 0: abcabcabc' -p2739 -tp2740 -aaa(lp2741 -S'abc\\Q(*+|\\Eabc' -p2742 -ag3 -a(lp2743 -(S'abc(*+|abc' -p2744 -S' 0: abc(*+|abc' -p2745 -tp2746 -aaa(lp2747 -S'\\Qabc\\$xyz\\E' -p2748 -ag3 -a(lp2749 -(S'abc\\$xyz' -p2750 -S' 0: abc\\$xyz' -p2751 -tp2752 -aaa(lp2753 -S'\\Qabc\\E\\$\\Qxyz\\E' -p2754 -ag3 -a(lp2755 -(S'abc$xyz' -p2756 -S' 0: abc$xyz' -p2757 -tp2758 -aaa(lp2759 +p2706 +tp2707 +aaa(lp2708 S'\\Gabc' -p2760 +p2709 ag3 -a(lp2761 +a(lp2710 (S'abc' -p2762 +p2711 S' 0: abc' -p2763 -tp2764 +p2712 +tp2713 a(S'*** Failers' -p2765 +p2714 S'No match' -p2766 -tp2767 +p2715 +tp2716 a(S'xyzabc' -p2768 -S'No match' -p2769 -tp2770 -aaa(lp2771 -S'-- This tests for an IPv6 address in the form where it can have up to --' -p2772 -ag3 -a(lp2773 -(S'/-- eight components, one and only one of which is empty. This must be --/' -p2774 -S'No match' -p2775 -tp2776 -a(S'/-- an internal component. --/' -p2777 -S'No match' -p2778 -tp2779 -aaa(lp2780 -S'[z\\Qa-d]\\E]' -p2781 -ag3 -a(lp2782 -(g583 -S' 0: z' -p2783 -tp2784 -a(g592 -S' 0: a' -p2785 -tp2786 -a(g2017 -S' 0: -' -p2787 -tp2788 -a(S'd' -p2789 -S' 0: d' -p2790 -tp2791 -a(S']' -p2792 -S' 0: ]' -p2793 -tp2794 -a(S'*** Failers' -p2795 -S' 0: a' -p2796 -tp2797 -a(g835 +p2717 S'No match' -p2798 -tp2799 -aaa(lp2800 +p2718 +tp2719 +aaa(lp2720 S'[\\z\\C]' -p2801 +p2721 ag3 -a(lp2802 +a(lp2722 (g583 S' 0: z' -p2803 -tp2804 +p2723 +tp2724 a(S'C' -p2805 +p2725 S' 0: C' -p2806 -tp2807 -aaa(lp2808 +p2726 +tp2727 +aaa(lp2728 S'\\M' -p2809 +p2729 ag3 -a(lp2810 +a(lp2730 (S'M' -p2811 +p2731 S' 0: M' -p2812 -tp2813 -aaa(lp2814 +p2732 +tp2733 +aaa(lp2734 S'(a+)*b' -p2815 +p2735 ag3 -a(lp2816 +a(lp2736 (S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -p2817 +p2737 S'No match' -p2818 -tp2819 -aaa(lp2820 +p2738 +tp2739 +aaa(lp2740 S'\xc5\xe6\xe5\xe4[\xe0-\xff\xc0-\xdf]+' -p2821 +p2741 ag3 -a(lp2822 +a(lp2742 (S'\xc5\xe6\xe5\xe4\xe0' -p2823 +p2743 S' 0: \xc5\xe6\xe5\xe4\xe0' -p2824 -tp2825 +p2744 +tp2745 a(S'\xc5\xe6\xe5\xe4\xff' -p2826 +p2746 S' 0: \xc5\xe6\xe5\xe4\xff' -p2827 -tp2828 +p2747 +tp2748 a(S'\xc5\xe6\xe5\xe4\xc0' -p2829 +p2749 S' 0: \xc5\xe6\xe5\xe4\xc0' -p2830 -tp2831 +p2750 +tp2751 a(S'\xc5\xe6\xe5\xe4\xdf' -p2832 +p2752 S' 0: \xc5\xe6\xe5\xe4\xdf' -p2833 -tp2834 -aaa(lp2835 +p2753 +tp2754 +aaa(lp2755 S'[[,abc,]+]' -p2836 +p2756 ag3 -a(lp2837 +a(lp2757 (S'abc]' -p2838 +p2758 S' 0: abc]' -p2839 -tp2840 +p2759 +tp2760 a(S'a,b]' -p2841 +p2761 S' 0: a,b]' -p2842 -tp2843 +p2762 +tp2763 a(S'[a,b,c]' -p2844 +p2764 S' 0: [a,b,c]' -p2845 -tp2846 -aaa(lp2847 +p2765 +tp2766 +aaa(lp2767 S'a*b*\\w' -p2848 +p2768 ag3 -a(lp2849 +a(lp2769 (S'aaabbbb' -p2850 +p2770 S' 0: aaabbbb' -p2851 -tp2852 +p2771 +tp2772 a(S'aaaa' -p2853 +p2773 S' 0: aaaa' -p2854 -tp2855 +p2774 +tp2775 a(g592 S' 0: a' -p2856 -tp2857 -aaa(lp2858 +p2776 +tp2777 +aaa(lp2778 S'a*b?\\w' -p2859 +p2779 ag3 -a(lp2860 +a(lp2780 (S'aaabbbb' -p2861 +p2781 S' 0: aaabb' -p2862 -tp2863 +p2782 +tp2783 a(S'aaaa' -p2864 +p2784 S' 0: aaaa' -p2865 -tp2866 +p2785 +tp2786 a(g592 S' 0: a' -p2867 -tp2868 -aaa(lp2869 +p2787 +tp2788 +aaa(lp2789 S'a*b{0,4}\\w' -p2870 +p2790 ag3 -a(lp2871 +a(lp2791 (S'aaabbbb' -p2872 +p2792 S' 0: aaabbbb' -p2873 -tp2874 +p2793 +tp2794 a(S'aaaa' -p2875 +p2795 S' 0: aaaa' -p2876 -tp2877 +p2796 +tp2797 a(g592 S' 0: a' -p2878 -tp2879 -aaa(lp2880 +p2798 +tp2799 +aaa(lp2800 S'a*b{0,}\\w' -p2881 +p2801 ag3 -a(lp2882 +a(lp2802 (S'aaabbbb' -p2883 +p2803 S' 0: aaabbbb' -p2884 -tp2885 +p2804 +tp2805 a(S'aaaa' -p2886 +p2806 S' 0: aaaa' -p2887 -tp2888 +p2807 +tp2808 a(g592 S' 0: a' -p2889 -tp2890 -aaa(lp2891 +p2809 +tp2810 +aaa(lp2811 S'a*\\d*\\w' -p2892 +p2812 ag3 -a(lp2893 +a(lp2813 (S'0a' -p2894 +p2814 S' 0: 0a' -p2895 -tp2896 +p2815 +tp2816 a(g592 S' 0: a' -p2897 -tp2898 -aaa(lp2899 +p2817 +tp2818 +aaa(lp2819 S'^\\w+=.*(\\\\\\n.*)*' -p2900 +p2820 ag3 -a(lp2901 +a(lp2821 (S'abc=xyz\\\npqr' -p2902 +p2822 S' 0: abc=xyz\\' -p2903 -tp2904 -aaa(lp2905 -S'^\\Eabc' -p2906 -ag3 -a(lp2907 -(S'abc' -p2908 -S' 0: abc' -p2909 -tp2910 -aaa(lp2911 -S'^[\\Eabc]' -p2912 -ag3 -a(lp2913 -(g592 -S' 0: a' -p2914 -tp2915 -a(S'** Failers' -p2916 -S'No match' -p2917 -tp2918 -a(S'E' -p2919 -S'No match' -p2920 -tp2921 -aaa(lp2922 -S'^[a-\\Ec]' -p2923 -ag3 -a(lp2924 -(g835 -S' 0: b' -p2925 -tp2926 -a(S'** Failers' -p2927 -S'No match' -p2928 -tp2929 -a(g2017 -S'No match' -p2930 -tp2931 -a(g2919 -S'No match' -p2932 -tp2933 -aaa(lp2934 -S'^[a\\E\\E-\\Ec]' -p2935 -ag3 -a(lp2936 -(g835 -S' 0: b' -p2937 -tp2938 -a(S'** Failers' -p2939 -S'No match' -p2940 -tp2941 -a(g2017 -S'No match' -p2942 -tp2943 -a(g2919 -S'No match' -p2944 -tp2945 -aaa(lp2946 -S'^[\\E\\Qa\\E-\\Qz\\E]+' -p2947 -ag3 -a(lp2948 -(g835 -S' 0: b' -p2949 -tp2950 -a(S'** Failers' -p2951 -S'No match' -p2952 -tp2953 -a(g2017 -S'No match' -p2954 -tp2955 -aaa(lp2956 -S'^[a\\Q]bc\\E]' -p2957 -ag3 -a(lp2958 -(g592 -S' 0: a' -p2959 -tp2960 -a(g2792 -S' 0: ]' -p2961 -tp2962 -a(S'c' -p2963 -S' 0: c' -p2964 -tp2965 -aaa(lp2966 -S'^[a-\\Q\\E]' -p2967 -ag3 -a(lp2968 -(g592 -S' 0: a' -p2969 -tp2970 -a(g2017 -S' 0: -' -p2971 -tp2972 -aaa(lp2973 +p2823 +tp2824 +aaa(lp2825 S'^(a()*)*' -p2974 +p2826 ag3 -a(lp2975 +a(lp2827 (S'aaaa' -p2976 +p2828 S' 0: aaaa' -p2977 -tp2978 -aaa(lp2979 +p2829 +tp2830 +aaa(lp2831 S'^(a()+)+' -p2980 +p2832 ag3 -a(lp2981 +a(lp2833 (S'aaaa' -p2982 +p2834 S' 0: aaaa' -p2983 -tp2984 -aaa(lp2985 +p2835 +tp2836 +aaa(lp2837 S'(a|)*\\d' -p2986 +p2838 ag3 -a(lp2987 +a(lp2839 (S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -p2988 +p2840 S'No match' -p2989 -tp2990 +p2841 +tp2842 a(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4' -p2991 +p2843 S' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4' -p2992 -tp2993 -aaa(lp2994 +p2844 +tp2845 +aaa(lp2846 S'(.*(.)?)*' -p2995 +p2847 ag3 -a(lp2996 +a(lp2848 (S'abcd' -p2997 +p2849 S' 0: abcd' -p2998 -tp2999 -aaa(lp3000 +p2850 +tp2851 +aaa(lp2852 S'[[:abcd:xyz]]' -p3001 +p2853 ag3 -a(lp3002 +a(lp2854 (S'a]' -p3003 +p2855 S' 0: a]' -p3004 -tp3005 +p2856 +tp2857 a(S':]' -p3006 +p2858 S' 0: :]' -p3007 -tp3008 -aaa(lp3009 +p2859 +tp2860 +aaa(lp2861 S'[abc[:x\\]pqr]' -p3010 +p2862 ag3 -a(lp3011 +a(lp2863 (g592 S' 0: a' -p3012 -tp3013 +p2864 +tp2865 a(S'[' -p3014 +p2866 S' 0: [' -p3015 -tp3016 +p2867 +tp2868 a(g441 S' 0: :' -p3017 -tp3018 -a(g2792 +p2869 +tp2870 +a(S']' +p2871 S' 0: ]' -p3019 -tp3020 +p2872 +tp2873 a(S'p' -p3021 +p2874 S' 0: p' -p3022 -tp3023 -aaa(lp3024 +p2875 +tp2876 +aaa(lp2877 S' End of testinput1 ' -p3025 +p2878 ag3 -a(lp3026 +a(lp2879 aa. \ No newline at end of file Added: pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle Thu Apr 3 09:36:51 2008 @@ -0,0 +1,6238 @@ +(lp0 +(lp1 +S'abc' +p2 +aS'' +p3 +a(lp4 +(S'abc' +p5 +S' 0: abc' +p6 +tp7 +aaa(lp8 +S'ab*c' +p9 +ag3 +a(lp10 +(S'abc' +p11 +S' 0: abc' +p12 +tp13 +a(S'abbbbc' +p14 +S' 0: abbbbc' +p15 +tp16 +a(S'ac' +p17 +S' 0: ac' +p18 +tp19 +aaa(lp20 +S'ab+c' +p21 +ag3 +a(lp22 +(S'abc' +p23 +S' 0: abc' +p24 +tp25 +a(S'abbbbbbc' +p26 +S' 0: abbbbbbc' +p27 +tp28 +a(S'*** Failers' +p29 +S'No match' +p30 +tp31 +a(S'ac' +p32 +S'No match' +p33 +tp34 +a(S'ab' +p35 +S'No match' +p36 +tp37 +aaa(lp38 +S'a*' +p39 +ag3 +a(lp40 +(S'a' +p41 +S' 0: a' +p42 +tp43 +a(S'aaaaaaaaaaaaaaaaa' +p44 +S' 0: aaaaaaaaaaaaaaaaa' +p45 +tp46 +a(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +p47 +S' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +p48 +tp49 +a(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaF' +p50 +S' 0: ' +p51 +tp52 +aaa(lp53 +S'(a|abcd|african)' +p54 +ag3 +a(lp55 +(g41 +S' 0: a' +p56 +tp57 +a(S'abcd' +p58 +S' 0: abcd' +p59 +tp60 +a(S'african' +p61 +S' 0: african' +p62 +tp63 +aaa(lp64 +S'^abc' +p65 +ag3 +a(lp66 +(S'abcdef' +p67 +S' 0: abc' +p68 +tp69 +a(S'*** Failers' +p70 +S'No match' +p71 +tp72 +a(S'xyzabc' +p73 +S'No match' +p74 +tp75 +a(S'xyz\nabc' +p76 +S'No match' +p77 +tp78 +aaa(lp79 +S'\\Aabc' +p80 +ag3 +a(lp81 +(S'abcdef' +p82 +S' 0: abc' +p83 +tp84 +a(S'*** Failers' +p85 +S'No match' +p86 +tp87 +a(S'xyzabc' +p88 +S'No match' +p89 +tp90 +a(S'xyz\nabc' +p91 +S'No match' +p92 +tp93 +aaa(lp94 +S'\\Gabc' +p95 +ag3 +a(lp96 +(S'abcdef' +p97 +S' 0: abc' +p98 +tp99 +a(S'xyzabc>3' +p100 +S' 0: abc' +p101 +tp102 +a(S'*** Failers' +p103 +S'No match' +p104 +tp105 +a(S'xyzabc' +p106 +S'No match' +p107 +tp108 +a(S'xyzabc>2' +p109 +S'No match' +p110 +tp111 +aaa(lp112 +S'x\\dy\\Dz' +p113 +ag3 +a(lp114 +(S'x9yzz' +p115 +S' 0: x9yzz' +p116 +tp117 +a(S'x0y+z' +p118 +S' 0: x0y+z' +p119 +tp120 +a(S'*** Failers' +p121 +S'No match' +p122 +tp123 +a(S'xyz' +p124 +S'No match' +p125 +tp126 +a(S'xxy0z' +p127 +S'No match' +p128 +tp129 +aaa(lp130 +S'x\\sy\\Sz' +p131 +ag3 +a(lp132 +(S'x yzz' +p133 +S' 0: x yzz' +p134 +tp135 +a(S'x y+z' +p136 +S' 0: x y+z' +p137 +tp138 +a(S'*** Failers' +p139 +S'No match' +p140 +tp141 +a(S'xyz' +p142 +S'No match' +p143 +tp144 +a(S'xxyyz' +p145 +S'No match' +p146 +tp147 +aaa(lp148 +S'x\\wy\\Wz' +p149 +ag3 +a(lp150 +(S'xxy+z' +p151 +S' 0: xxy+z' +p152 +tp153 +a(S'*** Failers' +p154 +S'No match' +p155 +tp156 +a(S'xxy0z' +p157 +S'No match' +p158 +tp159 +a(S'x+y+z' +p160 +S'No match' +p161 +tp162 +aaa(lp163 +S'x.y' +p164 +ag3 +a(lp165 +(S'x+y' +p166 +S' 0: x+y' +p167 +tp168 +a(S'x-y' +p169 +S' 0: x-y' +p170 +tp171 +a(S'*** Failers' +p172 +S'No match' +p173 +tp174 +a(S'x\ny' +p175 +S'No match' +p176 +tp177 +aaa(lp178 +S'a\\d\\z' +p179 +ag3 +a(lp180 +(S'ba0' +p181 +S' 0: a0' +p182 +tp183 +a(S'*** Failers' +p184 +S'No match' +p185 +tp186 +a(S'ba0\n' +p187 +S'No match' +p188 +tp189 +a(S'ba0\ncd' +p190 +S'No match' +p191 +tp192 +aaa(lp193 +S'a\\d\\Z' +p194 +ag3 +a(lp195 +(S'ba0' +p196 +S' 0: a0' +p197 +tp198 +a(S'ba0\n' +p199 +S' 0: a0' +p200 +tp201 +a(S'*** Failers' +p202 +S'No match' +p203 +tp204 +a(S'ba0\ncd' +p205 +S'No match' +p206 +tp207 +aaa(lp208 +S'a\\d$' +p209 +ag3 +a(lp210 +(S'ba0' +p211 +S' 0: a0' +p212 +tp213 +a(S'ba0\n' +p214 +S' 0: a0' +p215 +tp216 +a(S'*** Failers' +p217 +S'No match' +p218 +tp219 +a(S'ba0\ncd' +p220 +S'No match' +p221 +tp222 +aaa(lp223 +S'[^a]' +p224 +ag3 +a(lp225 +(S'abcd' +p226 +S' 0: b' +p227 +tp228 +aaa(lp229 +S'ab?\\w' +p230 +ag3 +a(lp231 +(S'abz' +p232 +S' 0: abz' +p233 +tp234 +a(S'abbz' +p235 +S' 0: abb' +p236 +tp237 +a(S'azz' +p238 +S' 0: az' +p239 +tp240 +aaa(lp241 +S'x{0,3}yz' +p242 +ag3 +a(lp243 +(S'ayzq' +p244 +S' 0: yz' +p245 +tp246 +a(S'axyzq' +p247 +S' 0: xyz' +p248 +tp249 +a(S'axxyz' +p250 +S' 0: xxyz' +p251 +tp252 +a(S'axxxyzq' +p253 +S' 0: xxxyz' +p254 +tp255 +a(S'axxxxyzq' +p256 +S' 0: xxxyz' +p257 +tp258 +a(S'*** Failers' +p259 +S'No match' +p260 +tp261 +a(S'ax' +p262 +S'No match' +p263 +tp264 +a(S'axx' +p265 +S'No match' +p266 +tp267 +aaa(lp268 +S'x{3}yz' +p269 +ag3 +a(lp270 +(S'axxxyzq' +p271 +S' 0: xxxyz' +p272 +tp273 +a(S'axxxxyzq' +p274 +S' 0: xxxyz' +p275 +tp276 +a(S'*** Failers' +p277 +S'No match' +p278 +tp279 +a(S'ax' +p280 +S'No match' +p281 +tp282 +a(S'axx' +p283 +S'No match' +p284 +tp285 +a(S'ayzq' +p286 +S'No match' +p287 +tp288 +a(S'axyzq' +p289 +S'No match' +p290 +tp291 +a(S'axxyz' +p292 +S'No match' +p293 +tp294 +aaa(lp295 +S'x{2,3}yz' +p296 +ag3 +a(lp297 +(S'axxyz' +p298 +S' 0: xxyz' +p299 +tp300 +a(S'axxxyzq' +p301 +S' 0: xxxyz' +p302 +tp303 +a(S'axxxxyzq' +p304 +S' 0: xxxyz' +p305 +tp306 +a(S'*** Failers' +p307 +S'No match' +p308 +tp309 +a(S'ax' +p310 +S'No match' +p311 +tp312 +a(S'axx' +p313 +S'No match' +p314 +tp315 +a(S'ayzq' +p316 +S'No match' +p317 +tp318 +a(S'axyzq' +p319 +S'No match' +p320 +tp321 +aaa(lp322 +S'[^a]+' +p323 +ag3 +a(lp324 +(S'bac' +p325 +S' 0: b' +p326 +tp327 +a(S'bcdefax' +p328 +S' 0: bcdef' +p329 +tp330 +a(S'*** Failers' +p331 +S' 0: *** F' +p332 +tp333 +a(S'aaaaa' +p334 +S'No match' +p335 +tp336 +aaa(lp337 +S'[^a]*' +p338 +ag3 +a(lp339 +(S'bac' +p340 +S' 0: b' +p341 +tp342 +a(S'bcdefax' +p343 +S' 0: bcdef' +p344 +tp345 +a(S'*** Failers' +p346 +S' 0: *** F' +p347 +tp348 +a(S'aaaaa' +p349 +S' 0: ' +p350 +tp351 +aaa(lp352 +S'[^a]{3,5}' +p353 +ag3 +a(lp354 +(S'xyz' +p355 +S' 0: xyz' +p356 +tp357 +a(S'awxyza' +p358 +S' 0: wxyz' +p359 +tp360 +a(S'abcdefa' +p361 +S' 0: bcdef' +p362 +tp363 +a(S'abcdefghijk' +p364 +S' 0: bcdef' +p365 +tp366 +a(S'*** Failers' +p367 +S' 0: *** F' +p368 +tp369 +a(S'axya' +p370 +S'No match' +p371 +tp372 +a(S'axa' +p373 +S'No match' +p374 +tp375 +a(S'aaaaa' +p376 +S'No match' +p377 +tp378 +aaa(lp379 +S'\\d*' +p380 +ag3 +a(lp381 +(S'1234b567' +p382 +S' 0: 1234' +p383 +tp384 +a(S'xyz' +p385 +S' 0: ' +p386 +tp387 +aaa(lp388 +S'\\D*' +p389 +ag3 +a(lp390 +(S'a1234b567' +p391 +S' 0: a' +p392 +tp393 +a(S'xyz' +p394 +S' 0: xyz' +p395 +tp396 +aaa(lp397 +S'\\d+' +p398 +ag3 +a(lp399 +(S'ab1234c56' +p400 +S' 0: 1234' +p401 +tp402 +a(S'*** Failers' +p403 +S'No match' +p404 +tp405 +a(S'xyz' +p406 +S'No match' +p407 +tp408 +aaa(lp409 +S'\\D+' +p410 +ag3 +a(lp411 +(S'ab123c56' +p412 +S' 0: ab' +p413 +tp414 +a(S'*** Failers' +p415 +S' 0: *** Failers' +p416 +tp417 +a(S'789' +p418 +S'No match' +p419 +tp420 +aaa(lp421 +S'\\d?A' +p422 +ag3 +a(lp423 +(S'045ABC' +p424 +S' 0: 5A' +p425 +tp426 +a(S'ABC' +p427 +S' 0: A' +p428 +tp429 +a(S'*** Failers' +p430 +S'No match' +p431 +tp432 +a(S'XYZ' +p433 +S'No match' +p434 +tp435 +aaa(lp436 +S'\\D?A' +p437 +ag3 +a(lp438 +(S'ABC' +p439 +S' 0: A' +p440 +tp441 +a(S'BAC' +p442 +S' 0: BA' +p443 +tp444 +a(S'9ABC' +p445 +S' 0: A' +p446 +tp447 +a(S'*** Failers' +p448 +S'No match' +p449 +tp450 +aaa(lp451 +S'a+' +p452 +ag3 +a(lp453 +(S'aaaa' +p454 +S' 0: aaaa' +p455 +tp456 +aaa(lp457 +S'^.*xyz' +p458 +ag3 +a(lp459 +(S'xyz' +p460 +S' 0: xyz' +p461 +tp462 +a(S'ggggggggxyz' +p463 +S' 0: ggggggggxyz' +p464 +tp465 +aaa(lp466 +S'^.+xyz' +p467 +ag3 +a(lp468 +(S'abcdxyz' +p469 +S' 0: abcdxyz' +p470 +tp471 +a(S'axyz' +p472 +S' 0: axyz' +p473 +tp474 +a(S'*** Failers' +p475 +S'No match' +p476 +tp477 +a(S'xyz' +p478 +S'No match' +p479 +tp480 +aaa(lp481 +S'^.?xyz' +p482 +ag3 +a(lp483 +(S'xyz' +p484 +S' 0: xyz' +p485 +tp486 +a(S'cxyz' +p487 +S' 0: cxyz' +p488 +tp489 +aaa(lp490 +S'^\\d{2,3}X' +p491 +ag3 +a(lp492 +(S'12X' +p493 +S' 0: 12X' +p494 +tp495 +a(S'123X' +p496 +S' 0: 123X' +p497 +tp498 +a(S'*** Failers' +p499 +S'No match' +p500 +tp501 +a(S'X' +p502 +S'No match' +p503 +tp504 +a(S'1X' +p505 +S'No match' +p506 +tp507 +a(S'1234X' +p508 +S'No match' +p509 +tp510 +aaa(lp511 +S'^[abcd]\\d' +p512 +ag3 +a(lp513 +(S'a45' +p514 +S' 0: a4' +p515 +tp516 +a(S'b93' +p517 +S' 0: b9' +p518 +tp519 +a(S'c99z' +p520 +S' 0: c9' +p521 +tp522 +a(S'd04' +p523 +S' 0: d0' +p524 +tp525 +a(S'*** Failers' +p526 +S'No match' +p527 +tp528 +a(S'e45' +p529 +S'No match' +p530 +tp531 +a(S'abcd' +p532 +S'No match' +p533 +tp534 +a(S'abcd1234' +p535 +S'No match' +p536 +tp537 +a(S'1234' +p538 +S'No match' +p539 +tp540 +aaa(lp541 +S'^[abcd]*\\d' +p542 +ag3 +a(lp543 +(S'a45' +p544 +S' 0: a4' +p545 +tp546 +a(S'b93' +p547 +S' 0: b9' +p548 +tp549 +a(S'c99z' +p550 +S' 0: c9' +p551 +tp552 +a(S'd04' +p553 +S' 0: d0' +p554 +tp555 +a(S'abcd1234' +p556 +S' 0: abcd1' +p557 +tp558 +a(S'1234' +p559 +S' 0: 1' +p560 +tp561 +a(S'*** Failers' +p562 +S'No match' +p563 +tp564 +a(S'e45' +p565 +S'No match' +p566 +tp567 +a(S'abcd' +p568 +S'No match' +p569 +tp570 +aaa(lp571 +S'^[abcd]+\\d' +p572 +ag3 +a(lp573 +(S'a45' +p574 +S' 0: a4' +p575 +tp576 +a(S'b93' +p577 +S' 0: b9' +p578 +tp579 +a(S'c99z' +p580 +S' 0: c9' +p581 +tp582 +a(S'd04' +p583 +S' 0: d0' +p584 +tp585 +a(S'abcd1234' +p586 +S' 0: abcd1' +p587 +tp588 +a(S'*** Failers' +p589 +S'No match' +p590 +tp591 +a(S'1234' +p592 +S'No match' +p593 +tp594 +a(S'e45' +p595 +S'No match' +p596 +tp597 +a(S'abcd' +p598 +S'No match' +p599 +tp600 +aaa(lp601 +S'^a+X' +p602 +ag3 +a(lp603 +(S'aX' +p604 +S' 0: aX' +p605 +tp606 +a(S'aaX' +p607 +S' 0: aaX' +p608 +tp609 +aaa(lp610 +S'^[abcd]?\\d' +p611 +ag3 +a(lp612 +(S'a45' +p613 +S' 0: a4' +p614 +tp615 +a(S'b93' +p616 +S' 0: b9' +p617 +tp618 +a(S'c99z' +p619 +S' 0: c9' +p620 +tp621 +a(S'd04' +p622 +S' 0: d0' +p623 +tp624 +a(S'1234' +p625 +S' 0: 1' +p626 +tp627 +a(S'*** Failers' +p628 +S'No match' +p629 +tp630 +a(S'abcd1234' +p631 +S'No match' +p632 +tp633 +a(S'e45' +p634 +S'No match' +p635 +tp636 +aaa(lp637 +S'^[abcd]{2,3}\\d' +p638 +ag3 +a(lp639 +(S'ab45' +p640 +S' 0: ab4' +p641 +tp642 +a(S'bcd93' +p643 +S' 0: bcd9' +p644 +tp645 +a(S'*** Failers' +p646 +S'No match' +p647 +tp648 +a(S'1234' +p649 +S'No match' +p650 +tp651 +a(S'a36' +p652 +S'No match' +p653 +tp654 +a(S'abcd1234' +p655 +S'No match' +p656 +tp657 +a(S'ee45' +p658 +S'No match' +p659 +tp660 +aaa(lp661 +S'^(abc)*\\d' +p662 +ag3 +a(lp663 +(S'abc45' +p664 +S' 0: abc4' +p665 +tp666 +a(S'abcabcabc45' +p667 +S' 0: abcabcabc4' +p668 +tp669 +a(S'42xyz' +p670 +S' 0: 4' +p671 +tp672 +a(S'*** Failers' +p673 +S'No match' +p674 +tp675 +aaa(lp676 +S'^(abc)+\\d' +p677 +ag3 +a(lp678 +(S'abc45' +p679 +S' 0: abc4' +p680 +tp681 +a(S'abcabcabc45' +p682 +S' 0: abcabcabc4' +p683 +tp684 +a(S'*** Failers' +p685 +S'No match' +p686 +tp687 +a(S'42xyz' +p688 +S'No match' +p689 +tp690 +aaa(lp691 +S'^(abc)?\\d' +p692 +ag3 +a(lp693 +(S'abc45' +p694 +S' 0: abc4' +p695 +tp696 +a(S'42xyz' +p697 +S' 0: 4' +p698 +tp699 +a(S'*** Failers' +p700 +S'No match' +p701 +tp702 +a(S'abcabcabc45' +p703 +S'No match' +p704 +tp705 +aaa(lp706 +S'^(abc){2,3}\\d' +p707 +ag3 +a(lp708 +(S'abcabc45' +p709 +S' 0: abcabc4' +p710 +tp711 +a(S'abcabcabc45' +p712 +S' 0: abcabcabc4' +p713 +tp714 +a(S'*** Failers' +p715 +S'No match' +p716 +tp717 +a(S'abcabcabcabc45' +p718 +S'No match' +p719 +tp720 +a(S'abc45' +p721 +S'No match' +p722 +tp723 +a(S'42xyz' +p724 +S'No match' +p725 +tp726 +aaa(lp727 +S'^(a*\\w|ab)=(a*\\w|ab)' +p728 +ag3 +a(lp729 +(S'ab=ab' +p730 +S' 0: ab=ab' +p731 +tp732 +aaa(lp733 +S'^abc' +p734 +ag3 +a(lp735 +(S'abcdef' +p736 +S' 0: abc' +p737 +tp738 +a(S'*** Failers' +p739 +S'No match' +p740 +tp741 +a(S'abcdefB' +p742 +S'No match' +p743 +tp744 +aaa(lp745 +S'^(a*|xyz)' +p746 +ag3 +a(lp747 +(S'bcd' +p748 +S' 0: ' +p749 +tp750 +a(S'aaabcd' +p751 +S' 0: aaa' +p752 +tp753 +a(S'xyz' +p754 +S' 0: xyz' +p755 +tp756 +a(S'xyzN' +p757 +S' 0: xyz' +p758 +tp759 +a(S'*** Failers' +p760 +S' 0: ' +p761 +tp762 +a(S'bcdN' +p763 +S'No match' +p764 +tp765 +aaa(lp766 +S'xyz$' +p767 +ag3 +a(lp768 +(S'xyz' +p769 +S' 0: xyz' +p770 +tp771 +a(S'xyz\n' +p772 +S' 0: xyz' +p773 +tp774 +a(S'*** Failers' +p775 +S'No match' +p776 +tp777 +a(S'xyzZ' +p778 +S'No match' +p779 +tp780 +a(S'xyz\nZ' +p781 +S'No match' +p782 +tp783 +aaa(lp784 +S'\\Gabc' +p785 +ag3 +a(lp786 +(S'abcdef' +p787 +S' 0: abc' +p788 +tp789 +a(S'defabcxyz>3' +p790 +S' 0: abc' +p791 +tp792 +a(S'*** Failers' +p793 +S'No match' +p794 +tp795 +a(S'defabcxyz' +p796 +S'No match' +p797 +tp798 +aaa(lp799 +S'^abcdef' +p800 +ag3 +a(lp801 +(S'abP' +p802 +S' 0: abcdef' +p803 +tp804 +a(S'*** Failers' +p805 +S'No match' +p806 +tp807 +a(S'abxP' +p808 +S'No match' +p809 +tp810 +aaa(lp811 +S'^a{2,4}\\d+z' +p812 +ag3 +a(lp813 +(S'aP' +p814 +S' 0: aa0z' +p815 +tp816 +a(S'aaaa4444444444444zP' +p817 +S' 0: aaaa4444444444444z' +p818 +tp819 +a(S'*** Failers' +p820 +S'No match' +p821 +tp822 +a(S'azP' +p823 +S'No match' +p824 +tp825 +a(S'aaaaaP' +p826 +S'No match' +p827 +tp828 +a(S'a56P' +p829 +S'No match' +p830 +tp831 +aaa(lp832 +S'^abcdef' +p833 +ag3 +a(lp834 +(S'abcP' +p835 +S' 0: def' +p836 +tp837 +aaa(lp838 +S'(ab*(cd|ef))+X' +p839 +ag3 +a(lp840 +(S'adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkjPZ' +p841 +S'No match' +p842 +tp843 +a(S'lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefaPBZ' +p844 +S' 0: bbbbbbbbbbbbcdX' +p845 +tp846 +aaa(lp847 +S'the quick brown fox' +p848 +ag3 +a(lp849 +(S'the quick brown fox' +p850 +S' 0: the quick brown fox' +p851 +tp852 +a(S'The quick brown FOX' +p853 +S'No match' +p854 +tp855 +a(S'What do you know about the quick brown fox?' +p856 +S' 0: the quick brown fox' +p857 +tp858 +a(S'What do you know about THE QUICK BROWN FOX?' +p859 +S'No match' +p860 +tp861 +aaa(lp862 +S'abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz' +p863 +ag3 +a(lp864 +(S'abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz' +p865 +S' 0: abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz' +p866 +tp867 +aaa(lp868 +S'a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz' +p869 +ag3 +a(lp870 +(S'abxyzpqrrrabbxyyyypqAzz' +p871 +S' 0: abxyzpqrrrabbxyyyypqAzz' +p872 +tp873 +a(S'abxyzpqrrrabbxyyyypqAzz' +p874 +S' 0: abxyzpqrrrabbxyyyypqAzz' +p875 +tp876 +a(S'aabxyzpqrrrabbxyyyypqAzz' +p877 +S' 0: aabxyzpqrrrabbxyyyypqAzz' +p878 +tp879 +a(S'aaabxyzpqrrrabbxyyyypqAzz' +p880 +S' 0: aaabxyzpqrrrabbxyyyypqAzz' +p881 +tp882 +a(S'aaaabxyzpqrrrabbxyyyypqAzz' +p883 +S' 0: aaaabxyzpqrrrabbxyyyypqAzz' +p884 +tp885 +a(S'abcxyzpqrrrabbxyyyypqAzz' +p886 +S' 0: abcxyzpqrrrabbxyyyypqAzz' +p887 +tp888 +a(S'aabcxyzpqrrrabbxyyyypqAzz' +p889 +S' 0: aabcxyzpqrrrabbxyyyypqAzz' +p890 +tp891 +a(S'aaabcxyzpqrrrabbxyyyypAzz' +p892 +S' 0: aaabcxyzpqrrrabbxyyyypAzz' +p893 +tp894 +a(S'aaabcxyzpqrrrabbxyyyypqAzz' +p895 +S' 0: aaabcxyzpqrrrabbxyyyypqAzz' +p896 +tp897 +a(S'aaabcxyzpqrrrabbxyyyypqqAzz' +p898 +S' 0: aaabcxyzpqrrrabbxyyyypqqAzz' +p899 +tp900 +a(S'aaabcxyzpqrrrabbxyyyypqqqAzz' +p901 +S' 0: aaabcxyzpqrrrabbxyyyypqqqAzz' +p902 +tp903 +a(S'aaabcxyzpqrrrabbxyyyypqqqqAzz' +p904 +S' 0: aaabcxyzpqrrrabbxyyyypqqqqAzz' +p905 +tp906 +a(S'aaabcxyzpqrrrabbxyyyypqqqqqAzz' +p907 +S' 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz' +p908 +tp909 +a(S'aaabcxyzpqrrrabbxyyyypqqqqqqAzz' +p910 +S' 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz' +p911 +tp912 +a(S'aaaabcxyzpqrrrabbxyyyypqAzz' +p913 +S' 0: aaaabcxyzpqrrrabbxyyyypqAzz' +p914 +tp915 +a(S'abxyzzpqrrrabbxyyyypqAzz' +p916 +S' 0: abxyzzpqrrrabbxyyyypqAzz' +p917 +tp918 +a(S'aabxyzzzpqrrrabbxyyyypqAzz' +p919 +S' 0: aabxyzzzpqrrrabbxyyyypqAzz' +p920 +tp921 +a(S'aaabxyzzzzpqrrrabbxyyyypqAzz' +p922 +S' 0: aaabxyzzzzpqrrrabbxyyyypqAzz' +p923 +tp924 +a(S'aaaabxyzzzzpqrrrabbxyyyypqAzz' +p925 +S' 0: aaaabxyzzzzpqrrrabbxyyyypqAzz' +p926 +tp927 +a(S'abcxyzzpqrrrabbxyyyypqAzz' +p928 +S' 0: abcxyzzpqrrrabbxyyyypqAzz' +p929 +tp930 +a(S'aabcxyzzzpqrrrabbxyyyypqAzz' +p931 +S' 0: aabcxyzzzpqrrrabbxyyyypqAzz' +p932 +tp933 +a(S'aaabcxyzzzzpqrrrabbxyyyypqAzz' +p934 +S' 0: aaabcxyzzzzpqrrrabbxyyyypqAzz' +p935 +tp936 +a(S'aaaabcxyzzzzpqrrrabbxyyyypqAzz' +p937 +S' 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz' +p938 +tp939 +a(S'aaaabcxyzzzzpqrrrabbbxyyyypqAzz' +p940 +S' 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz' +p941 +tp942 +a(S'aaaabcxyzzzzpqrrrabbbxyyyyypqAzz' +p943 +S' 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz' +p944 +tp945 +a(S'aaabcxyzpqrrrabbxyyyypABzz' +p946 +S' 0: aaabcxyzpqrrrabbxyyyypABzz' +p947 +tp948 +a(S'aaabcxyzpqrrrabbxyyyypABBzz' +p949 +S' 0: aaabcxyzpqrrrabbxyyyypABBzz' +p950 +tp951 +a(S'>>>aaabxyzpqrrrabbxyyyypqAzz' +p952 +S' 0: aaabxyzpqrrrabbxyyyypqAzz' +p953 +tp954 +a(S'>aaaabxyzpqrrrabbxyyyypqAzz' +p955 +S' 0: aaaabxyzpqrrrabbxyyyypqAzz' +p956 +tp957 +a(S'>>>>abcxyzpqrrrabbxyyyypqAzz' +p958 +S' 0: abcxyzpqrrrabbxyyyypqAzz' +p959 +tp960 +a(S'*** Failers' +p961 +S'No match' +p962 +tp963 +a(S'abxyzpqrrabbxyyyypqAzz' +p964 +S'No match' +p965 +tp966 +a(S'abxyzpqrrrrabbxyyyypqAzz' +p967 +S'No match' +p968 +tp969 +a(S'abxyzpqrrrabxyyyypqAzz' +p970 +S'No match' +p971 +tp972 +a(S'aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz' +p973 +S'No match' +p974 +tp975 +a(S'aaaabcxyzzzzpqrrrabbbxyyypqAzz' +p976 +S'No match' +p977 +tp978 +a(S'aaabcxyzpqrrrabbxyyyypqqqqqqqAzz' +p979 +S'No match' +p980 +tp981 +aaa(lp982 +S'^(abc){1,2}zz' +p983 +ag3 +a(lp984 +(S'abczz' +p985 +S' 0: abczz' +p986 +tp987 +a(S'abcabczz' +p988 +S' 0: abcabczz' +p989 +tp990 +a(S'*** Failers' +p991 +S'No match' +p992 +tp993 +a(S'zz' +p994 +S'No match' +p995 +tp996 +a(S'abcabcabczz' +p997 +S'No match' +p998 +tp999 +a(S'>>abczz' +p1000 +S'No match' +p1001 +tp1002 +aaa(lp1003 +S'^(b+|a){1,2}c' +p1004 +ag3 +a(lp1005 +(S'bc' +p1006 +S' 0: bc' +p1007 +tp1008 +a(S'bbc' +p1009 +S' 0: bbc' +p1010 +tp1011 +a(S'bbbc' +p1012 +S' 0: bbbc' +p1013 +tp1014 +a(S'bac' +p1015 +S' 0: bac' +p1016 +tp1017 +a(S'bbac' +p1018 +S' 0: bbac' +p1019 +tp1020 +a(S'aac' +p1021 +S' 0: aac' +p1022 +tp1023 +a(S'abbbbbbbbbbbc' +p1024 +S' 0: abbbbbbbbbbbc' +p1025 +tp1026 +a(S'bbbbbbbbbbbac' +p1027 +S' 0: bbbbbbbbbbbac' +p1028 +tp1029 +a(S'*** Failers' +p1030 +S'No match' +p1031 +tp1032 +a(S'aaac' +p1033 +S'No match' +p1034 +tp1035 +a(S'abbbbbbbbbbbac' +p1036 +S'No match' +p1037 +tp1038 +aaa(lp1039 +S'^\\ca\\cA\\c[\\c{\\c:' +p1040 +ag3 +a(lp1041 +(S'\x01\x01\x1b;z' +p1042 +S' 0: \x01\x01\x1b;z' +p1043 +tp1044 +aaa(lp1045 +S'^[ab\\]cde]' +p1046 +ag3 +a(lp1047 +(S'athing' +p1048 +S' 0: a' +p1049 +tp1050 +a(S'bthing' +p1051 +S' 0: b' +p1052 +tp1053 +a(S']thing' +p1054 +S' 0: ]' +p1055 +tp1056 +a(S'cthing' +p1057 +S' 0: c' +p1058 +tp1059 +a(S'dthing' +p1060 +S' 0: d' +p1061 +tp1062 +a(S'ething' +p1063 +S' 0: e' +p1064 +tp1065 +a(S'*** Failers' +p1066 +S'No match' +p1067 +tp1068 +a(S'fthing' +p1069 +S'No match' +p1070 +tp1071 +a(S'[thing' +p1072 +S'No match' +p1073 +tp1074 +a(S'\\thing' +p1075 +S'No match' +p1076 +tp1077 +aaa(lp1078 +S'^[]cde]' +p1079 +ag3 +a(lp1080 +(S']thing' +p1081 +S' 0: ]' +p1082 +tp1083 +a(S'cthing' +p1084 +S' 0: c' +p1085 +tp1086 +a(S'dthing' +p1087 +S' 0: d' +p1088 +tp1089 +a(S'ething' +p1090 +S' 0: e' +p1091 +tp1092 +a(S'*** Failers' +p1093 +S'No match' +p1094 +tp1095 +a(S'athing' +p1096 +S'No match' +p1097 +tp1098 +a(S'fthing' +p1099 +S'No match' +p1100 +tp1101 +aaa(lp1102 +S'^[^ab\\]cde]' +p1103 +ag3 +a(lp1104 +(S'fthing' +p1105 +S' 0: f' +p1106 +tp1107 +a(S'[thing' +p1108 +S' 0: [' +p1109 +tp1110 +a(S'\\thing' +p1111 +S' 0: \\' +p1112 +tp1113 +a(S'*** Failers' +p1114 +S' 0: *' +p1115 +tp1116 +a(S'athing' +p1117 +S'No match' +p1118 +tp1119 +a(S'bthing' +p1120 +S'No match' +p1121 +tp1122 +a(S']thing' +p1123 +S'No match' +p1124 +tp1125 +a(S'cthing' +p1126 +S'No match' +p1127 +tp1128 +a(S'dthing' +p1129 +S'No match' +p1130 +tp1131 +a(S'ething' +p1132 +S'No match' +p1133 +tp1134 +aaa(lp1135 +S'^[^]cde]' +p1136 +ag3 +a(lp1137 +(S'athing' +p1138 +S' 0: a' +p1139 +tp1140 +a(S'fthing' +p1141 +S' 0: f' +p1142 +tp1143 +a(S'*** Failers' +p1144 +S' 0: *' +p1145 +tp1146 +a(S']thing' +p1147 +S'No match' +p1148 +tp1149 +a(S'cthing' +p1150 +S'No match' +p1151 +tp1152 +a(S'dthing' +p1153 +S'No match' +p1154 +tp1155 +a(S'ething' +p1156 +S'No match' +p1157 +tp1158 +aaa(lp1159 +S'^\\\x81' +p1160 +ag3 +a(lp1161 +(S'\x81' +p1162 +S' 0: \x81' +p1163 +tp1164 +aaa(lp1165 +S'^\xff' +p1166 +ag3 +a(lp1167 +(S'\xff' +p1168 +S' 0: \xff' +p1169 +tp1170 +aaa(lp1171 +S'^[0-9]+$' +p1172 +ag3 +a(lp1173 +(S'0' +p1174 +S' 0: 0' +p1175 +tp1176 +a(S'1' +p1177 +S' 0: 1' +p1178 +tp1179 +a(S'2' +p1180 +S' 0: 2' +p1181 +tp1182 +a(S'3' +p1183 +S' 0: 3' +p1184 +tp1185 +a(S'4' +p1186 +S' 0: 4' +p1187 +tp1188 +a(S'5' +p1189 +S' 0: 5' +p1190 +tp1191 +a(S'6' +p1192 +S' 0: 6' +p1193 +tp1194 +a(S'7' +p1195 +S' 0: 7' +p1196 +tp1197 +a(S'8' +p1198 +S' 0: 8' +p1199 +tp1200 +a(S'9' +p1201 +S' 0: 9' +p1202 +tp1203 +a(S'10' +p1204 +S' 0: 10' +p1205 +tp1206 +a(S'100' +p1207 +S' 0: 100' +p1208 +tp1209 +a(S'*** Failers' +p1210 +S'No match' +p1211 +tp1212 +a(S'abc' +p1213 +S'No match' +p1214 +tp1215 +aaa(lp1216 +S'^.*nter' +p1217 +ag3 +a(lp1218 +(S'enter' +p1219 +S' 0: enter' +p1220 +tp1221 +a(S'inter' +p1222 +S' 0: inter' +p1223 +tp1224 +a(S'uponter' +p1225 +S' 0: uponter' +p1226 +tp1227 +aaa(lp1228 +S'^xxx[0-9]+$' +p1229 +ag3 +a(lp1230 +(S'xxx0' +p1231 +S' 0: xxx0' +p1232 +tp1233 +a(S'xxx1234' +p1234 +S' 0: xxx1234' +p1235 +tp1236 +a(S'*** Failers' +p1237 +S'No match' +p1238 +tp1239 +a(S'xxx' +p1240 +S'No match' +p1241 +tp1242 +aaa(lp1243 +S'^.+[0-9][0-9][0-9]$' +p1244 +ag3 +a(lp1245 +(S'x123' +p1246 +S' 0: x123' +p1247 +tp1248 +a(S'xx123' +p1249 +S' 0: xx123' +p1250 +tp1251 +a(S'123456' +p1252 +S' 0: 123456' +p1253 +tp1254 +a(S'*** Failers' +p1255 +S'No match' +p1256 +tp1257 +a(S'123' +p1258 +S'No match' +p1259 +tp1260 +a(S'x1234' +p1261 +S' 0: x1234' +p1262 +tp1263 +aaa(lp1264 +S'^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$' +p1265 +ag3 +a(lp1266 +(S'abc!pqr=apquxz.ixr.zzz.ac.uk' +p1267 +S' 0: abc!pqr=apquxz.ixr.zzz.ac.uk' +p1268 +tp1269 +a(S'*** Failers' +p1270 +S'No match' +p1271 +tp1272 +a(S'!pqr=apquxz.ixr.zzz.ac.uk' +p1273 +S'No match' +p1274 +tp1275 +a(S'abc!=apquxz.ixr.zzz.ac.uk' +p1276 +S'No match' +p1277 +tp1278 +a(S'abc!pqr=apquxz:ixr.zzz.ac.uk' +p1279 +S'No match' +p1280 +tp1281 +a(S'abc!pqr=apquxz.ixr.zzz.ac.ukk' +p1282 +S'No match' +p1283 +tp1284 +aaa(lp1285 +S':' +p1286 +ag3 +a(lp1287 +(S'Well, we need a colon: somewhere' +p1288 +S' 0: :' +p1289 +tp1290 +a(S"*** Fail if we don't" +p1291 +S'No match' +p1292 +tp1293 +aaa(lp1294 +S'^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$' +p1295 +ag3 +a(lp1296 +(S'.1.2.3' +p1297 +S' 0: .1.2.3' +p1298 +tp1299 +a(S'A.12.123.0' +p1300 +S' 0: A.12.123.0' +p1301 +tp1302 +a(S'*** Failers' +p1303 +S'No match' +p1304 +tp1305 +a(S'.1.2.3333' +p1306 +S'No match' +p1307 +tp1308 +a(S'1.2.3' +p1309 +S'No match' +p1310 +tp1311 +a(S'1234.2.3' +p1312 +S'No match' +p1313 +tp1314 +aaa(lp1315 +S'^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$' +p1316 +ag3 +a(lp1317 +(S'1 IN SOA non-sp1 non-sp2(' +p1318 +S' 0: 1 IN SOA non-sp1 non-sp2(' +p1319 +tp1320 +a(S'1 IN SOA non-sp1 non-sp2 (' +p1321 +S' 0: 1 IN SOA non-sp1 non-sp2 (' +p1322 +tp1323 +a(S'*** Failers' +p1324 +S'No match' +p1325 +tp1326 +a(S'1IN SOA non-sp1 non-sp2(' +p1327 +S'No match' +p1328 +tp1329 +aaa(lp1330 +S'^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$' +p1331 +ag3 +a(lp1332 +(S'a.' +p1333 +S' 0: a.' +p1334 +tp1335 +a(S'Z.' +p1336 +S' 0: Z.' +p1337 +tp1338 +a(S'2.' +p1339 +S' 0: 2.' +p1340 +tp1341 +a(S'ab-c.pq-r.' +p1342 +S' 0: ab-c.pq-r.' +p1343 +tp1344 +a(S'sxk.zzz.ac.uk.' +p1345 +S' 0: sxk.zzz.ac.uk.' +p1346 +tp1347 +a(S'x-.y-.' +p1348 +S' 0: x-.y-.' +p1349 +tp1350 +a(S'*** Failers' +p1351 +S'No match' +p1352 +tp1353 +a(S'-abc.peq.' +p1354 +S'No match' +p1355 +tp1356 +aaa(lp1357 +S'^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$' +p1358 +ag3 +a(lp1359 +(S'*.a' +p1360 +S' 0: *.a' +p1361 +tp1362 +a(S'*.b0-a' +p1363 +S' 0: *.b0-a' +p1364 +tp1365 +a(S'*.c3-b.c' +p1366 +S' 0: *.c3-b.c' +p1367 +tp1368 +a(S'*.c-a.b-c' +p1369 +S' 0: *.c-a.b-c' +p1370 +tp1371 +a(S'*** Failers' +p1372 +S'No match' +p1373 +tp1374 +a(S'*.0' +p1375 +S'No match' +p1376 +tp1377 +a(S'*.a-' +p1378 +S'No match' +p1379 +tp1380 +a(S'*.a-b.c-' +p1381 +S'No match' +p1382 +tp1383 +a(S'*.c-a.0-c' +p1384 +S'No match' +p1385 +tp1386 +aaa(lp1387 +S'^\\".*\\"\\s*(;.*)?$' +p1388 +ag3 +a(lp1389 +(S'"1234"' +p1390 +S' 0: "1234"' +p1391 +tp1392 +a(S'"abcd" ;' +p1393 +S' 0: "abcd" ;' +p1394 +tp1395 +a(S'"" ; rhubarb' +p1396 +S' 0: "" ; rhubarb' +p1397 +tp1398 +a(S'*** Failers' +p1399 +S'No match' +p1400 +tp1401 +a(S'"1234" : things' +p1402 +S'No match' +p1403 +tp1404 +aaa(lp1405 +S'^$' +p1406 +ag3 +a(lp1407 +(g3 +S' 0: ' +p1408 +tp1409 +a(S'*** Failers' +p1410 +S'No match' +p1411 +tp1412 +aaa(lp1413 +S'^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$' +p1414 +ag3 +a(lp1415 +(S'abcdefhijklm' +p1416 +S' 0: abcdefhijklm' +p1417 +tp1418 +aaa(lp1419 +S'^[\\w][\\W][\\s][\\S][\\d][\\D][\\b][\\n][\\c]][\\022]' +p1420 +ag3 +a(lp1421 +(S'a+ Z0+\x08\n\x1d\x12' +p1422 +S' 0: a+ Z0+\x08\n\x1d\x12' +p1423 +tp1424 +aaa(lp1425 +S'^a*\\w' +p1426 +ag3 +a(lp1427 +(S'z' +p1428 +S' 0: z' +p1429 +tp1430 +a(S'az' +p1431 +S' 0: az' +p1432 +tp1433 +a(S'aaaz' +p1434 +S' 0: aaaz' +p1435 +tp1436 +a(g41 +S' 0: a' +p1437 +tp1438 +a(S'aa' +p1439 +S' 0: aa' +p1440 +tp1441 +a(S'aaaa' +p1442 +S' 0: aaaa' +p1443 +tp1444 +a(S'a+' +p1445 +S' 0: a' +p1446 +tp1447 +a(S'aa+' +p1448 +S' 0: aa' +p1449 +tp1450 +aaa(lp1451 +S'^a+\\w' +p1452 +ag3 +a(lp1453 +(S'az' +p1454 +S' 0: az' +p1455 +tp1456 +a(S'aaaz' +p1457 +S' 0: aaaz' +p1458 +tp1459 +a(S'aa' +p1460 +S' 0: aa' +p1461 +tp1462 +a(S'aaaa' +p1463 +S' 0: aaaa' +p1464 +tp1465 +a(S'aa+' +p1466 +S' 0: aa' +p1467 +tp1468 +aaa(lp1469 +S'^\\d{8}\\w{2,}' +p1470 +ag3 +a(lp1471 +(S'1234567890' +p1472 +S' 0: 1234567890' +p1473 +tp1474 +a(S'12345678ab' +p1475 +S' 0: 12345678ab' +p1476 +tp1477 +a(S'12345678__' +p1478 +S' 0: 12345678__' +p1479 +tp1480 +a(S'*** Failers' +p1481 +S'No match' +p1482 +tp1483 +a(S'1234567' +p1484 +S'No match' +p1485 +tp1486 +aaa(lp1487 +S'^[aeiou\\d]{4,5}$' +p1488 +ag3 +a(lp1489 +(S'uoie' +p1490 +S' 0: uoie' +p1491 +tp1492 +a(S'1234' +p1493 +S' 0: 1234' +p1494 +tp1495 +a(S'12345' +p1496 +S' 0: 12345' +p1497 +tp1498 +a(S'aaaaa' +p1499 +S' 0: aaaaa' +p1500 +tp1501 +a(S'*** Failers' +p1502 +S'No match' +p1503 +tp1504 +a(S'123456' +p1505 +S'No match' +p1506 +tp1507 +aaa(lp1508 +S'^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]' +p1509 +ag3 +a(lp1510 +(S'From abcd Mon Sep 01 12:33:02 1997' +p1511 +S' 0: From abcd Mon Sep 01 12:33' +p1512 +tp1513 +aaa(lp1514 +S'^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d' +p1515 +ag3 +a(lp1516 +(S'From abcd Mon Sep 01 12:33:02 1997' +p1517 +S' 0: From abcd Mon Sep 01 12:33' +p1518 +tp1519 +a(S'From abcd Mon Sep 1 12:33:02 1997' +p1520 +S' 0: From abcd Mon Sep 1 12:33' +p1521 +tp1522 +a(S'*** Failers' +p1523 +S'No match' +p1524 +tp1525 +a(S'From abcd Sep 01 12:33:02 1997' +p1526 +S'No match' +p1527 +tp1528 +aaa(lp1529 +S'^[ab]{1,3}(ab*|b)' +p1530 +ag3 +a(lp1531 +(S'aabbbbb' +p1532 +S' 0: aabbbbb' +p1533 +tp1534 +aaa(lp1535 +S'abc\\0def\\00pqr\\000xyz\\0000AB' +p1536 +ag3 +a(lp1537 +(S'abc\x00def\x00pqr\x00xyz\x000AB' +p1538 +S' 0: abc\x00def\x00pqr\x00xyz\x000AB' +p1539 +tp1540 +a(S'abc456 abc\x00def\x00pqr\x00xyz\x000ABCDE' +p1541 +S' 0: abc\x00def\x00pqr\x00xyz\x000AB' +p1542 +tp1543 +aaa(lp1544 +S'abc\\x0def\\x00pqr\\x000xyz\\x0000AB' +p1545 +ag3 +a(lp1546 +(S'abc\ref\x00pqr\x000xyz\x0000AB' +p1547 +S' 0: abc\ref\x00pqr\x000xyz\x0000AB' +p1548 +tp1549 +a(S'abc456 abc\ref\x00pqr\x000xyz\x0000ABCDE' +p1550 +S' 0: abc\ref\x00pqr\x000xyz\x0000AB' +p1551 +tp1552 +aaa(lp1553 +S'^[\\000-\\037]' +p1554 +ag3 +a(lp1555 +(S'\x00A' +p1556 +S' 0: \x00' +p1557 +tp1558 +a(S'\x01B' +p1559 +S' 0: \x01' +p1560 +tp1561 +a(S'\x1fC' +p1562 +S' 0: \x1f' +p1563 +tp1564 +aaa(lp1565 +S'\\0*' +p1566 +ag3 +a(lp1567 +(S'\x00\x00\x00\x00' +p1568 +S' 0: \x00\x00\x00\x00' +p1569 +tp1570 +aaa(lp1571 +S'A\\x00{2,3}Z' +p1572 +ag3 +a(lp1573 +(S'The A\x00\x00Z' +p1574 +S' 0: A\x00\x00Z' +p1575 +tp1576 +a(S'An A\x00\x00\x00Z' +p1577 +S' 0: A\x00\x00\x00Z' +p1578 +tp1579 +a(S'*** Failers' +p1580 +S'No match' +p1581 +tp1582 +a(S'A\x00Z' +p1583 +S'No match' +p1584 +tp1585 +a(S'A\x00\x00\x00\x00Z' +p1586 +S'No match' +p1587 +tp1588 +aaa(lp1589 +S'^\\s' +p1590 +ag3 +a(lp1591 +(S' abc' +p1592 +S' 0: ' +p1593 +tp1594 +a(S'\x0cabc' +p1595 +S' 0: \x0c' +p1596 +tp1597 +a(S'\nabc' +p1598 +S' 0: \n' +p1599 +tp1600 +a(S'\rabc' +p1601 +S' 0: \r' +p1602 +tp1603 +a(S'\tabc' +p1604 +S' 0: \t' +p1605 +tp1606 +a(S'*** Failers' +p1607 +S'No match' +p1608 +tp1609 +a(S'abc' +p1610 +S'No match' +p1611 +tp1612 +aaa(lp1613 +S'ab{1,3}bc' +p1614 +ag3 +a(lp1615 +(S'abbbbc' +p1616 +S' 0: abbbbc' +p1617 +tp1618 +a(S'abbbc' +p1619 +S' 0: abbbc' +p1620 +tp1621 +a(S'abbc' +p1622 +S' 0: abbc' +p1623 +tp1624 +a(S'*** Failers' +p1625 +S'No match' +p1626 +tp1627 +a(S'abc' +p1628 +S'No match' +p1629 +tp1630 +a(S'abbbbbc' +p1631 +S'No match' +p1632 +tp1633 +aaa(lp1634 +S'([^.]*)\\.([^:]*):[T ]+(.*)' +p1635 +ag3 +a(lp1636 +(S'track1.title:TBlah blah blah' +p1637 +S' 0: track1.title:TBlah blah blah' +p1638 +tp1639 +aaa(lp1640 +S'^[W-c]+$' +p1641 +ag3 +a(lp1642 +(S'WXY_^abc' +p1643 +S' 0: WXY_^abc' +p1644 +tp1645 +a(S'*** Failers' +p1646 +S'No match' +p1647 +tp1648 +a(S'wxy' +p1649 +S'No match' +p1650 +tp1651 +aaa(lp1652 +S'^abc$' +p1653 +ag3 +a(lp1654 +(S'abc' +p1655 +S' 0: abc' +p1656 +tp1657 +a(S'*** Failers' +p1658 +S'No match' +p1659 +tp1660 +a(S'qqq\nabc' +p1661 +S'No match' +p1662 +tp1663 +a(S'abc\nzzz' +p1664 +S'No match' +p1665 +tp1666 +a(S'qqq\nabc\nzzz' +p1667 +S'No match' +p1668 +tp1669 +aaa(lp1670 +S'[-az]+' +p1671 +ag3 +a(lp1672 +(S'az-' +p1673 +S' 0: az-' +p1674 +tp1675 +a(S'*** Failers' +p1676 +S' 0: a' +p1677 +tp1678 +a(S'b' +p1679 +S'No match' +p1680 +tp1681 +aaa(lp1682 +S'[az-]+' +p1683 +ag3 +a(lp1684 +(S'za-' +p1685 +S' 0: za-' +p1686 +tp1687 +a(S'*** Failers' +p1688 +S' 0: a' +p1689 +tp1690 +a(g1679 +S'No match' +p1691 +tp1692 +aaa(lp1693 +S'[a\\-z]+' +p1694 +ag3 +a(lp1695 +(S'a-z' +p1696 +S' 0: a-z' +p1697 +tp1698 +a(S'*** Failers' +p1699 +S' 0: a' +p1700 +tp1701 +a(g1679 +S'No match' +p1702 +tp1703 +aaa(lp1704 +S'[a-z]+' +p1705 +ag3 +a(lp1706 +(S'abcdxyz' +p1707 +S' 0: abcdxyz' +p1708 +tp1709 +aaa(lp1710 +S'[\\d-]+' +p1711 +ag3 +a(lp1712 +(S'12-34' +p1713 +S' 0: 12-34' +p1714 +tp1715 +a(S'*** Failers' +p1716 +S'No match' +p1717 +tp1718 +a(S'aaa' +p1719 +S'No match' +p1720 +tp1721 +aaa(lp1722 +S'[\\d-z]+' +p1723 +ag3 +a(lp1724 +(S'12-34z' +p1725 +S' 0: 12-34z' +p1726 +tp1727 +a(S'*** Failers' +p1728 +S'No match' +p1729 +tp1730 +a(S'aaa' +p1731 +S'No match' +p1732 +tp1733 +aaa(lp1734 +S'\\x5c' +p1735 +ag3 +a(lp1736 +(S'\\' +p1737 +S' 0: \\' +p1738 +tp1739 +aaa(lp1740 +S'\\x20Z' +p1741 +ag3 +a(lp1742 +(S'the Zoo' +p1743 +S' 0: Z' +p1744 +tp1745 +a(S'*** Failers' +p1746 +S'No match' +p1747 +tp1748 +a(S'Zulu' +p1749 +S'No match' +p1750 +tp1751 +aaa(lp1752 +S'ab{3cd' +p1753 +ag3 +a(lp1754 +(S'ab{3cd' +p1755 +S' 0: ab{3cd' +p1756 +tp1757 +aaa(lp1758 +S'ab{3,cd' +p1759 +ag3 +a(lp1760 +(S'ab{3,cd' +p1761 +S' 0: ab{3,cd' +p1762 +tp1763 +aaa(lp1764 +S'ab{3,4a}cd' +p1765 +ag3 +a(lp1766 +(S'ab{3,4a}cd' +p1767 +S' 0: ab{3,4a}cd' +p1768 +tp1769 +aaa(lp1770 +S'{4,5a}bc' +p1771 +ag3 +a(lp1772 +(S'{4,5a}bc' +p1773 +S' 0: {4,5a}bc' +p1774 +tp1775 +aaa(lp1776 +S'abc$' +p1777 +ag3 +a(lp1778 +(S'abc' +p1779 +S' 0: abc' +p1780 +tp1781 +a(S'abc\n' +p1782 +S' 0: abc' +p1783 +tp1784 +a(S'*** Failers' +p1785 +S'No match' +p1786 +tp1787 +a(S'abc\ndef' +p1788 +S'No match' +p1789 +tp1790 +aaa(lp1791 +S'(abc)\\223' +p1792 +ag3 +a(lp1793 +(S'abc\x93' +p1794 +S' 0: abc\x93' +p1795 +tp1796 +aaa(lp1797 +S'(abc)\\323' +p1798 +ag3 +a(lp1799 +(S'abc\xd3' +p1800 +S' 0: abc\xd3' +p1801 +tp1802 +aaa(lp1803 +S'abc\\81' +p1804 +ag3 +a(lp1805 +(S'abc\x0081' +p1806 +S' 0: abc\x0081' +p1807 +tp1808 +a(S'abc\x0081' +p1809 +S' 0: abc\x0081' +p1810 +tp1811 +aaa(lp1812 +S'abc\\91' +p1813 +ag3 +a(lp1814 +(S'abc\x0091' +p1815 +S' 0: abc\x0091' +p1816 +tp1817 +a(S'abc\x0091' +p1818 +S' 0: abc\x0091' +p1819 +tp1820 +aaa(lp1821 +S'ab\\idef' +p1822 +ag3 +a(lp1823 +(S'abidef' +p1824 +S' 0: abidef' +p1825 +tp1826 +aaa(lp1827 +S'a{0}bc' +p1828 +ag3 +a(lp1829 +(S'bc' +p1830 +S' 0: bc' +p1831 +tp1832 +aaa(lp1833 +S'abc[\\10]de' +p1834 +ag3 +a(lp1835 +(S'abc\x08de' +p1836 +S' 0: abc\x08de' +p1837 +tp1838 +aaa(lp1839 +S'abc[\\1]de' +p1840 +ag3 +a(lp1841 +(S'abc\x01de' +p1842 +S' 0: abc\x01de' +p1843 +tp1844 +aaa(lp1845 +S'^([^a])([^\\b])([^c]*)([^d]{3,4})' +p1846 +ag3 +a(lp1847 +(S'baNOTccccd' +p1848 +S' 0: baNOTcccc' +p1849 +tp1850 +a(S'baNOTcccd' +p1851 +S' 0: baNOTccc' +p1852 +tp1853 +a(S'baNOTccd' +p1854 +S' 0: baNOTcc' +p1855 +tp1856 +a(S'bacccd' +p1857 +S' 0: baccc' +p1858 +tp1859 +a(S'*** Failers' +p1860 +S' 0: *** Failers' +p1861 +tp1862 +a(S'anything' +p1863 +S'No match' +p1864 +tp1865 +a(S'b\x08c' +p1866 +S'No match' +p1867 +tp1868 +a(S'baccd' +p1869 +S'No match' +p1870 +tp1871 +aaa(lp1872 +S'[^a]' +p1873 +ag3 +a(lp1874 +(S'Abc' +p1875 +S' 0: A' +p1876 +tp1877 +aaa(lp1878 +S'[^a]+' +p1879 +ag3 +a(lp1880 +(S'AAAaAbc' +p1881 +S' 0: AAA' +p1882 +tp1883 +aaa(lp1884 +S'[^a]+' +p1885 +ag3 +a(lp1886 +(S'bbb\nccc' +p1887 +S' 0: bbb\nccc' +p1888 +tp1889 +aaa(lp1890 +S'[^k]$' +p1891 +ag3 +a(lp1892 +(S'abc' +p1893 +S' 0: c' +p1894 +tp1895 +a(S'*** Failers' +p1896 +S' 0: s' +p1897 +tp1898 +a(S'abk' +p1899 +S'No match' +p1900 +tp1901 +aaa(lp1902 +S'[^k]{2,3}$' +p1903 +ag3 +a(lp1904 +(S'abc' +p1905 +S' 0: abc' +p1906 +tp1907 +a(S'kbc' +p1908 +S' 0: bc' +p1909 +tp1910 +a(S'kabc' +p1911 +S' 0: abc' +p1912 +tp1913 +a(S'*** Failers' +p1914 +S' 0: ers' +p1915 +tp1916 +a(S'abk' +p1917 +S'No match' +p1918 +tp1919 +a(S'akb' +p1920 +S'No match' +p1921 +tp1922 +a(S'akk' +p1923 +S'No match' +p1924 +tp1925 +aaa(lp1926 +S'^\\d{8,}\\@.+[^k]$' +p1927 +ag3 +a(lp1928 +(S'12345678 at a.b.c.d' +p1929 +S' 0: 12345678 at a.b.c.d' +p1930 +tp1931 +a(S'123456789 at x.y.z' +p1932 +S' 0: 123456789 at x.y.z' +p1933 +tp1934 +a(S'*** Failers' +p1935 +S'No match' +p1936 +tp1937 +a(S'12345678 at x.y.uk' +p1938 +S'No match' +p1939 +tp1940 +a(S'1234567 at a.b.c.d' +p1941 +S'No match' +p1942 +tp1943 +aaa(lp1944 +S'[^a]' +p1945 +ag3 +a(lp1946 +(S'aaaabcd' +p1947 +S' 0: b' +p1948 +tp1949 +a(S'aaAabcd' +p1950 +S' 0: A' +p1951 +tp1952 +aaa(lp1953 +S'[^az]' +p1954 +ag3 +a(lp1955 +(S'aaaabcd' +p1956 +S' 0: b' +p1957 +tp1958 +a(S'aaAabcd' +p1959 +S' 0: A' +p1960 +tp1961 +aaa(lp1962 +S'\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377' +p1963 +ag3 +a(lp1964 +(S'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' +p1965 +S' 0: \x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' +p1966 +tp1967 +aaa(lp1968 +S'(\\.\\d\\d[1-9]?)\\d+' +p1969 +ag3 +a(lp1970 +(S'1.230003938' +p1971 +S' 0: .230003938' +p1972 +tp1973 +a(S'1.875000282' +p1974 +S' 0: .875000282' +p1975 +tp1976 +a(S'1.235' +p1977 +S' 0: .235' +p1978 +tp1979 +aaa(lp1980 +S'foo(.*)bar' +p1981 +ag3 +a(lp1982 +(S'The food is under the bar in the barn.' +p1983 +S' 0: food is under the bar in the bar' +p1984 +tp1985 +aaa(lp1986 +S'(.*)(\\d*)' +p1987 +ag3 +a(lp1988 +(S'I have 2 numbers: 53147' +p1989 +S' 0: I have 2 numbers: 53147' +p1990 +tp1991 +aaa(lp1992 +S'(.*)(\\d+)' +p1993 +ag3 +a(lp1994 +(S'I have 2 numbers: 53147' +p1995 +S' 0: I have 2 numbers: 53147' +p1996 +tp1997 +aaa(lp1998 +S'(.*)(\\d+)$' +p1999 +ag3 +a(lp2000 +(S'I have 2 numbers: 53147' +p2001 +S' 0: I have 2 numbers: 53147' +p2002 +tp2003 +aaa(lp2004 +S'(.*)\\b(\\d+)$' +p2005 +ag3 +a(lp2006 +(S'I have 2 numbers: 53147' +p2007 +S' 0: I have 2 numbers: 53147' +p2008 +tp2009 +aaa(lp2010 +S'(.*\\D)(\\d+)$' +p2011 +ag3 +a(lp2012 +(S'I have 2 numbers: 53147' +p2013 +S' 0: I have 2 numbers: 53147' +p2014 +tp2015 +aaa(lp2016 +S'^[W-]46]' +p2017 +ag3 +a(lp2018 +(S'W46]789' +p2019 +S' 0: W46]' +p2020 +tp2021 +a(S'-46]789' +p2022 +S' 0: -46]' +p2023 +tp2024 +a(S'*** Failers' +p2025 +S'No match' +p2026 +tp2027 +a(S'Wall' +p2028 +S'No match' +p2029 +tp2030 +a(S'Zebra' +p2031 +S'No match' +p2032 +tp2033 +a(S'42' +p2034 +S'No match' +p2035 +tp2036 +a(S'[abcd]' +p2037 +S'No match' +p2038 +tp2039 +a(S']abcd[' +p2040 +S'No match' +p2041 +tp2042 +aaa(lp2043 +S'^[W-\\]46]' +p2044 +ag3 +a(lp2045 +(S'W46]789' +p2046 +S' 0: W' +p2047 +tp2048 +a(S'Wall' +p2049 +S' 0: W' +p2050 +tp2051 +a(S'Zebra' +p2052 +S' 0: Z' +p2053 +tp2054 +a(S'Xylophone' +p2055 +S' 0: X' +p2056 +tp2057 +a(S'42' +p2058 +S' 0: 4' +p2059 +tp2060 +a(S'[abcd]' +p2061 +S' 0: [' +p2062 +tp2063 +a(S']abcd[' +p2064 +S' 0: ]' +p2065 +tp2066 +a(S'\\backslash' +p2067 +S' 0: \\' +p2068 +tp2069 +a(S'*** Failers' +p2070 +S'No match' +p2071 +tp2072 +a(S'-46]789' +p2073 +S'No match' +p2074 +tp2075 +a(S'well' +p2076 +S'No match' +p2077 +tp2078 +aaa(lp2079 +S'\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d' +p2080 +ag3 +a(lp2081 +(S'01/01/2000' +p2082 +S' 0: 01/01/2000' +p2083 +tp2084 +aaa(lp2085 +S'^(a){0,0}' +p2086 +ag3 +a(lp2087 +(S'bcd' +p2088 +S' 0: ' +p2089 +tp2090 +a(S'abc' +p2091 +S' 0: ' +p2092 +tp2093 +a(S'aab' +p2094 +S' 0: ' +p2095 +tp2096 +aaa(lp2097 +S'^(a){0,1}' +p2098 +ag3 +a(lp2099 +(S'bcd' +p2100 +S' 0: ' +p2101 +tp2102 +a(S'abc' +p2103 +S' 0: a' +p2104 +tp2105 +a(S'aab' +p2106 +S' 0: a' +p2107 +tp2108 +aaa(lp2109 +S'^(a){0,2}' +p2110 +ag3 +a(lp2111 +(S'bcd' +p2112 +S' 0: ' +p2113 +tp2114 +a(S'abc' +p2115 +S' 0: a' +p2116 +tp2117 +a(S'aab' +p2118 +S' 0: aa' +p2119 +tp2120 +aaa(lp2121 +S'^(a){0,3}' +p2122 +ag3 +a(lp2123 +(S'bcd' +p2124 +S' 0: ' +p2125 +tp2126 +a(S'abc' +p2127 +S' 0: a' +p2128 +tp2129 +a(S'aab' +p2130 +S' 0: aa' +p2131 +tp2132 +a(S'aaa' +p2133 +S' 0: aaa' +p2134 +tp2135 +aaa(lp2136 +S'^(a){0,}' +p2137 +ag3 +a(lp2138 +(S'bcd' +p2139 +S' 0: ' +p2140 +tp2141 +a(S'abc' +p2142 +S' 0: a' +p2143 +tp2144 +a(S'aab' +p2145 +S' 0: aa' +p2146 +tp2147 +a(S'aaa' +p2148 +S' 0: aaa' +p2149 +tp2150 +a(S'aaaaaaaa' +p2151 +S' 0: aaaaaaaa' +p2152 +tp2153 +aaa(lp2154 +S'^(a){1,1}' +p2155 +ag3 +a(lp2156 +(S'bcd' +p2157 +S'No match' +p2158 +tp2159 +a(S'abc' +p2160 +S' 0: a' +p2161 +tp2162 +a(S'aab' +p2163 +S' 0: a' +p2164 +tp2165 +aaa(lp2166 +S'^(a){1,2}' +p2167 +ag3 +a(lp2168 +(S'bcd' +p2169 +S'No match' +p2170 +tp2171 +a(S'abc' +p2172 +S' 0: a' +p2173 +tp2174 +a(S'aab' +p2175 +S' 0: aa' +p2176 +tp2177 +aaa(lp2178 +S'^(a){1,3}' +p2179 +ag3 +a(lp2180 +(S'bcd' +p2181 +S'No match' +p2182 +tp2183 +a(S'abc' +p2184 +S' 0: a' +p2185 +tp2186 +a(S'aab' +p2187 +S' 0: aa' +p2188 +tp2189 +a(S'aaa' +p2190 +S' 0: aaa' +p2191 +tp2192 +aaa(lp2193 +S'^(a){1,}' +p2194 +ag3 +a(lp2195 +(S'bcd' +p2196 +S'No match' +p2197 +tp2198 +a(S'abc' +p2199 +S' 0: a' +p2200 +tp2201 +a(S'aab' +p2202 +S' 0: aa' +p2203 +tp2204 +a(S'aaa' +p2205 +S' 0: aaa' +p2206 +tp2207 +a(S'aaaaaaaa' +p2208 +S' 0: aaaaaaaa' +p2209 +tp2210 +aaa(lp2211 +S'.*\\.gif' +p2212 +ag3 +a(lp2213 +(S'borfle\nbib.gif\nno' +p2214 +S' 0: bib.gif' +p2215 +tp2216 +aaa(lp2217 +S'.{0,}\\.gif' +p2218 +ag3 +a(lp2219 +(S'borfle\nbib.gif\nno' +p2220 +S' 0: bib.gif' +p2221 +tp2222 +aaa(lp2223 +S'.*$' +p2224 +ag3 +a(lp2225 +(S'borfle\nbib.gif\nno' +p2226 +S' 0: no' +p2227 +tp2228 +aaa(lp2229 +S'.*$' +p2230 +ag3 +a(lp2231 +(S'borfle\nbib.gif\nno\n' +p2232 +S' 0: no' +p2233 +tp2234 +aaa(lp2235 +S'^.*B' +p2236 +ag3 +a(lp2237 +(S'**** Failers' +p2238 +S'No match' +p2239 +tp2240 +a(S'abc\nB' +p2241 +S'No match' +p2242 +tp2243 +aaa(lp2244 +S'^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' +p2245 +ag3 +a(lp2246 +(S'123456654321' +p2247 +S' 0: 123456654321' +p2248 +tp2249 +aaa(lp2250 +S'^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d' +p2251 +ag3 +a(lp2252 +(S'123456654321' +p2253 +S' 0: 123456654321' +p2254 +tp2255 +aaa(lp2256 +S'^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]' +p2257 +ag3 +a(lp2258 +(S'123456654321' +p2259 +S' 0: 123456654321' +p2260 +tp2261 +aaa(lp2262 +S'^[abc]{12}' +p2263 +ag3 +a(lp2264 +(S'abcabcabcabc' +p2265 +S' 0: abcabcabcabc' +p2266 +tp2267 +aaa(lp2268 +S'^[a-c]{12}' +p2269 +ag3 +a(lp2270 +(S'abcabcabcabc' +p2271 +S' 0: abcabcabcabc' +p2272 +tp2273 +aaa(lp2274 +S'^(a|b|c){12}' +p2275 +ag3 +a(lp2276 +(S'abcabcabcabc' +p2277 +S' 0: abcabcabcabc' +p2278 +tp2279 +aaa(lp2280 +S'^[abcdefghijklmnopqrstuvwxy0123456789]' +p2281 +ag3 +a(lp2282 +(S'n' +p2283 +S' 0: n' +p2284 +tp2285 +a(S'*** Failers' +p2286 +S'No match' +p2287 +tp2288 +a(g1428 +S'No match' +p2289 +tp2290 +aaa(lp2291 +S'abcde{0,0}' +p2292 +ag3 +a(lp2293 +(S'abcd' +p2294 +S' 0: abcd' +p2295 +tp2296 +a(S'*** Failers' +p2297 +S'No match' +p2298 +tp2299 +a(S'abce' +p2300 +S'No match' +p2301 +tp2302 +aaa(lp2303 +S'ab[cd]{0,0}e' +p2304 +ag3 +a(lp2305 +(S'abe' +p2306 +S' 0: abe' +p2307 +tp2308 +a(S'*** Failers' +p2309 +S'No match' +p2310 +tp2311 +a(S'abcde' +p2312 +S'No match' +p2313 +tp2314 +aaa(lp2315 +S'ab(c){0,0}d' +p2316 +ag3 +a(lp2317 +(S'abd' +p2318 +S' 0: abd' +p2319 +tp2320 +a(S'*** Failers' +p2321 +S'No match' +p2322 +tp2323 +a(S'abcd' +p2324 +S'No match' +p2325 +tp2326 +aaa(lp2327 +S'a(b*)' +p2328 +ag3 +a(lp2329 +(g41 +S' 0: a' +p2330 +tp2331 +a(S'ab' +p2332 +S' 0: ab' +p2333 +tp2334 +a(S'abbbb' +p2335 +S' 0: abbbb' +p2336 +tp2337 +a(S'*** Failers' +p2338 +S' 0: a' +p2339 +tp2340 +a(S'bbbbb' +p2341 +S'No match' +p2342 +tp2343 +aaa(lp2344 +S'ab\\d{0}e' +p2345 +ag3 +a(lp2346 +(S'abe' +p2347 +S' 0: abe' +p2348 +tp2349 +a(S'*** Failers' +p2350 +S'No match' +p2351 +tp2352 +a(S'ab1e' +p2353 +S'No match' +p2354 +tp2355 +aaa(lp2356 +S'"([^\\\\"]+|\\\\.)*"' +p2357 +ag3 +a(lp2358 +(S'the "quick" brown fox' +p2359 +S' 0: "quick"' +p2360 +tp2361 +a(S'"the \\"quick\\" brown fox"' +p2362 +S' 0: "the \\"quick\\" brown fox"' +p2363 +tp2364 +aaa(lp2365 +S'a[^a]b' +p2366 +ag3 +a(lp2367 +(S'acb' +p2368 +S' 0: acb' +p2369 +tp2370 +a(S'a\nb' +p2371 +S' 0: a\nb' +p2372 +tp2373 +aaa(lp2374 +S'a.b' +p2375 +ag3 +a(lp2376 +(S'acb' +p2377 +S' 0: acb' +p2378 +tp2379 +a(S'*** Failers' +p2380 +S'No match' +p2381 +tp2382 +a(S'a\nb' +p2383 +S'No match' +p2384 +tp2385 +aaa(lp2386 +S'\\x00{ab}' +p2387 +ag3 +a(lp2388 +(S'\x00{ab}' +p2389 +S' 0: \x00{ab}' +p2390 +tp2391 +aaa(lp2392 +S'(A|B)*CD' +p2393 +ag3 +a(lp2394 +(S'CD' +p2395 +S' 0: CD' +p2396 +tp2397 +aaa(lp2398 +S'(\\d+)(\\w)' +p2399 +ag3 +a(lp2400 +(S'12345a' +p2401 +S' 0: 12345a' +p2402 +tp2403 +a(S'12345+' +p2404 +S' 0: 12345' +p2405 +tp2406 +aaa(lp2407 +S'(a+|b+|c+)*c' +p2408 +ag3 +a(lp2409 +(S'aaabbbbccccd' +p2410 +S' 0: aaabbbbcccc' +p2411 +tp2412 +aaa(lp2413 +S'(abc|)+' +p2414 +ag3 +a(lp2415 +(S'abc' +p2416 +S' 0: abc' +p2417 +tp2418 +a(S'abcabc' +p2419 +S' 0: abcabc' +p2420 +tp2421 +a(S'abcabcabc' +p2422 +S' 0: abcabcabc' +p2423 +tp2424 +a(S'xyz' +p2425 +S' 0: ' +p2426 +tp2427 +aaa(lp2428 +S'([a]*)*' +p2429 +ag3 +a(lp2430 +(g41 +S' 0: a' +p2431 +tp2432 +a(S'aaaaa' +p2433 +S' 0: aaaaa' +p2434 +tp2435 +aaa(lp2436 +S'([ab]*)*' +p2437 +ag3 +a(lp2438 +(g41 +S' 0: a' +p2439 +tp2440 +a(g1679 +S' 0: b' +p2441 +tp2442 +a(S'ababab' +p2443 +S' 0: ababab' +p2444 +tp2445 +a(S'aaaabcde' +p2446 +S' 0: aaaab' +p2447 +tp2448 +a(S'bbbb' +p2449 +S' 0: bbbb' +p2450 +tp2451 +aaa(lp2452 +S'([^a]*)*' +p2453 +ag3 +a(lp2454 +(g1679 +S' 0: b' +p2455 +tp2456 +a(S'bbbb' +p2457 +S' 0: bbbb' +p2458 +tp2459 +a(S'aaa' +p2460 +S' 0: ' +p2461 +tp2462 +aaa(lp2463 +S'([^ab]*)*' +p2464 +ag3 +a(lp2465 +(S'cccc' +p2466 +S' 0: cccc' +p2467 +tp2468 +a(S'abab' +p2469 +S' 0: ' +p2470 +tp2471 +aaa(lp2472 +S'The following tests are taken from the Perl 5.005 test suite; some of them' +p2473 +ag3 +a(lp2474 +(S"/are compatible with 5.004, but I'd rather not have to sort them out./" +p2475 +S'No match' +p2476 +tp2477 +aaa(lp2478 +S'abc' +p2479 +ag3 +a(lp2480 +(S'abc' +p2481 +S' 0: abc' +p2482 +tp2483 +a(S'xabcy' +p2484 +S' 0: abc' +p2485 +tp2486 +a(S'ababc' +p2487 +S' 0: abc' +p2488 +tp2489 +a(S'*** Failers' +p2490 +S'No match' +p2491 +tp2492 +a(S'xbc' +p2493 +S'No match' +p2494 +tp2495 +a(S'axc' +p2496 +S'No match' +p2497 +tp2498 +a(S'abx' +p2499 +S'No match' +p2500 +tp2501 +aaa(lp2502 +S'ab*c' +p2503 +ag3 +a(lp2504 +(S'abc' +p2505 +S' 0: abc' +p2506 +tp2507 +aaa(lp2508 +S'ab*bc' +p2509 +ag3 +a(lp2510 +(S'abc' +p2511 +S' 0: abc' +p2512 +tp2513 +a(S'abbc' +p2514 +S' 0: abbc' +p2515 +tp2516 +a(S'abbbbc' +p2517 +S' 0: abbbbc' +p2518 +tp2519 +aaa(lp2520 +S'.{1}' +p2521 +ag3 +a(lp2522 +(S'abbbbc' +p2523 +S' 0: a' +p2524 +tp2525 +aaa(lp2526 +S'.{3,4}' +p2527 +ag3 +a(lp2528 +(S'abbbbc' +p2529 +S' 0: abbb' +p2530 +tp2531 +aaa(lp2532 +S'ab{0,}bc' +p2533 +ag3 +a(lp2534 +(S'abbbbc' +p2535 +S' 0: abbbbc' +p2536 +tp2537 +aaa(lp2538 +S'ab+bc' +p2539 +ag3 +a(lp2540 +(S'abbc' +p2541 +S' 0: abbc' +p2542 +tp2543 +a(S'*** Failers' +p2544 +S'No match' +p2545 +tp2546 +a(S'abc' +p2547 +S'No match' +p2548 +tp2549 +a(S'abq' +p2550 +S'No match' +p2551 +tp2552 +aaa(lp2553 +S'ab{1,}bc' +p2554 +ag3 +a(lp2555 +aa(lp2556 +S'ab+bc' +p2557 +ag3 +a(lp2558 +(S'abbbbc' +p2559 +S' 0: abbbbc' +p2560 +tp2561 +aaa(lp2562 +S'ab{1,}bc' +p2563 +ag3 +a(lp2564 +(S'abbbbc' +p2565 +S' 0: abbbbc' +p2566 +tp2567 +aaa(lp2568 +S'ab{1,3}bc' +p2569 +ag3 +a(lp2570 +(S'abbbbc' +p2571 +S' 0: abbbbc' +p2572 +tp2573 +aaa(lp2574 +S'ab{3,4}bc' +p2575 +ag3 +a(lp2576 +(S'abbbbc' +p2577 +S' 0: abbbbc' +p2578 +tp2579 +aaa(lp2580 +S'ab{4,5}bc' +p2581 +ag3 +a(lp2582 +(S'*** Failers' +p2583 +S'No match' +p2584 +tp2585 +a(S'abq' +p2586 +S'No match' +p2587 +tp2588 +a(S'abbbbc' +p2589 +S'No match' +p2590 +tp2591 +aaa(lp2592 +S'ab?bc' +p2593 +ag3 +a(lp2594 +(S'abbc' +p2595 +S' 0: abbc' +p2596 +tp2597 +a(S'abc' +p2598 +S' 0: abc' +p2599 +tp2600 +aaa(lp2601 +S'ab{0,1}bc' +p2602 +ag3 +a(lp2603 +(S'abc' +p2604 +S' 0: abc' +p2605 +tp2606 +aaa(lp2607 +S'ab?bc' +p2608 +ag3 +a(lp2609 +aa(lp2610 +S'ab?c' +p2611 +ag3 +a(lp2612 +(S'abc' +p2613 +S' 0: abc' +p2614 +tp2615 +aaa(lp2616 +S'ab{0,1}c' +p2617 +ag3 +a(lp2618 +(S'abc' +p2619 +S' 0: abc' +p2620 +tp2621 +aaa(lp2622 +S'^abc$' +p2623 +ag3 +a(lp2624 +(S'abc' +p2625 +S' 0: abc' +p2626 +tp2627 +a(S'*** Failers' +p2628 +S'No match' +p2629 +tp2630 +a(S'abbbbc' +p2631 +S'No match' +p2632 +tp2633 +a(S'abcc' +p2634 +S'No match' +p2635 +tp2636 +aaa(lp2637 +S'^abc' +p2638 +ag3 +a(lp2639 +(S'abcc' +p2640 +S' 0: abc' +p2641 +tp2642 +aaa(lp2643 +S'^abc$' +p2644 +ag3 +a(lp2645 +aa(lp2646 +S'abc$' +p2647 +ag3 +a(lp2648 +(S'aabc' +p2649 +S' 0: abc' +p2650 +tp2651 +a(S'*** Failers' +p2652 +S'No match' +p2653 +tp2654 +a(S'aabc' +p2655 +S' 0: abc' +p2656 +tp2657 +a(S'aabcd' +p2658 +S'No match' +p2659 +tp2660 +aaa(lp2661 +S'^' +p2662 +ag3 +a(lp2663 +(S'abc' +p2664 +S' 0: ' +p2665 +tp2666 +aaa(lp2667 +S'$' +p2668 +ag3 +a(lp2669 +(S'abc' +p2670 +S' 0: ' +p2671 +tp2672 +aaa(lp2673 +S'a.c' +p2674 +ag3 +a(lp2675 +(S'abc' +p2676 +S' 0: abc' +p2677 +tp2678 +a(S'axc' +p2679 +S' 0: axc' +p2680 +tp2681 +aaa(lp2682 +S'a.*c' +p2683 +ag3 +a(lp2684 +(S'axyzc' +p2685 +S' 0: axyzc' +p2686 +tp2687 +aaa(lp2688 +S'a[bc]d' +p2689 +ag3 +a(lp2690 +(S'abd' +p2691 +S' 0: abd' +p2692 +tp2693 +a(S'*** Failers' +p2694 +S'No match' +p2695 +tp2696 +a(S'axyzd' +p2697 +S'No match' +p2698 +tp2699 +a(S'abc' +p2700 +S'No match' +p2701 +tp2702 +aaa(lp2703 +S'a[b-d]e' +p2704 +ag3 +a(lp2705 +(S'ace' +p2706 +S' 0: ace' +p2707 +tp2708 +aaa(lp2709 +S'a[b-d]' +p2710 +ag3 +a(lp2711 +(S'aac' +p2712 +S' 0: ac' +p2713 +tp2714 +aaa(lp2715 +S'a[-b]' +p2716 +ag3 +a(lp2717 +(S'a-' +p2718 +S' 0: a-' +p2719 +tp2720 +aaa(lp2721 +S'a[b-]' +p2722 +ag3 +a(lp2723 +(S'a-' +p2724 +S' 0: a-' +p2725 +tp2726 +aaa(lp2727 +S'a]' +p2728 +ag3 +a(lp2729 +(S'a]' +p2730 +S' 0: a]' +p2731 +tp2732 +aaa(lp2733 +S'a[]]b' +p2734 +ag3 +a(lp2735 +(S'a]b' +p2736 +S' 0: a]b' +p2737 +tp2738 +aaa(lp2739 +S'a[^bc]d' +p2740 +ag3 +a(lp2741 +(S'aed' +p2742 +S' 0: aed' +p2743 +tp2744 +a(S'*** Failers' +p2745 +S'No match' +p2746 +tp2747 +a(S'abd' +p2748 +S'No match' +p2749 +tp2750 +a(S'abd' +p2751 +S'No match' +p2752 +tp2753 +aaa(lp2754 +S'a[^-b]c' +p2755 +ag3 +a(lp2756 +(S'adc' +p2757 +S' 0: adc' +p2758 +tp2759 +aaa(lp2760 +S'a[^]b]c' +p2761 +ag3 +a(lp2762 +(S'adc' +p2763 +S' 0: adc' +p2764 +tp2765 +a(S'*** Failers' +p2766 +S'No match' +p2767 +tp2768 +a(S'a-c' +p2769 +S' 0: a-c' +p2770 +tp2771 +a(S'a]c' +p2772 +S'No match' +p2773 +tp2774 +aaa(lp2775 +S'\\ba\\b' +p2776 +ag3 +a(lp2777 +(S'a-' +p2778 +S' 0: a' +p2779 +tp2780 +a(S'-a' +p2781 +S' 0: a' +p2782 +tp2783 +a(S'-a-' +p2784 +S' 0: a' +p2785 +tp2786 +aaa(lp2787 +S'\\by\\b' +p2788 +ag3 +a(lp2789 +(S'*** Failers' +p2790 +S'No match' +p2791 +tp2792 +a(S'xy' +p2793 +S'No match' +p2794 +tp2795 +a(S'yz' +p2796 +S'No match' +p2797 +tp2798 +a(S'xyz' +p2799 +S'No match' +p2800 +tp2801 +aaa(lp2802 +S'\\Ba\\B' +p2803 +ag3 +a(lp2804 +(S'*** Failers' +p2805 +S' 0: a' +p2806 +tp2807 +a(S'a-' +p2808 +S'No match' +p2809 +tp2810 +a(S'-a' +p2811 +S'No match' +p2812 +tp2813 +a(S'-a-' +p2814 +S'No match' +p2815 +tp2816 +aaa(lp2817 +S'\\By\\b' +p2818 +ag3 +a(lp2819 +(S'xy' +p2820 +S' 0: y' +p2821 +tp2822 +aaa(lp2823 +S'\\by\\B' +p2824 +ag3 +a(lp2825 +(S'yz' +p2826 +S' 0: y' +p2827 +tp2828 +aaa(lp2829 +S'\\By\\B' +p2830 +ag3 +a(lp2831 +(S'xyz' +p2832 +S' 0: y' +p2833 +tp2834 +aaa(lp2835 +S'\\w' +p2836 +ag3 +a(lp2837 +(g41 +S' 0: a' +p2838 +tp2839 +aaa(lp2840 +S'\\W' +p2841 +ag3 +a(lp2842 +(S'-' +p2843 +S' 0: -' +p2844 +tp2845 +a(S'*** Failers' +p2846 +S' 0: *' +p2847 +tp2848 +a(g2843 +S' 0: -' +p2849 +tp2850 +a(g41 +S'No match' +p2851 +tp2852 +aaa(lp2853 +S'a\\sb' +p2854 +ag3 +a(lp2855 +(S'a b' +p2856 +S' 0: a b' +p2857 +tp2858 +aaa(lp2859 +S'a\\Sb' +p2860 +ag3 +a(lp2861 +(S'a-b' +p2862 +S' 0: a-b' +p2863 +tp2864 +a(S'*** Failers' +p2865 +S'No match' +p2866 +tp2867 +a(S'a-b' +p2868 +S' 0: a-b' +p2869 +tp2870 +a(S'a b' +p2871 +S'No match' +p2872 +tp2873 +aaa(lp2874 +S'\\d' +p2875 +ag3 +a(lp2876 +(g1177 +S' 0: 1' +p2877 +tp2878 +aaa(lp2879 +S'\\D' +p2880 +ag3 +a(lp2881 +(g2843 +S' 0: -' +p2882 +tp2883 +a(S'*** Failers' +p2884 +S' 0: *' +p2885 +tp2886 +a(g2843 +S' 0: -' +p2887 +tp2888 +a(g1177 +S'No match' +p2889 +tp2890 +aaa(lp2891 +S'[\\w]' +p2892 +ag3 +a(lp2893 +(g41 +S' 0: a' +p2894 +tp2895 +aaa(lp2896 +S'[\\W]' +p2897 +ag3 +a(lp2898 +(g2843 +S' 0: -' +p2899 +tp2900 +a(S'*** Failers' +p2901 +S' 0: *' +p2902 +tp2903 +a(g2843 +S' 0: -' +p2904 +tp2905 +a(g41 +S'No match' +p2906 +tp2907 +aaa(lp2908 +S'a[\\s]b' +p2909 +ag3 +a(lp2910 +(S'a b' +p2911 +S' 0: a b' +p2912 +tp2913 +aaa(lp2914 +S'a[\\S]b' +p2915 +ag3 +a(lp2916 +(S'a-b' +p2917 +S' 0: a-b' +p2918 +tp2919 +a(S'*** Failers' +p2920 +S'No match' +p2921 +tp2922 +a(S'a-b' +p2923 +S' 0: a-b' +p2924 +tp2925 +a(S'a b' +p2926 +S'No match' +p2927 +tp2928 +aaa(lp2929 +S'[\\d]' +p2930 +ag3 +a(lp2931 +(g1177 +S' 0: 1' +p2932 +tp2933 +aaa(lp2934 +S'[\\D]' +p2935 +ag3 +a(lp2936 +(g2843 +S' 0: -' +p2937 +tp2938 +a(S'*** Failers' +p2939 +S' 0: *' +p2940 +tp2941 +a(g2843 +S' 0: -' +p2942 +tp2943 +a(g1177 +S'No match' +p2944 +tp2945 +aaa(lp2946 +S'ab|cd' +p2947 +ag3 +a(lp2948 +(S'abc' +p2949 +S' 0: ab' +p2950 +tp2951 +a(S'abcd' +p2952 +S' 0: ab' +p2953 +tp2954 +aaa(lp2955 +S'()ef' +p2956 +ag3 +a(lp2957 +(S'def' +p2958 +S' 0: ef' +p2959 +tp2960 +aaa(lp2961 +S'$b' +p2962 +ag3 +a(lp2963 +aa(lp2964 +S'a\\(b' +p2965 +ag3 +a(lp2966 +(S'a(b' +p2967 +S' 0: a(b' +p2968 +tp2969 +aaa(lp2970 +S'a\\(*b' +p2971 +ag3 +a(lp2972 +(S'ab' +p2973 +S' 0: ab' +p2974 +tp2975 +a(S'a((b' +p2976 +S' 0: a((b' +p2977 +tp2978 +aaa(lp2979 +S'a\\\\b' +p2980 +ag3 +a(lp2981 +(S'a\x08' +p2982 +S'No match' +p2983 +tp2984 +aaa(lp2985 +S'((a))' +p2986 +ag3 +a(lp2987 +(S'abc' +p2988 +S' 0: a' +p2989 +tp2990 +aaa(lp2991 +S'(a)b(c)' +p2992 +ag3 +a(lp2993 +(S'abc' +p2994 +S' 0: abc' +p2995 +tp2996 +aaa(lp2997 +S'a+b+c' +p2998 +ag3 +a(lp2999 +(S'aabbabc' +p3000 +S' 0: abc' +p3001 +tp3002 +aaa(lp3003 +S'a{1,}b{1,}c' +p3004 +ag3 +a(lp3005 +(S'aabbabc' +p3006 +S' 0: abc' +p3007 +tp3008 +aaa(lp3009 +S'(a+|b)*' +p3010 +ag3 +a(lp3011 +(S'ab' +p3012 +S' 0: ab' +p3013 +tp3014 +aaa(lp3015 +S'(a+|b){0,}' +p3016 +ag3 +a(lp3017 +(S'ab' +p3018 +S' 0: ab' +p3019 +tp3020 +aaa(lp3021 +S'(a+|b)+' +p3022 +ag3 +a(lp3023 +(S'ab' +p3024 +S' 0: ab' +p3025 +tp3026 +aaa(lp3027 +S'(a+|b){1,}' +p3028 +ag3 +a(lp3029 +(S'ab' +p3030 +S' 0: ab' +p3031 +tp3032 +aaa(lp3033 +S'(a+|b)?' +p3034 +ag3 +a(lp3035 +(S'ab' +p3036 +S' 0: a' +p3037 +tp3038 +aaa(lp3039 +S'(a+|b){0,1}' +p3040 +ag3 +a(lp3041 +(S'ab' +p3042 +S' 0: a' +p3043 +tp3044 +aaa(lp3045 +S'[^ab]*' +p3046 +ag3 +a(lp3047 +(S'cde' +p3048 +S' 0: cde' +p3049 +tp3050 +aaa(lp3051 +S'abc' +p3052 +ag3 +a(lp3053 +(S'*** Failers' +p3054 +S'No match' +p3055 +tp3056 +a(g1679 +S'No match' +p3057 +tp3058 +aaa(lp3059 +S'a*' +p3060 +ag3 +a(lp3061 +aa(lp3062 +S'([abc])*d' +p3063 +ag3 +a(lp3064 +(S'abbbcd' +p3065 +S' 0: abbbcd' +p3066 +tp3067 +aaa(lp3068 +S'([abc])*bcd' +p3069 +ag3 +a(lp3070 +(S'abcd' +p3071 +S' 0: abcd' +p3072 +tp3073 +aaa(lp3074 +S'a|b|c|d|e' +p3075 +ag3 +a(lp3076 +(S'e' +p3077 +S' 0: e' +p3078 +tp3079 +aaa(lp3080 +S'(a|b|c|d|e)f' +p3081 +ag3 +a(lp3082 +(S'ef' +p3083 +S' 0: ef' +p3084 +tp3085 +aaa(lp3086 +S'abcd*efg' +p3087 +ag3 +a(lp3088 +(S'abcdefg' +p3089 +S' 0: abcdefg' +p3090 +tp3091 +aaa(lp3092 +S'ab*' +p3093 +ag3 +a(lp3094 +(S'xabyabbbz' +p3095 +S' 0: ab' +p3096 +tp3097 +a(S'xayabbbz' +p3098 +S' 0: a' +p3099 +tp3100 +aaa(lp3101 +S'(ab|cd)e' +p3102 +ag3 +a(lp3103 +(S'abcde' +p3104 +S' 0: cde' +p3105 +tp3106 +aaa(lp3107 +S'[abhgefdc]ij' +p3108 +ag3 +a(lp3109 +(S'hij' +p3110 +S' 0: hij' +p3111 +tp3112 +aaa(lp3113 +S'^(ab|cd)e' +p3114 +ag3 +a(lp3115 +aa(lp3116 +S'(abc|)ef' +p3117 +ag3 +a(lp3118 +(S'abcdef' +p3119 +S' 0: ef' +p3120 +tp3121 +aaa(lp3122 +S'(a|b)c*d' +p3123 +ag3 +a(lp3124 +(S'abcd' +p3125 +S' 0: bcd' +p3126 +tp3127 +aaa(lp3128 +S'(ab|ab*)bc' +p3129 +ag3 +a(lp3130 +(S'abc' +p3131 +S' 0: abc' +p3132 +tp3133 +aaa(lp3134 +S'a([bc]*)c*' +p3135 +ag3 +a(lp3136 +(S'abc' +p3137 +S' 0: abc' +p3138 +tp3139 +aaa(lp3140 +S'a([bc]*)(c*d)' +p3141 +ag3 +a(lp3142 +(S'abcd' +p3143 +S' 0: abcd' +p3144 +tp3145 +aaa(lp3146 +S'a([bc]+)(c*d)' +p3147 +ag3 +a(lp3148 +(S'abcd' +p3149 +S' 0: abcd' +p3150 +tp3151 +aaa(lp3152 +S'a([bc]*)(c+d)' +p3153 +ag3 +a(lp3154 +(S'abcd' +p3155 +S' 0: abcd' +p3156 +tp3157 +aaa(lp3158 +S'a[bcd]*dcdcde' +p3159 +ag3 +a(lp3160 +(S'adcdcde' +p3161 +S' 0: adcdcde' +p3162 +tp3163 +aaa(lp3164 +S'a[bcd]+dcdcde' +p3165 +ag3 +a(lp3166 +(S'*** Failers' +p3167 +S'No match' +p3168 +tp3169 +a(S'abcde' +p3170 +S'No match' +p3171 +tp3172 +a(S'adcdcde' +p3173 +S'No match' +p3174 +tp3175 +aaa(lp3176 +S'(ab|a)b*c' +p3177 +ag3 +a(lp3178 +(S'abc' +p3179 +S' 0: abc' +p3180 +tp3181 +aaa(lp3182 +S'((a)(b)c)(d)' +p3183 +ag3 +a(lp3184 +(S'abcd' +p3185 +S' 0: abcd' +p3186 +tp3187 +aaa(lp3188 +S'[a-zA-Z_][a-zA-Z0-9_]*' +p3189 +ag3 +a(lp3190 +(S'alpha' +p3191 +S' 0: alpha' +p3192 +tp3193 +aaa(lp3194 +S'^a(bc+|b[eh])g|.h$' +p3195 +ag3 +a(lp3196 +(S'abh' +p3197 +S' 0: bh' +p3198 +tp3199 +aaa(lp3200 +S'(bc+d$|ef*g.|h?i(j|k))' +p3201 +ag3 +a(lp3202 +(S'effgz' +p3203 +S' 0: effgz' +p3204 +tp3205 +a(S'ij' +p3206 +S' 0: ij' +p3207 +tp3208 +a(S'reffgz' +p3209 +S' 0: effgz' +p3210 +tp3211 +a(S'*** Failers' +p3212 +S'No match' +p3213 +tp3214 +a(S'effg' +p3215 +S'No match' +p3216 +tp3217 +a(S'bcdd' +p3218 +S'No match' +p3219 +tp3220 +aaa(lp3221 +S'((((((((((a))))))))))' +p3222 +ag3 +a(lp3223 +(g41 +S' 0: a' +p3224 +tp3225 +aaa(lp3226 +S'(((((((((a)))))))))' +p3227 +ag3 +a(lp3228 +(g41 +S' 0: a' +p3229 +tp3230 +aaa(lp3231 +S'multiple words of text' +p3232 +ag3 +a(lp3233 +(S'*** Failers' +p3234 +S'No match' +p3235 +tp3236 +a(S'aa' +p3237 +S'No match' +p3238 +tp3239 +a(S'uh-uh' +p3240 +S'No match' +p3241 +tp3242 +aaa(lp3243 +S'multiple words' +p3244 +ag3 +a(lp3245 +(S'multiple words, yeah' +p3246 +S' 0: multiple words' +p3247 +tp3248 +aaa(lp3249 +S'(.*)c(.*)' +p3250 +ag3 +a(lp3251 +(S'abcde' +p3252 +S' 0: abcde' +p3253 +tp3254 +aaa(lp3255 +S'\\((.*), (.*)\\)' +p3256 +ag3 +a(lp3257 +(S'(a, b)' +p3258 +S' 0: (a, b)' +p3259 +tp3260 +aaa(lp3261 +S'[k]' +p3262 +ag3 +a(lp3263 +aa(lp3264 +S'abcd' +p3265 +ag3 +a(lp3266 +(S'abcd' +p3267 +S' 0: abcd' +p3268 +tp3269 +aaa(lp3270 +S'a(bc)d' +p3271 +ag3 +a(lp3272 +(S'abcd' +p3273 +S' 0: abcd' +p3274 +tp3275 +aaa(lp3276 +S'a[-]?c' +p3277 +ag3 +a(lp3278 +(S'ac' +p3279 +S' 0: ac' +p3280 +tp3281 +aaa(lp3282 +S'((foo)|(bar))*' +p3283 +ag3 +a(lp3284 +(S'foobar' +p3285 +S' 0: foobar' +p3286 +tp3287 +aaa(lp3288 +S'^(.+)?B' +p3289 +ag3 +a(lp3290 +(S'AB' +p3291 +S' 0: AB' +p3292 +tp3293 +aaa(lp3294 +S'^([^a-z])|(\\^)$' +p3295 +ag3 +a(lp3296 +(S'.' +p3297 +S' 0: .' +p3298 +tp3299 +aaa(lp3300 +S'^[<>]&' +p3301 +ag3 +a(lp3302 +(S'<&OUT' +p3303 +S' 0: <&' +p3304 +tp3305 +aaa(lp3306 +S'^(){3,5}' +p3307 +ag3 +a(lp3308 +(S'abc' +p3309 +S' 0: ' +p3310 +tp3311 +aaa(lp3312 +S'^(a+)*ax' +p3313 +ag3 +a(lp3314 +(S'aax' +p3315 +S' 0: aax' +p3316 +tp3317 +aaa(lp3318 +S'^((a|b)+)*ax' +p3319 +ag3 +a(lp3320 +(S'aax' +p3321 +S' 0: aax' +p3322 +tp3323 +aaa(lp3324 +S'^((a|bc)+)*ax' +p3325 +ag3 +a(lp3326 +(S'aax' +p3327 +S' 0: aax' +p3328 +tp3329 +aaa(lp3330 +S'(a|x)*ab' +p3331 +ag3 +a(lp3332 +(S'cab' +p3333 +S' 0: ab' +p3334 +tp3335 +aaa(lp3336 +S'(a)*ab' +p3337 +ag3 +a(lp3338 +(S'cab' +p3339 +S' 0: ab' +p3340 +tp3341 +aaa(lp3342 +S'foo\\w*\\d{4}baz' +p3343 +ag3 +a(lp3344 +(S'foobar1234baz' +p3345 +S' 0: foobar1234baz' +p3346 +tp3347 +aaa(lp3348 +S'^b' +p3349 +ag3 +a(lp3350 +aa(lp3351 +S'(\\w+:)+' +p3352 +ag3 +a(lp3353 +(S'one:' +p3354 +S' 0: one:' +p3355 +tp3356 +aaa(lp3357 +S'([\\w:]+::)?(\\w+)$' +p3358 +ag3 +a(lp3359 +(S'abcd' +p3360 +S' 0: abcd' +p3361 +tp3362 +a(S'xy:z:::abcd' +p3363 +S' 0: xy:z:::abcd' +p3364 +tp3365 +aaa(lp3366 +S'^[^bcd]*(c+)' +p3367 +ag3 +a(lp3368 +(S'aexycd' +p3369 +S' 0: aexyc' +p3370 +tp3371 +aaa(lp3372 +S'(a*)b+' +p3373 +ag3 +a(lp3374 +(S'caab' +p3375 +S' 0: aab' +p3376 +tp3377 +aaa(lp3378 +S'([\\w:]+::)?(\\w+)$' +p3379 +ag3 +a(lp3380 +(S'abcd' +p3381 +S' 0: abcd' +p3382 +tp3383 +a(S'xy:z:::abcd' +p3384 +S' 0: xy:z:::abcd' +p3385 +tp3386 +a(S'*** Failers' +p3387 +S' 0: Failers' +p3388 +tp3389 +a(S'abcd:' +p3390 +S'No match' +p3391 +tp3392 +a(S'abcd:' +p3393 +S'No match' +p3394 +tp3395 +aaa(lp3396 +S'^[^bcd]*(c+)' +p3397 +ag3 +a(lp3398 +(S'aexycd' +p3399 +S' 0: aexyc' +p3400 +tp3401 +aaa(lp3402 +S'(>a+)ab' +p3403 +ag3 +a(lp3404 +aa(lp3405 +S'([[:]+)' +p3406 +ag3 +a(lp3407 +(S'a:[b]:' +p3408 +S' 0: :[' +p3409 +tp3410 +aaa(lp3411 +S'([[=]+)' +p3412 +ag3 +a(lp3413 +(S'a=[b]=' +p3414 +S' 0: =[' +p3415 +tp3416 +aaa(lp3417 +S'([[.]+)' +p3418 +ag3 +a(lp3419 +(S'a.[b].' +p3420 +S' 0: .[' +p3421 +tp3422 +aaa(lp3423 +S'a\\Z' +p3424 +ag3 +a(lp3425 +(S'*** Failers' +p3426 +S'No match' +p3427 +tp3428 +a(S'aaab' +p3429 +S'No match' +p3430 +tp3431 +a(S'a\nb\n' +p3432 +S'No match' +p3433 +tp3434 +aaa(lp3435 +S'b\\Z' +p3436 +ag3 +a(lp3437 +(S'a\nb\n' +p3438 +S' 0: b' +p3439 +tp3440 +aaa(lp3441 +S'b\\z' +p3442 +ag3 +a(lp3443 +aa(lp3444 +S'b\\Z' +p3445 +ag3 +a(lp3446 +(S'a\nb' +p3447 +S' 0: b' +p3448 +tp3449 +aaa(lp3450 +S'b\\z' +p3451 +ag3 +a(lp3452 +(S'a\nb' +p3453 +S' 0: b' +p3454 +tp3455 +a(S'*** Failers' +p3456 +S'No match' +p3457 +tp3458 +aaa(lp3459 +S'((Z)+|A)*' +p3460 +ag3 +a(lp3461 +(S'ZABCDEFG' +p3462 +S' 0: ZA' +p3463 +tp3464 +aaa(lp3465 +S'(Z()|A)*' +p3466 +ag3 +a(lp3467 +(S'ZABCDEFG' +p3468 +S' 0: ZA' +p3469 +tp3470 +aaa(lp3471 +S'(Z(())|A)*' +p3472 +ag3 +a(lp3473 +(S'ZABCDEFG' +p3474 +S' 0: ZA' +p3475 +tp3476 +aaa(lp3477 +S'^[a-\\d]' +p3478 +ag3 +a(lp3479 +(S'abcde' +p3480 +S' 0: a' +p3481 +tp3482 +a(S'-things' +p3483 +S' 0: -' +p3484 +tp3485 +a(S'0digit' +p3486 +S' 0: 0' +p3487 +tp3488 +a(S'*** Failers' +p3489 +S'No match' +p3490 +tp3491 +a(S'bcdef' +p3492 +S'No match' +p3493 +tp3494 +aaa(lp3495 +S'^[\\d-a]' +p3496 +ag3 +a(lp3497 +(S'abcde' +p3498 +S' 0: a' +p3499 +tp3500 +a(S'-things' +p3501 +S' 0: -' +p3502 +tp3503 +a(S'0digit' +p3504 +S' 0: 0' +p3505 +tp3506 +a(S'*** Failers' +p3507 +S'No match' +p3508 +tp3509 +a(S'bcdef' +p3510 +S'No match' +p3511 +tp3512 +aaa(lp3513 +S'[[:space:]]+' +p3514 +ag3 +a(lp3515 +(S'> \t\n\x0c\r\x0b<' +p3516 +S' 0: \t\n\x0c\r\x0b' +p3517 +tp3518 +aaa(lp3519 +S'[[:blank:]]+' +p3520 +ag3 +a(lp3521 +(S'> \t\n\x0c\r\x0b<' +p3522 +S' 0: \t' +p3523 +tp3524 +aaa(lp3525 +S'[\\s]+' +p3526 +ag3 +a(lp3527 +(S'> \t\n\x0c\r\x0b<' +p3528 +S' 0: \t\n\x0c\r' +p3529 +tp3530 +aaa(lp3531 +S'\\s+' +p3532 +ag3 +a(lp3533 +(S'> \t\n\x0c\r\x0b<' +p3534 +S' 0: \t\n\x0c\r' +p3535 +tp3536 +aaa(lp3537 +S'\\Gabc' +p3538 +ag3 +a(lp3539 +(S'abc' +p3540 +S' 0: abc' +p3541 +tp3542 +a(S'*** Failers' +p3543 +S'No match' +p3544 +tp3545 +a(S'xyzabc' +p3546 +S'No match' +p3547 +tp3548 +aaa(lp3549 +S'[\\z\\C]' +p3550 +ag3 +a(lp3551 +(g1428 +S' 0: z' +p3552 +tp3553 +a(S'C' +p3554 +S' 0: C' +p3555 +tp3556 +aaa(lp3557 +S'\\M' +p3558 +ag3 +a(lp3559 +(S'M' +p3560 +S' 0: M' +p3561 +tp3562 +aaa(lp3563 +S'(a+)*b' +p3564 +ag3 +a(lp3565 +(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +p3566 +S'No match' +p3567 +tp3568 +aaa(lp3569 +S'\xc5\xe6\xe5\xe4[\xe0-\xff\xc0-\xdf]+' +p3570 +ag3 +a(lp3571 +(S'\xc5\xe6\xe5\xe4\xe0' +p3572 +S' 0: \xc5\xe6\xe5\xe4\xe0' +p3573 +tp3574 +a(S'\xc5\xe6\xe5\xe4\xff' +p3575 +S' 0: \xc5\xe6\xe5\xe4\xff' +p3576 +tp3577 +a(S'\xc5\xe6\xe5\xe4\xc0' +p3578 +S' 0: \xc5\xe6\xe5\xe4\xc0' +p3579 +tp3580 +a(S'\xc5\xe6\xe5\xe4\xdf' +p3581 +S' 0: \xc5\xe6\xe5\xe4\xdf' +p3582 +tp3583 +aaa(lp3584 +S'line\\nbreak' +p3585 +ag3 +a(lp3586 +(S'this is a line\nbreak' +p3587 +S' 0: line\nbreak' +p3588 +tp3589 +a(S'line one\nthis is a line\nbreak in the second line' +p3590 +S' 0: line\nbreak' +p3591 +tp3592 +aaa(lp3593 +S'1234' +p3594 +ag3 +a(lp3595 +(S'123P' +p3596 +S'No match' +p3597 +tp3598 +aaa(lp3599 +S'1234' +p3600 +ag3 +a(lp3601 +(S'123P' +p3602 +S' 0: 4' +p3603 +tp3604 +aaa(lp3605 +S'Content-Type\\x3A[^\\r\\n]{6,}' +p3606 +ag3 +a(lp3607 +(S'Content-Type:xxxxxyyy' +p3608 +S' 0: Content-Type:xxxxxyyy' +p3609 +tp3610 +aaa(lp3611 +S'Content-Type\\x3A[^\\r\\n]{6,}z' +p3612 +ag3 +a(lp3613 +(S'Content-Type:xxxxxyyyz' +p3614 +S' 0: Content-Type:xxxxxyyyz' +p3615 +tp3616 +aaa(lp3617 +S'Content-Type\\x3A[^a]{6,}' +p3618 +ag3 +a(lp3619 +(S'Content-Type:xxxyyy' +p3620 +S' 0: Content-Type:xxxyyy' +p3621 +tp3622 +aaa(lp3623 +S'Content-Type\\x3A[^a]{6,}z' +p3624 +ag3 +a(lp3625 +(S'Content-Type:xxxyyyz' +p3626 +S' 0: Content-Type:xxxyyyz' +p3627 +tp3628 +aaa(lp3629 +S'^\\w+=.*(\\\\\\n.*)*' +p3630 +ag3 +a(lp3631 +(S'abc=xyz\\\npqr' +p3632 +S' 0: abc=xyz\\\npqr' +p3633 +tp3634 +aaa(lp3635 +S'^(a()*)*' +p3636 +ag3 +a(lp3637 +(S'aaaa' +p3638 +S' 0: aaaa' +p3639 +tp3640 +aaa(lp3641 +S'^(a()+)+' +p3642 +ag3 +a(lp3643 +(S'aaaa' +p3644 +S' 0: aaaa' +p3645 +tp3646 +aaa(lp3647 +S'(a|)*\\d' +p3648 +ag3 +a(lp3649 +(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +p3650 +S'No match' +p3651 +tp3652 +a(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4' +p3653 +S' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4' +p3654 +tp3655 +aaa(lp3656 +S'.+foo' +p3657 +ag3 +a(lp3658 +(S'afoo' +p3659 +S' 0: afoo' +p3660 +tp3661 +a(S'** Failers' +p3662 +S'No match' +p3663 +tp3664 +a(S'\r\nfoo' +p3665 +S'No match' +p3666 +tp3667 +a(S'\nfoo' +p3668 +S'No match' +p3669 +tp3670 +aaa(lp3671 +S'\\H\\h\\V\\v' +p3672 +ag3 +a(lp3673 +(S'X X\n' +p3674 +S' 0: X X\n' +p3675 +tp3676 +a(S'X\tX\x0b' +p3677 +S' 0: X\tX\x0b' +p3678 +tp3679 +a(S'** Failers' +p3680 +S'No match' +p3681 +tp3682 +a(S'\xa0 X\n' +p3683 +S'No match' +p3684 +tp3685 +aaa(lp3686 +S'\\H{3,4}' +p3687 +ag3 +a(lp3688 +(S'XY ABCDE' +p3689 +S' 0: ABCD' +p3690 +tp3691 +a(S'XY PQR ST' +p3692 +S' 0: PQR' +p3693 +tp3694 +aaa(lp3695 +S'.\\h{3,4}.' +p3696 +ag3 +a(lp3697 +(S'XY AB PQRS' +p3698 +S' 0: B P' +p3699 +tp3700 +aaa(lp3701 +S'\\h*X\\h?\\H+Y\\H?Z' +p3702 +ag3 +a(lp3703 +(S'>XNNNYZ' +p3704 +S' 0: XNNNYZ' +p3705 +tp3706 +a(S'> X NYQZ' +p3707 +S' 0: X NYQZ' +p3708 +tp3709 +a(S'** Failers' +p3710 +S'No match' +p3711 +tp3712 +a(S'>XYZ' +p3713 +S'No match' +p3714 +tp3715 +a(S'> X NY Z' +p3716 +S'No match' +p3717 +tp3718 +aaa(lp3719 +S'\\v*X\\v?Y\\v+Z\\V*\\x0a\\V+\\x0b\\V{2,3}\\x0c' +p3720 +ag3 +a(lp3721 +(S'>XY\nZ\nA\x0bNN\x0c' +p3722 +S' 0: XY\nZ\nA\x0bNN\x0c' +p3723 +tp3724 +a(S'>\n\rX\nY\n\x0bZZZ\nAAA\x0bNNN\x0c' +p3725 +S' 0: \n\rX\nY\n\x0bZZZ\nAAA\x0bNNN\x0c' +p3726 +tp3727 +aaa(lp3728 +S' End of testinput7 ' +p3729 +ag3 +a(lp3730 +aa. \ No newline at end of file From antocuni at codespeak.net Thu Apr 3 15:09:03 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 3 Apr 2008 15:09:03 +0200 (CEST) Subject: [pypy-svn] r53280 - in pypy/branch/jit-hotpath/pypy: jit/rainbow/test rpython/lltypesystem rpython/ootypesystem translator/backendopt Message-ID: <20080403130903.45444169FCD@codespeak.net> Author: antocuni Date: Thu Apr 3 15:09:01 2008 New Revision: 53280 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lltype.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py pypy/branch/jit-hotpath/pypy/translator/backendopt/graphanalyze.py Log: - teach ImpurityAnalizer how to check if calls to external methods are pure - mark all methods of ootype.String and ootype.Unicode as pure - rewrite test_plus_minus to use an RPython string instead of a lowlevel string, so that it can work also with ootype - after all of this, test_plus_minus passes :-) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 3 15:09:01 2008 @@ -13,7 +13,6 @@ from pypy.rpython.lltypesystem import lltype, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.llinterp import LLInterpreter, LLException -from pypy.rpython.module.support import LLSupport from pypy.annotation import model as annmodel from pypy.annotation.policy import AnnotatorPolicy from pypy.objspace.flow.model import summary, Variable @@ -818,7 +817,9 @@ assert res.x == 123 def test_plus_minus(self): - def ll_plus_minus(s, x, y): + PROGRAMS = ["+-+"] + def ll_plus_minus(i, x, y): + s = PROGRAMS[i] # to prevent constant-folding acc = x n = len(s) pc = 0 @@ -831,10 +832,9 @@ acc -= y pc += 1 return acc - ll_plus_minus.convert_arguments = [LLSupport.to_rstr, int, int] - res = self.interpret(ll_plus_minus, ["+-+", 0, 2], [0]) - assert res == ll_plus_minus("+-+", 0, 2) - self.check_insns({'int_add': 2, 'int_sub': 1}) + res = self.interpret(ll_plus_minus, [0, 0, 2], [0]) + assert res == ll_plus_minus(0, 0, 2) + self.check_insns({'int_add': 2, 'int_sub': 1, 'direct_call': 1}) def test_red_virtual_container(self): # this checks that red boxes are able to be virtualized dynamically by @@ -2181,7 +2181,6 @@ def _skip(self): py.test.skip('in progress') - test_plus_minus = _skip test_red_array = _skip test_red_struct_array = _skip test_red_varsized_struct = _skip @@ -2217,7 +2216,3 @@ test_void_args = _skip test_ptrequality = _skip test_green_ptrequality = _skip - - - - Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lltype.py Thu Apr 3 15:09:01 2008 @@ -697,7 +697,7 @@ def cast_primitive(TGT, value): ORIG = typeOf(value) if not isinstance(TGT, Primitive) or not isinstance(ORIG, Primitive): - raise TypeError, "can only primitive to primitive" + raise TypeError, "can cast only primitive to primitive" if ORIG == TGT: return value if ORIG == Char or ORIG == UniChar: Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Thu Apr 3 15:09:01 2008 @@ -329,7 +329,7 @@ immutable = False # conservative - def _setup_methods(self, generic_types, can_raise=[]): + def _setup_methods(self, generic_types, can_raise=[], pure_meth=[]): methods = {} for name, meth in self._GENERIC_METHODS.iteritems(): args = [self._specialize_type(arg, generic_types) for arg in meth.ARGS] @@ -339,6 +339,10 @@ methods[name] = METH self._METHODS = frozendict(methods) self._can_raise = tuple(can_raise) + if pure_meth == 'ALL': + self._pure_meth = tuple(methods.keys()) + else: + self._pure_meth = tuple(pure_meth) def _lookup(self, meth_name): METH = self._METHODS.get(meth_name) @@ -346,7 +350,10 @@ if METH is not None: cls = self._get_interp_class() can_raise = meth_name in self._can_raise - meth = _meth(METH, _name=meth_name, _callable=getattr(cls, meth_name), _can_raise=can_raise) + pure_meth = meth_name in self._pure_meth + meth = _meth(METH, _name=meth_name, + _callable=getattr(cls, meth_name), + _can_raise=can_raise, _pure_meth=pure_meth) meth._virtual = False return self, meth @@ -384,7 +391,7 @@ "ll_contains": Meth([self.CHAR], Bool), "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T), }) - self._setup_methods(generic_types) + self._setup_methods(generic_types, pure_meth='ALL') def _example(self): return self._defl() Modified: pypy/branch/jit-hotpath/pypy/translator/backendopt/graphanalyze.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/backendopt/graphanalyze.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/backendopt/graphanalyze.py Thu Apr 3 15:09:01 2008 @@ -148,3 +148,9 @@ except AttributeError: pass return GraphAnalyzer.analyze_direct_call(self, graph, seen) + + def analyze_external_method(self, op, TYPE, meth): + if getattr(meth, "_pure_meth", False): + return False + else: + return GraphAnalyzer.analyze_external_method(self, op, TYPE, meth) From antocuni at codespeak.net Thu Apr 3 16:18:46 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 3 Apr 2008 16:18:46 +0200 (CEST) Subject: [pypy-svn] r53281 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080403141846.D3A5E16850F@codespeak.net> Author: antocuni Date: Thu Apr 3 16:18:44 2008 New Revision: 53281 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: move two tests to TestLLType, and write the equivalent for ootype Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 3 16:18:44 2008 @@ -950,40 +950,6 @@ assert res == 24 self.check_insns({'int_lt': 1, 'int_mul': 1}) - def test_red_subcontainer(self): - S = lltype.GcStruct('S', ('n', lltype.Signed)) - T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - def ll_function(k): - t = lltype.malloc(T) - s = t.s - s.n = k - if k < 0: - return -123 - result = s.n * (k-1) - keepalive_until_here(t) - return result - res = self.interpret(ll_function, [7], []) - assert res == 42 - self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) - - - def test_red_subcontainer_cast(self): - S = lltype.GcStruct('S', ('n', lltype.Signed)) - T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) - def ll_function(k): - t = lltype.malloc(T) - s = lltype.cast_pointer(lltype.Ptr(S), t) - s.n = k - if k < 0: - return -123 - result = s.n * (k-1) - keepalive_until_here(t) - return result - res = self.interpret(ll_function, [7], []) - assert res == 42 - self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) - - def test_merge_structures(self): S = self.GcStruct('S', ('n', lltype.Signed)) T = self.GcStruct('T', ('s', self.Ptr(S)), ('n', lltype.Signed)) @@ -2064,6 +2030,39 @@ res = self.interpret(ll_function, [0], []) assert res == 4 * 4 + def test_red_subcontainer(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + def ll_function(k): + t = lltype.malloc(T) + s = t.s + s.n = k + if k < 0: + return -123 + result = s.n * (k-1) + keepalive_until_here(t) + return result + res = self.interpret(ll_function, [7], []) + assert res == 42 + self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) + + + def test_red_subcontainer_cast(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + def ll_function(k): + t = lltype.malloc(T) + s = lltype.cast_pointer(lltype.Ptr(S), t) + s.n = k + if k < 0: + return -123 + result = s.n * (k-1) + keepalive_until_here(t) + return result + res = self.interpret(ll_function, [7], []) + assert res == 42 + self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) + class TestOOType(SimpleTests): type_system = "ootype" @@ -2178,6 +2177,23 @@ res = self.interpret(ll_function, [0], []) assert res == 4 * 4 + def test_red_subclass(self): + S = ootype.Instance('S', ootype.ROOT, {'x': lltype.Signed}) + T = ootype.Instance('T', S, {'y': lltype.Float}) + + def ll_function(k): + t = ootype.new(T) + s = ootype.ooupcast(S, t) + s.x = k + if k < 0: + return -123 + result = s.x * (k-1) + return result + res = self.interpret(ll_function, [7], []) + assert res == 42 + self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) + + def _skip(self): py.test.skip('in progress') @@ -2185,8 +2201,6 @@ test_red_struct_array = _skip test_red_varsized_struct = _skip test_array_of_voids = _skip - test_red_subcontainer = _skip - test_red_subcontainer_cast = _skip test_deepfrozen_interior = _skip test_compile_time_const_tuple = _skip test_residual_red_call = _skip From niko at codespeak.net Thu Apr 3 16:48:14 2008 From: niko at codespeak.net (niko at codespeak.net) Date: Thu, 3 Apr 2008 16:48:14 +0200 (CEST) Subject: [pypy-svn] r53282 - pypy/branch/fixed-list-ootype-2 Message-ID: <20080403144814.909FF16A03B@codespeak.net> Author: niko Date: Thu Apr 3 16:48:14 2008 New Revision: 53282 Added: pypy/branch/fixed-list-ootype-2/ - copied from r53281, pypy/dist/ Log: make a new branch from the trunk so that we can merge fixed-list-ootype to it From fijal at codespeak.net Thu Apr 3 20:17:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 20:17:02 +0200 (CEST) Subject: [pypy-svn] r53286 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403181702.ED8B816A471@codespeak.net> Author: fijal Date: Thu Apr 3 20:17:01 2008 New Revision: 53286 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: frame access for ints (for floats and bools it needs to be adapted, but we have no tests for that) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 20:17:01 2008 @@ -9,7 +9,6 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import rffi -from pypy.jit.codegen.emit_moves import emit_moves, emit_moves_safe WORD = 4 DEBUG_CALL_ALIGN = True @@ -18,6 +17,17 @@ else: CALL_ALIGN = 1 +def peek_word_at(addr): + # now the Very Obscure Bit: when translated, 'addr' is an + # address. When not, it's an integer. It just happens to + # make the test pass, but that's probably going to change. + if objectmodel.we_are_translated(): + return addr.signed[0] + else: + from ctypes import cast, c_void_p, c_int, POINTER + p = cast(c_void_p(addr), POINTER(c_int)) + return p[0] + class Var(GenVar): def __init__(self, stackpos): @@ -465,6 +475,15 @@ op = eax return self.returnintvar(op) + def genop_get_frame_base(self): + # XXX really? + self.mc.MOV(eax, esp) + self.mc.SUB(eax, imm(self.stackdepth)) + return self.returnintvar(eax) + + def get_frame_info(self, vars_gv): + return vars_gv + 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)) @@ -1430,6 +1449,18 @@ # XXX kind probably goes away return zero_const + @staticmethod + @specialize.arg(0) + def read_frame_var(T, base, info, index): + assert T is lltype.Signed + v = info[index] + value = peek_word_at(base + v.stackpos + 1) + return value + + @staticmethod + def genconst_from_frame_var(kind, base, info, index): + xxx + global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst zero_const = AddrConst(llmemory.NULL) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 20:17:01 2008 @@ -14,7 +14,6 @@ py.test.skip("unsupported") # frame access related - test_read_frame_var_direct = skipped test_genconst_from_frame_var_direct = skipped test_write_frame_place_direct = skipped test_write_lots_of_frame_places_direct = skipped From fijal at codespeak.net Thu Apr 3 20:19:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 20:19:46 +0200 (CEST) Subject: [pypy-svn] r53288 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403181946.1084216A4B5@codespeak.net> Author: fijal Date: Thu Apr 3 20:19:45 2008 New Revision: 53288 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: another one Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 20:19:45 2008 @@ -1459,7 +1459,11 @@ @staticmethod def genconst_from_frame_var(kind, base, info, index): - xxx + # eh, kind here should be "what we're looking for?" + v = info[index] + if isinstance(v, GenConst): + return + return IntConst(peek_word_at(base + v.stackpos + 1)) global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 20:19:45 2008 @@ -14,7 +14,6 @@ py.test.skip("unsupported") # frame access related - test_genconst_from_frame_var_direct = skipped test_write_frame_place_direct = skipped test_write_lots_of_frame_places_direct = skipped test_read_frame_place_direct = skipped From fijal at codespeak.net Thu Apr 3 21:07:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 21:07:53 +0200 (CEST) Subject: [pypy-svn] r53289 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403190753.C7F7D16A688@codespeak.net> Author: fijal Date: Thu Apr 3 21:07:50 2008 New Revision: 53289 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: read_frame_place passes write_frame_place segfaults, still investigating Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 21:07:50 2008 @@ -28,6 +28,17 @@ p = cast(c_void_p(addr), POINTER(c_int)) return p[0] +def poke_word_into(addr, value): + # now the Very Obscure Bit: when translated, 'addr' is an + # address. When not, it's an integer. It just happens to + # make the test pass, but that's probably going to change. + if objectmodel.we_are_translated(): + addr.signed[0] = value + else: + from ctypes import cast, c_void_p, c_int, POINTER + p = cast(c_void_p(addr), POINTER(c_int)) + p[0] = value + class Var(GenVar): def __init__(self, stackpos): @@ -478,7 +489,7 @@ def genop_get_frame_base(self): # XXX really? self.mc.MOV(eax, esp) - self.mc.SUB(eax, imm(self.stackdepth)) + self.mc.SUB(eax, imm(self.stackdepth - 1)) return self.returnintvar(eax) def get_frame_info(self, vars_gv): @@ -687,7 +698,10 @@ def returnintvar(self, op): res = IntVar(self.stackdepth) - self.push(op) + if op is None: + self.push(imm(0)) + else: + self.push(op) return res def returnboolvar(self, op): @@ -1059,6 +1073,16 @@ self.mc.FILD(gv_x.operand(self)) return self.returnfloatvar(st0) + def alloc_frame_place(self, kind, gv_initial_value=None): + # XXX kind + if gv_initial_value is not None: + return self.returnintvar(gv_initial_value.operand(self)) + else: + return self.returnintvar(None) + + def genop_absorb_place(self, v): + return v + SIZE2SHIFT = {1: 0, 2: 1, 4: 2, @@ -1454,7 +1478,7 @@ def read_frame_var(T, base, info, index): assert T is lltype.Signed v = info[index] - value = peek_word_at(base + v.stackpos + 1) + value = peek_word_at(base + v.stackpos) return value @staticmethod @@ -1463,7 +1487,19 @@ v = info[index] if isinstance(v, GenConst): return - return IntConst(peek_word_at(base + v.stackpos + 1)) + return IntConst(peek_word_at(base + v.stackpos)) + + @staticmethod + @specialize.arg(0) + def write_frame_place(T, base, place, value): + assert T is lltype.Signed + poke_word_into(base + place.stackpos, value) + + @staticmethod + @specialize.arg(0) + def read_frame_place(T, base, place): + assert T is lltype.Signed + return peek_word_at(base + place.stackpos) global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 21:07:50 2008 @@ -14,9 +14,7 @@ py.test.skip("unsupported") # frame access related - test_write_frame_place_direct = skipped test_write_lots_of_frame_places_direct = skipped - test_read_frame_place_direct = skipped test_frame_vars_like_the_frontend_direct = skipped test_demo_f1_direct = skipped From fijal at codespeak.net Thu Apr 3 21:33:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 21:33:13 +0200 (CEST) Subject: [pypy-svn] r53290 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403193313.6009F16A726@codespeak.net> Author: fijal Date: Thu Apr 3 21:33:12 2008 New Revision: 53290 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: put * WORD everywhere in stack access, still segfaults. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 21:33:12 2008 @@ -489,7 +489,7 @@ def genop_get_frame_base(self): # XXX really? self.mc.MOV(eax, esp) - self.mc.SUB(eax, imm(self.stackdepth - 1)) + self.mc.SUB(eax, imm((self.stackdepth - 1) * WORD)) return self.returnintvar(eax) def get_frame_info(self, vars_gv): @@ -1478,7 +1478,7 @@ def read_frame_var(T, base, info, index): assert T is lltype.Signed v = info[index] - value = peek_word_at(base + v.stackpos) + value = peek_word_at(base + v.stackpos * WORD) return value @staticmethod @@ -1487,19 +1487,19 @@ v = info[index] if isinstance(v, GenConst): return - return IntConst(peek_word_at(base + v.stackpos)) + return IntConst(peek_word_at(base + v.stackpos * WORD)) @staticmethod @specialize.arg(0) def write_frame_place(T, base, place, value): assert T is lltype.Signed - poke_word_into(base + place.stackpos, value) + poke_word_into(base + place.stackpos * WORD, value) @staticmethod @specialize.arg(0) def read_frame_place(T, base, place): assert T is lltype.Signed - return peek_word_at(base + place.stackpos) + return peek_word_at(base + place.stackpos * WORD) global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst From fijal at codespeak.net Thu Apr 3 21:34:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 21:34:10 +0200 (CEST) Subject: [pypy-svn] r53291 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403193410.0B8D516A730@codespeak.net> Author: fijal Date: Thu Apr 3 21:34:10 2008 New Revision: 53291 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: uh, before I forget Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 21:34:10 2008 @@ -1486,7 +1486,7 @@ # eh, kind here should be "what we're looking for?" v = info[index] if isinstance(v, GenConst): - return + return v return IntConst(peek_word_at(base + v.stackpos * WORD)) @staticmethod From fijal at codespeak.net Thu Apr 3 21:45:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 21:45:49 +0200 (CEST) Subject: [pypy-svn] r53292 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403194549.EEE1F16A796@codespeak.net> Author: fijal Date: Thu Apr 3 21:45:49 2008 New Revision: 53292 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: (arigo) better arithmetics Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 21:45:49 2008 @@ -487,9 +487,8 @@ return self.returnintvar(op) def genop_get_frame_base(self): - # XXX really? self.mc.MOV(eax, esp) - self.mc.SUB(eax, imm((self.stackdepth - 1) * WORD)) + self.mc.ADD(eax, imm((self.stackdepth - 1) * WORD)) return self.returnintvar(eax) def get_frame_info(self, vars_gv): @@ -1076,9 +1075,10 @@ def alloc_frame_place(self, kind, gv_initial_value=None): # XXX kind if gv_initial_value is not None: - return self.returnintvar(gv_initial_value.operand(self)) + res = self.returnintvar(gv_initial_value.operand(self)) else: - return self.returnintvar(None) + res = self.returnintvar(None) + return res def genop_absorb_place(self, v): return v @@ -1478,7 +1478,7 @@ def read_frame_var(T, base, info, index): assert T is lltype.Signed v = info[index] - value = peek_word_at(base + v.stackpos * WORD) + value = peek_word_at(base - v.stackpos * WORD) return value @staticmethod @@ -1487,19 +1487,19 @@ v = info[index] if isinstance(v, GenConst): return v - return IntConst(peek_word_at(base + v.stackpos * WORD)) + return IntConst(peek_word_at(base - v.stackpos * WORD)) @staticmethod @specialize.arg(0) def write_frame_place(T, base, place, value): assert T is lltype.Signed - poke_word_into(base + place.stackpos * WORD, value) + poke_word_into(base - place.stackpos * WORD, value) @staticmethod @specialize.arg(0) def read_frame_place(T, base, place): assert T is lltype.Signed - return peek_word_at(base + place.stackpos * WORD) + return peek_word_at(base - place.stackpos * WORD) global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst From fijal at codespeak.net Thu Apr 3 21:46:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 21:46:36 +0200 (CEST) Subject: [pypy-svn] r53293 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test Message-ID: <20080403194636.CA8C016A7A0@codespeak.net> Author: fijal Date: Thu Apr 3 21:46:36 2008 New Revision: 53293 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: good, all direct tests are passing :) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 21:46:36 2008 @@ -10,14 +10,6 @@ RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked - def skipped(self): - py.test.skip("unsupported") - - # frame access related - test_write_lots_of_frame_places_direct = skipped - test_frame_vars_like_the_frontend_direct = skipped - test_demo_f1_direct = skipped - class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked From fijal at codespeak.net Thu Apr 3 22:03:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 22:03:18 +0200 (CEST) Subject: [pypy-svn] r53294 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080403200318.8EF3116A7DE@codespeak.net> Author: fijal Date: Thu Apr 3 22:03:16 2008 New Revision: 53294 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: don't try to be too smart... Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 22:03:16 2008 @@ -40,6 +40,7 @@ p[0] = value class Var(GenVar): + token = 'x' def __init__(self, stackpos): # 'stackpos' is an index relative to the pushed arguments @@ -79,6 +80,7 @@ class AddressVar(IntVar): ll_type = llmemory.Address token = 'a' + SIZE = 1 class BoolVar(Var): # represents a boolean as an integer which *must* be exactly 0 or 1 @@ -107,11 +109,11 @@ LL_TO_GENVAR = {} TOKEN_TO_GENVAR = {} TOKEN_TO_SIZE = {} -for value in locals().values(): - if hasattr(value, 'll_type'): - LL_TO_GENVAR[value.ll_type] = value.token - TOKEN_TO_GENVAR[value.token] = value - TOKEN_TO_SIZE[value.token] = value.SIZE +for value in [IntVar, FloatVar, BoolVar, AddressVar]: + assert hasattr(value, 'll_type') + LL_TO_GENVAR[value.ll_type] = value.token + TOKEN_TO_GENVAR[value.token] = value + TOKEN_TO_SIZE[value.token] = value.SIZE LL_TO_GENVAR[lltype.Unsigned] = 'i' LL_TO_GENVAR[lltype.Void] = 'v' Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Thu Apr 3 22:03:16 2008 @@ -13,6 +13,3 @@ class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked - - def setup_class(cls): - py.test.skip("skip compilation tests") From fijal at codespeak.net Thu Apr 3 22:22:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 22:22:45 +0200 (CEST) Subject: [pypy-svn] r53295 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403202245.7AADA16A83A@codespeak.net> Author: fijal Date: Thu Apr 3 22:22:44 2008 New Revision: 53295 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: some annotator hacks. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 22:22:44 2008 @@ -41,6 +41,8 @@ class Var(GenVar): token = 'x' + # XXX hack for annotator + stackpos = 0 def __init__(self, stackpos): # 'stackpos' is an index relative to the pushed arguments @@ -61,6 +63,9 @@ def nonimmoperand(self, builder, tmpregister): return self.operand(builder) + def operand(self, builder): + raise NotImplementedError + def __repr__(self): return self.token + 'var@%d' % (self.stackpos,) @@ -188,6 +193,8 @@ class FloatConst(Const): SIZE = 2 + # XXX hack for annotator + rawbuf = lltype.nullptr(rffi.DOUBLEP.TO) def __init__(self, floatval): # XXX we should take more care who is creating this and From fijal at codespeak.net Thu Apr 3 22:30:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 22:30:10 +0200 (CEST) Subject: [pypy-svn] r53296 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403203010.7C58116A850@codespeak.net> Author: fijal Date: Thu Apr 3 22:30:09 2008 New Revision: 53296 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: good, all rgenop tests are passing :) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 22:30:09 2008 @@ -1151,7 +1151,8 @@ res_positions.append(pos) res_positions.append(pos - 1) # no repeats please - assert sorted(dict.fromkeys(res_positions).keys()) == sorted(res_positions) + if not objectmodel.we_are_translated(): + assert sorted(dict.fromkeys(res_positions).keys()) == sorted(res_positions) return res_gv, res_positions def remap_stack_layout(builder, outputargs_gv, target): From fijal at codespeak.net Thu Apr 3 23:10:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 23:10:34 +0200 (CEST) Subject: [pypy-svn] r53297 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403211034.6C4CB16A8CA@codespeak.net> Author: fijal Date: Thu Apr 3 23:10:32 2008 New Revision: 53297 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: enough support for different things to pass first 12 tests of test_genc_portal Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 23:10:32 2008 @@ -120,6 +120,9 @@ TOKEN_TO_GENVAR[value.token] = value TOKEN_TO_SIZE[value.token] = value.SIZE LL_TO_GENVAR[lltype.Unsigned] = 'i' +LL_TO_GENVAR[lltype.Char] = 'i' +# we might want to have different value for chare +# but I see no point now LL_TO_GENVAR[lltype.Void] = 'v' UNROLLING_TOKEN_TO_GENVAR = unrolling_iterable(TOKEN_TO_GENVAR.items()) @@ -1461,10 +1464,18 @@ llmemory.ItemOffset(A.OF)) @staticmethod + @specialize.arg(0) + def map_arg(arg): + if isinstance(arg, lltype.Ptr): + return llmemory.Address + return arg + + @classmethod @specialize.memo() - def sigToken(FUNCTYPE): - return ([LL_TO_GENVAR[arg] for arg in FUNCTYPE.ARGS if arg - is not lltype.Void], LL_TO_GENVAR[FUNCTYPE.RESULT]) + def sigToken(cls, FUNCTYPE): + return ([LL_TO_GENVAR[cls.map_arg(arg)] for arg in FUNCTYPE.ARGS if arg + is not lltype.Void], + LL_TO_GENVAR[cls.map_arg(FUNCTYPE.RESULT)]) @staticmethod def erasedType(T): From fijal at codespeak.net Thu Apr 3 23:10:52 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 23:10:52 +0200 (CEST) Subject: [pypy-svn] r53298 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test Message-ID: <20080403211052.784E416A8CD@codespeak.net> Author: fijal Date: Thu Apr 3 23:10:52 2008 New Revision: 53298 Added: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py (contents, props changed) Log: and a test itself Added: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py ============================================================================== --- (empty file) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py Thu Apr 3 23:10:52 2008 @@ -0,0 +1,100 @@ +import py, os, sys +from pypy.annotation import model as annmodel +from pypy.rlib.unroll import unrolling_iterable +from pypy.translator.c.genc import CStandaloneBuilder +from pypy.jit.rainbow.test import test_portal +from pypy.jit.codegen.ia32.rgenop import RI386GenOp +from pypy.rpython.annlowlevel import PseudoHighLevelCallable + +class I386PortalTestMixin(object): + RGenOp = RI386GenOp + translate_support_code = True + + def timeshift_from_portal(self, main, portal, main_args, + inline=None, policy=None, + backendoptimize=False): + self.testname = sys._getframe(1).f_code.co_name + + # ---------- translate main() and the support code ---------- + self._timeshift_from_portal(main, portal=portal, main_args=main_args, + inline=inline, policy=policy, + backendoptimize=backendoptimize) + + # ---------- run the stand-alone executable ---------- + cmdargs = ' '.join([str(arg) for arg in main_args]) + output = self.cbuilder.cmdexec(cmdargs) + lines = output.split() + lastline = lines[-1] + assert not lastline.startswith('EXCEPTION:') + if hasattr(main, 'convert_result'): + return lastline + else: + return int(lastline) # assume an int + + + # The following function is called by _timeshift_from_portal() unless + # its results are already in the cache from a previous call + def _serialize(self, main, main_args, portal, + policy=None, inline=None, + backendoptimize=False): + + # ---------- prepare a stand-alone main() function ---------- + convert_result = getattr(main, 'convert_result', str) + if hasattr(main, 'convert_arguments'): + decoders = main.convert_arguments + assert len(decoders) == len(main_args) + else: + decoders = [int] * len(main_args) + decoders = unrolling_iterable(decoders) + numargs = len(main_args) + USAGE = '%s: %d arguments expected\n' % (self.testname, numargs) + + def usage(): + os.write(2, USAGE) + return 2 + + def ll_main(argv): + if len(argv) != 1 + numargs: + return usage() + if len(argv) > 1 and argv[1] == '--help': + return usage() + args = () + i = 1 + for decoder in decoders: + args += (decoder(argv[i]),) + i = i + 1 + try: + res = main(*args) + except Exception, e: + os.write(1, 'EXCEPTION: %s\n' % (e,)) + return 0 + os.write(1, convert_result(res) + '\n') + return 0 + + # ---------- rewire portal and translate everything ---------- + super(I386PortalTestMixin, self)._serialize( + ll_main, None, portal=portal, + inline=inline, policy=policy, + backendoptimize=backendoptimize) + + # ---------- generate a stand-alone executable ---------- + t = self.rtyper.annotator.translator + t.config.translation.gc = 'boehm' + self.cbuilder = CStandaloneBuilder(t, ll_main, config=t.config) + self.cbuilder.generate_source() + exename = self.cbuilder.compile() + print '-'*60 + print 'Generated executable for %s: %s' % (self.testname, exename) + print '-'*60 + + + def check_insns(self, expected=None, **counts): + "Cannot check instructions in the generated assembler." + + +class TestPortal(I386PortalTestMixin, + test_portal.TestPortal): + + # for the individual tests see + # ====> ../../../rainbow/test/test_portal.py + pass From fijal at codespeak.net Thu Apr 3 23:32:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 23:32:30 +0200 (CEST) Subject: [pypy-svn] r53300 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403213230.203EF16A794@codespeak.net> Author: fijal Date: Thu Apr 3 23:32:28 2008 New Revision: 53300 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Fix for a crash, another test passes Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Thu Apr 3 23:32:28 2008 @@ -215,7 +215,10 @@ class BoolConst(Const): SIZE = 1 - + + def operand(self, builder): + return imm8(self.value) + def newvar(self, builder): return builder.returnboolvar(self.operand(builder)) @@ -233,6 +236,9 @@ def operand(self, builder): return imm(llmemory.cast_adr_to_int(self.addr)) + def newvar(self, builder): + return builder.returnintvar(self.operand(builder)) + def nonimmoperand(self, builder, tmpregister): builder.mc.MOV(tmpregister, self.operand(builder)) return tmpregister From fijal at codespeak.net Thu Apr 3 23:44:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Apr 2008 23:44:17 +0200 (CEST) Subject: [pypy-svn] r53301 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080403214417.B154B16A942@codespeak.net> Author: fijal Date: Thu Apr 3 23:44:17 2008 New Revision: 53301 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py Log: fix for tests of lltype-based backends Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py Thu Apr 3 23:44:17 2008 @@ -26,6 +26,7 @@ class AbstractOopSpecDesc: __metaclass__ = cachedtype + is_method = False def __init__(self, RGenOp, rtyper, exceptiondesc, fnobj, can_raise): self.rtyper = rtyper From fijal at codespeak.net Fri Apr 4 00:42:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 00:42:47 +0200 (CEST) Subject: [pypy-svn] r53303 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080403224247.75E8C16A967@codespeak.net> Author: fijal Date: Fri Apr 4 00:42:45 2008 New Revision: 53303 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: * Fix the bug that prevented one test to run * Clarify exceptions as a side-effect Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Fri Apr 4 00:42:45 2008 @@ -229,6 +229,7 @@ class AddrConst(GenConst): + SIZE = 1 def __init__(self, addr): self.addr = addr @@ -497,9 +498,10 @@ else: if fieldsize == 1: op = mem8(edx, offset) - else: - assert fieldsize == 2 + elif fieldsize == 2: op = mem(edx, offset) + else: + raise NotImplementedError("fieldsize != 1,2,4") self.mc.MOVZX(eax, op) op = eax return self.returnintvar(op) @@ -520,8 +522,10 @@ else: if fieldsize == 2: self.mc.o16() # followed by the MOV below + elif fieldsize == WORD: + pass else: - assert fieldsize == WORD + raise NotImplementedError("fieldsize != 1,2,4") self.mc.MOV(mem(edx, offset), eax) def genop_getsubstruct(self, (offset, fieldsize), gv_ptr): @@ -552,7 +556,8 @@ op = self.itemaddr(edx, arraytoken, gv_index) _, _, itemsize = arraytoken if itemsize != WORD: - assert itemsize == 1 or itemsize == 2 + if itemsize > 2: + raise NotImplementedError("itemsize != 1,2,4") self.mc.MOVZX(eax, op) op = eax return self.returnintvar(op) @@ -580,7 +585,7 @@ elif itemsize == 2: self.mc.o16() # followed by the MOV below else: - raise AssertionError + raise NotImplementedError("setarrayitme for fieldsize != 1,2,4") self.mc.MOV(destop, eax) def genop_malloc_fixedsize(self, size): @@ -1361,7 +1366,8 @@ self.mcs.append(mc) def check_no_open_mc(self): - assert len(self.mcs) == self.total_code_blocks + if len(self.mcs) != self.total_code_blocks: + raise Exception("Open MC!") def newbuilder(self, stackdepth): return Builder(self, stackdepth) From fijal at codespeak.net Fri Apr 4 02:48:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 02:48:28 +0200 (CEST) Subject: [pypy-svn] r53304 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404004828.6A34716A9F6@codespeak.net> Author: fijal Date: Fri Apr 4 02:48:26 2008 New Revision: 53304 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: support for ForIn Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Fri Apr 4 02:48:26 2008 @@ -390,11 +390,13 @@ visit_regularvarfor = visit_regularfor def visit_infor(self, node): + from pypy.lang.js.operations import Identifier pos = self.get_pos(node) left = self.dispatch(node.children[1]) right = self.dispatch(node.children[2]) body= self.dispatch(node.children[3]) - return operations.ForIn(pos, left, right, body) + assert isinstance(left, Identifier) + return operations.ForIn(pos, left.name, right, body) def visit_invarfor(self, node): pos = self.get_pos(node) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 02:48:26 2008 @@ -2,7 +2,7 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\ W_Array, W_PrimitiveObject, ActivationObject,\ create_object, W_Object, w_Undefined, newbool,\ - w_True, w_False, W_List, w_Null + w_True, w_False, W_List, w_Null, W_Iterator from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException from pypy.rlib.unroll import unrolling_iterable from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ @@ -686,6 +686,34 @@ args = y.get_args() stack.append(commonnew(ctx, x, args)) +# ------------ iterator support ---------------- + +class LOAD_ITERATOR(Opcode): + def eval(self, ctx, stack): + obj = stack.pop().ToObject(ctx) + props = [prop.value for prop in obj.propdict.values() if not prop.de] + stack.append(W_Iterator(props)) + +class JUMP_IF_ITERATOR_EMPTY(BaseJump): + def eval(self, ctx, stack): + pass + + def do_jump(self, stack, pos): + iterator = stack[-1] + assert isinstance(iterator, W_Iterator) + if iterator.empty(): + return self.where + return pos + 1 + +class NEXT_ITERATOR(Opcode): + def __init__(self, name): + self.name = name + + def eval(self, ctx, stack): + iterator = stack[-1] + assert isinstance(iterator, W_Iterator) + ctx.assign(self.name, iterator.next()) + OpcodeMap = {} for name, value in locals().items(): Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri Apr 4 02:48:26 2008 @@ -619,6 +619,17 @@ # def __str__(self): # return "<" + str(self.base) + " -> " + str(self.property_name) + ">" + +class W_Iterator(W_Root): + def __init__(self, elements_w): + self.elements_w = elements_w + + def next(self): + if self.elements_w: + return self.elements_w.pop() + + def empty(self): + return len(self.elements_w) == 0 def create_object(ctx, prototypename, callfunc=None, Value=w_Undefined): proto = ctx.get_global().Get(prototypename).Get('prototype') Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 02:48:26 2008 @@ -865,13 +865,25 @@ class ForIn(Statement): - def __init__(self, pos, iterator, lobject, body): + def __init__(self, pos, name, lobject, body): self.pos = pos #assert isinstance(iterator, Node) - self.iterator = iterator + self.iteratorname = name self.object = lobject self.body = body + def emit(self, bytecode): + self.object.emit(bytecode) + bytecode.emit('LOAD_ITERATOR') + precond = bytecode.emit_startloop_label() + finish = bytecode.prealocate_endloop_label() + bytecode.emit('JUMP_IF_ITERATOR_EMPTY', finish) + bytecode.emit('NEXT_ITERATOR', self.iteratorname) + self.body.emit(bytecode) + bytecode.emit('JUMP', precond) + bytecode.emit_endloop_label(finish) + bytecode.emit('POP') + def execute(self, ctx): obj = self.object.eval(ctx).GetValue().ToObject(ctx) for prop in obj.propdict.values(): From fijal at codespeak.net Fri Apr 4 02:56:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 02:56:50 +0200 (CEST) Subject: [pypy-svn] r53305 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404005650.B5F4116A9F0@codespeak.net> Author: fijal Date: Fri Apr 4 02:56:48 2008 New Revision: 53305 Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: ForVarIn Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 02:56:48 2008 @@ -843,10 +843,25 @@ class ForVarIn(Statement): def __init__(self, pos, vardecl, lobject, body): self.pos = pos - self.vardecl = vardecl + assert isinstance(vardecl, VariableDeclaration) + self.iteratorname = vardecl.identifier self.object = lobject self.body = body + + def emit(self, bytecode): + bytecode.emit('DECLARE_VAR', self.iteratorname) + self.object.emit(bytecode) + bytecode.emit('LOAD_ITERATOR') + precond = bytecode.emit_startloop_label() + finish = bytecode.prealocate_endloop_label() + bytecode.emit('JUMP_IF_ITERATOR_EMPTY', finish) + bytecode.emit('NEXT_ITERATOR', self.iteratorname) + self.body.emit(bytecode) + bytecode.emit('JUMP', precond) + bytecode.emit_endloop_label(finish) + bytecode.emit('POP') + def execute(self, ctx): self.vardecl.eval(ctx) obj = self.object.eval(ctx).GetValue().ToObject(ctx) @@ -884,22 +899,6 @@ bytecode.emit_endloop_label(finish) bytecode.emit('POP') - def execute(self, ctx): - obj = self.object.eval(ctx).GetValue().ToObject(ctx) - for prop in obj.propdict.values(): - if prop.de: - continue - iterator = self.iterator.eval(ctx) - iterator.PutValue(prop.value, ctx) - try: - result = self.body.execute(ctx) - except ExecutionReturned, e: - if e.type == 'break': - break - elif e.type == 'continue': - continue - - class For(Statement): def __init__(self, pos, setup, condition, update, body): self.pos = pos From fijal at codespeak.net Fri Apr 4 03:05:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 03:05:32 +0200 (CEST) Subject: [pypy-svn] r53306 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404010532.9969716AA00@codespeak.net> Author: fijal Date: Fri Apr 4 03:05:32 2008 New Revision: 53306 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: With support. I think we can do better and not have a finally: related slowdown when not using with (not sure how bad this is honestly) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 03:05:32 2008 @@ -14,18 +14,28 @@ def run_bytecode(opcodes, ctx, stack, check_stack=True): i = 0 - while i < len(opcodes): - for name, op in opcode_unrolling: - opcode = opcodes[i] - opcode = hint(opcode, deepfreeze=True) - if isinstance(opcode, op): - result = opcode.eval(ctx, stack) - assert result is None - break - if isinstance(opcode, BaseJump): - i = opcode.do_jump(stack, i) - else: - i += 1 + to_pop = 0 + try: + while i < len(opcodes): + for name, op in opcode_unrolling: + opcode = opcodes[i] + opcode = hint(opcode, deepfreeze=True) + if isinstance(opcode, op): + result = opcode.eval(ctx, stack) + assert result is None + break + if isinstance(opcode, BaseJump): + i = opcode.do_jump(stack, i) + else: + i += 1 + if isinstance(opcode, WITH_START): + to_pop += 1 + elif isinstance(opcode, WITH_END): + to_pop -= 1 + finally: + for i in range(to_pop): + ctx.pop_object() + if check_stack: assert not stack @@ -714,6 +724,19 @@ assert isinstance(iterator, W_Iterator) ctx.assign(self.name, iterator.next()) +# ---------------- with support --------------------- + +class WITH_START(Opcode): + def __init__(self, name): + self.name = name + + def eval(self, ctx, stack): + ctx.push_object(ctx.resolve_identifier(self.name).ToObject(ctx)) + +class WITH_END(Opcode): + def eval(self, ctx, stack): + ctx.pop_object() + OpcodeMap = {} for name, value in locals().items(): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 03:05:32 2008 @@ -788,9 +788,15 @@ class With(Statement): def __init__(self, pos, identifier, body): self.pos = pos - self.identifier = identifier + assert isinstance(identifier, VariableIdentifier) + self.identifier = identifier.identifier self.body = body + def emit(self, bytecode): + bytecode.emit('WITH_START', self.identifier) + self.body.emit(bytecode) + bytecode.emit('WITH_END') + def execute(self, ctx): obj = self.identifier.eval(ctx).GetValue().ToObject(ctx) ctx.push_object(obj) @@ -860,24 +866,7 @@ self.body.emit(bytecode) bytecode.emit('JUMP', precond) bytecode.emit_endloop_label(finish) - bytecode.emit('POP') - - def execute(self, ctx): - self.vardecl.eval(ctx) - obj = self.object.eval(ctx).GetValue().ToObject(ctx) - for prop in obj.propdict.values(): - if prop.de: - continue - iterator = self.vardecl.eval(ctx) - iterator.PutValue(prop.value, ctx) - try: - result = self.body.execute(ctx) - except ExecutionReturned, e: - if e.type == 'break': - break - elif e.type == 'continue': - continue - + bytecode.emit('POP') class ForIn(Statement): def __init__(self, pos, name, lobject, body): From fijal at codespeak.net Fri Apr 4 03:06:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 03:06:29 +0200 (CEST) Subject: [pypy-svn] r53307 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404010629.5836E16AA00@codespeak.net> Author: fijal Date: Fri Apr 4 03:06:28 2008 New Revision: 53307 Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: remove unnecessary methods Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 03:06:28 2008 @@ -62,8 +62,7 @@ bytecode.emit('POP') class Expression(Statement): - def execute(self, ctx): - return self.eval(ctx) + pass class ListOp(Expression): def __init__(self, pos, nodes): @@ -253,18 +252,6 @@ for node in self.nodes: node.emit(bytecode) - def execute(self, ctx): - try: - last = w_Undefined - for node in self.nodes: - last = node.execute(ctx) - return last - except ExecutionReturned, e: - if e.type == 'return': - return e.value - else: - raise e - BitwiseAnd = create_binary_op('BITAND') #class BitwiseNot(UnaryOp): @@ -644,28 +631,7 @@ funccode.emit(bytecode) for node in self.nodes: - node.emit(bytecode) - - def execute(self, ctx): - for varname in self.var_decl: - ctx.variable.Put(varname, w_Undefined, dd=True) - for funcname, funccode in self.func_decl.items(): - ctx.variable.Put(funcname, funccode.eval(ctx)) - node = self - - try: - last = w_Undefined - for node in self.nodes: - last = node.execute(ctx) - return last - except Exception, e: - if isinstance(e, ExecutionReturned) and e.type == 'return': - return e.value - else: - # TODO: proper exception handling - print "%s:%d: %s"%(self.sourcename, node.pos.lineno, node) - raise - + node.emit(bytecode) class Program(Statement): def __init__(self, pos, body): @@ -771,9 +737,6 @@ def emit(self, bytecode): self.body.emit(bytecode) - - def execute(self, ctx): - return self.body.eval(ctx) class Void(Expression): def __init__(self, pos, expr): @@ -797,17 +760,6 @@ self.body.emit(bytecode) bytecode.emit('WITH_END') - def execute(self, ctx): - obj = self.identifier.eval(ctx).GetValue().ToObject(ctx) - ctx.push_object(obj) - - try: - retval = self.body.execute(ctx) - finally: - ctx.pop_object() - return retval - - class WhileBase(Statement): def __init__(self, pos, condition, body): self.pos = pos @@ -833,18 +785,7 @@ bytecode.emit('JUMP_IF_FALSE', endlabel) self.body.emit(bytecode) bytecode.emit('JUMP', startlabel) - bytecode.emit_endloop_label(endlabel) - - def execute(self, ctx): - while self.condition.eval(ctx).ToBoolean(): - try: - self.body.execute(ctx) - except ExecutionReturned, e: - if e.type == 'break': - break - elif e.type == 'continue': - continue - + bytecode.emit_endloop_label(endlabel) class ForVarIn(Statement): def __init__(self, pos, vardecl, lobject, body): From fijal at codespeak.net Fri Apr 4 04:15:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 04:15:12 +0200 (CEST) Subject: [pypy-svn] r53308 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404021512.3C97116AA1F@codespeak.net> Author: fijal Date: Fri Apr 4 04:15:10 2008 New Revision: 53308 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: * basic support for methods * pass few trivial tests Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Fri Apr 4 04:15:10 2008 @@ -14,8 +14,8 @@ '*': operations.Mult, '/': operations.Division, '%': operations.Mod, - #'^': operations.BitwiseXor, - #'|': operations.BitwiseOr, + '^': operations.BitwiseXor, + '|': operations.BitwiseOr, '&': operations.BitwiseAnd, '&&': operations.And, '||': operations.Or, @@ -27,9 +27,9 @@ '>=': operations.Ge, '<': operations.Lt, '<=': operations.Le, - #'>>': operations.Rsh, - #'>>>': operations.Ursh, - #'<<': operations.Lsh, + '>>': operations.Rsh, + '>>>': operations.Ursh, + '<<': operations.Lsh, '.': operations.MemberDot, '[': operations.Member, ',': operations.Comma, Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri Apr 4 04:15:10 2008 @@ -250,10 +250,10 @@ def Call(self, ctx, args=[], this=None): tam = len(args) if tam >= 1: - fbody = args[tam-1].GetValue().ToString(ctx) + fbody = args[tam-1].ToString(ctx) argslist = [] for i in range(tam-1): - argslist.append(args[i].GetValue().ToString(ctx)) + argslist.append(args[i].ToString(ctx)) fargs = ','.join(argslist) functioncode = "function (%s) {%s}"%(fargs, fbody) else: Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 04:15:10 2008 @@ -8,6 +8,7 @@ from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ compare_e, increment, commonnew, mult, division, uminus, mod from pypy.rlib.jit import hint +from pypy.rlib.rarithmetic import intmask class AlreadyRun(Exception): pass @@ -399,6 +400,34 @@ def operation(ctx, op1, op2): return W_IntNumber(op1&op2) +class BITXOR(BaseBinaryBitwiseOp): + @staticmethod + def operation(ctx, op1, op2): + return W_IntNumber(op1^op2) + +class BITOR(BaseBinaryBitwiseOp): + @staticmethod + def operation(ctx, op1, op2): + return W_IntNumber(op1|op2) + +class URSH(BaseBinaryBitwiseOp): + def eval(self, ctx, stack): + op2 = stack.pop().ToUInt32() + op1 = stack.pop().ToUInt32() + stack.append(W_IntNumber(op1 >> (op2 & 0x1F))) + +class RSH(BaseBinaryBitwiseOp): + def eval(self, ctx, stack): + op2 = stack.pop().ToUInt32() + op1 = stack.pop().ToInt32() + stack.append(W_IntNumber(op1 >> intmask(op2 & 0x1F))) + +class LSH(BaseBinaryBitwiseOp): + def eval(self, ctx, stack): + op2 = stack.pop().ToUInt32() + op1 = stack.pop().ToInt32() + stack.append(W_IntNumber(op1 << intmask(op2 & 0x1F))) + class MUL(BaseBinaryOperation): @staticmethod def operation(ctx, op1, op2): @@ -517,12 +546,38 @@ stack.append(result) return result +class BaseAssignBitOper(BaseStore): + def process(self, ctx, name, stack): + right = stack.pop().ToInt32() + left = ctx.resolve_identifier(name).ToInt32() + result = self.operation(ctx, left, right) + stack.append(result) + return result + class STORE_ADD(BaseAssignOper): operation = staticmethod(ADD.operation) class STORE_SUB(BaseAssignOper): operation = staticmethod(SUB.operation) +class STORE_MUL(BaseAssignOper): + operation = staticmethod(MUL.operation) + +class STORE_DIV(BaseAssignOper): + operation = staticmethod(DIV.operation) + +class STORE_MOD(BaseAssignOper): + operation = staticmethod(MOD.operation) + +class STORE_BITAND(BaseAssignBitOper): + operation = staticmethod(BITAND.operation) + +class STORE_BITOR(BaseAssignBitOper): + operation = staticmethod(BITOR.operation) + +class STORE_BITXOR(BaseAssignBitOper): + operation = staticmethod(BITXOR.operation) + class STORE_POSTINCR(BaseStore): def process(self, ctx, name, stack): value = ctx.resolve_identifier(name) @@ -645,6 +700,21 @@ raise ThrowException(W_String('it is not a function')) stack.append(res) +class CALL_METHOD(Opcode): + def eval(self, ctx, stack): + method = stack.pop() + what = stack.pop().ToObject(ctx) + args = stack.pop() + r1 = what.Get(method.ToString()) + if not isinstance(r1, W_PrimitiveObject): + raise ThrowException(W_String("it is not a callable")) + try: + res = r1.Call(ctx=ctx, args=args.tolist(), this=what) + except JsTypeError: + raise ThrowException(W_String('it is not a function')) + stack.append(res) + + class DUP(Opcode): def eval(self, ctx, stack): stack.append(stack[-1]) Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 04:15:10 2008 @@ -134,6 +134,10 @@ '/=' : 'DIV', '++' : 'INCR', '--' : 'DECR', + '%=' : 'MOD', + '&=' : 'BITAND', + '|=' : 'BITOR', + '^=' : 'BITXOR', } class SimpleIncrement(Expression): @@ -252,24 +256,14 @@ for node in self.nodes: node.emit(bytecode) -BitwiseAnd = create_binary_op('BITAND') +BitwiseAnd = create_binary_op('BITAND') +BitwiseXor = create_binary_op('BITXOR') +BitwiseOr = create_binary_op('BITOR') #class BitwiseNot(UnaryOp): # def eval(self, ctx): # op1 = self.expr.eval(ctx).GetValue().ToInt32() # return W_IntNumber(~op1) - - -# class BitwiseOr(BinaryOp): -# def decision(self, ctx, op1, op2): -# return W_IntNumber(op1|op2) - - - -# class BitwiseXor(BinaryOp): -# def decision(self, ctx, op1, op2): -# return W_IntNumber(op1^op2) - class Unconditional(Statement): def __init__(self, pos, target): @@ -294,8 +288,17 @@ def emit(self, bytecode): self.args.emit(bytecode) - self.left.emit(bytecode) - bytecode.emit('CALL') + left = self.left + if isinstance(left, MemberDot): + left.left.emit(bytecode) + # XXX optimise + bytecode.emit('LOAD_STRINGCONSTANT', left.name) + bytecode.emit('CALL_METHOD') + elif isinstance(left, Member): + raise NotImplementedError + else: + left.emit(bytecode) + bytecode.emit('CALL') Comma = create_binary_op('COMMA') @@ -443,23 +446,9 @@ # ############################################################################## -# class Ursh(BinaryOp): -# def decision(self, ctx, op1, op2): -# a = op1.ToUInt32() -# b = op2.ToUInt32() -# return W_IntNumber(a >> (b & 0x1F)) - -# class Rsh(BinaryOp): -# def decision(self, ctx, op1, op2): -# a = op1.ToInt32() -# b = op2.ToUInt32() -# return W_IntNumber(a >> intmask(b & 0x1F)) - -# class Lsh(BinaryOp): -# def decision(self, ctx, op1, op2): -# a = op1.ToInt32() -# b = op2.ToUInt32() -# return W_IntNumber(a << intmask(b & 0x1F)) +Ursh = create_binary_op('URSH') +Rsh = create_binary_op('RSH') +Lsh = create_binary_op('LSH') ############################################################################## # @@ -720,7 +709,7 @@ def get_literal(self): return self.identifier -class VariableDeclList(Expression): +class VariableDeclList(Statement): def __init__(self, pos, nodes): self.pos = pos self.nodes = nodes @@ -839,7 +828,8 @@ def emit(self, bytecode): self.setup.emit(bytecode) - bytecode.emit('POP') + if isinstance(self.setup, Expression): + bytecode.emit('POP') precond = bytecode.emit_startloop_label() finish = bytecode.prealocate_endloop_label() self.condition.emit(bytecode) From fijal at codespeak.net Fri Apr 4 04:24:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 04:24:37 +0200 (CEST) Subject: [pypy-svn] r53309 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404022437.0DDE316AA19@codespeak.net> Author: fijal Date: Fri Apr 4 04:24:35 2008 New Revision: 53309 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: another passing test Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Fri Apr 4 04:24:35 2008 @@ -345,7 +345,6 @@ if len(node.children) == 1: return self.dispatch(node.children[0]) else: - raise NotImplementedError pos = self.get_pos(node) val = self.dispatch(node.children[1]) return operations.New(pos, val) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 04:24:35 2008 @@ -766,6 +766,11 @@ args = y.get_args() stack.append(commonnew(ctx, x, args)) +class NEW_NO_ARGS(Opcode): + def eval(self, ctx, stack): + x = stack.pop() + stack.append(commonnew(ctx, x, [])) + # ------------ iterator support ---------------- class LOAD_ITERATOR(Opcode): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 04:24:35 2008 @@ -526,10 +526,14 @@ # ############################################################################## -#class New(UnaryOp): -# def eval(self, ctx): -# x = self.expr.eval(ctx).GetValue() -# return commonnew(ctx, x, []) +class New(Expression): + def __init__(self, pos, left): + self.pos = pos + self.left = left + + def emit(self, bytecode): + self.left.emit(bytecode) + bytecode.emit('NEW_NO_ARGS') class NewWithArgs(Expression): def __init__(self, pos, left, right): From santagada at codespeak.net Fri Apr 4 05:18:19 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Fri, 4 Apr 2008 05:18:19 +0200 (CEST) Subject: [pypy-svn] r53310 - pypy/branch/js-refactoring/pypy/lang/js/bench Message-ID: <20080404031819.ABC0016A9E3@codespeak.net> Author: santagada Date: Fri Apr 4 05:18:16 2008 New Revision: 53310 Added: pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/ackermann.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/ary.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/binarytrees.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/fannkuch.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/fasta.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/fibo.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/harmonic.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/hash.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/hash2.javascript (contents, props changed) pypy/branch/js-refactoring/pypy/lang/js/bench/heapsort.javascript (contents, props changed) Removed: pypy/branch/js-refactoring/pypy/lang/js/bench/f1.js pypy/branch/js-refactoring/pypy/lang/js/bench/f2.js Modified: pypy/branch/js-refactoring/pypy/lang/js/bench/ (props changed) Log: first import of the benchmarks, there are still more to come Added: pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt Fri Apr 4 05:18:16 2008 @@ -0,0 +1,32 @@ +All benchmarks are from The Computer Language Benchmarks Game, licensed under the revised BSD License + +Parameters for the benchmarks: + +ackermann 9,10,11 +ary 3000,5000,7000,9000 +binarytrees 12,14,16 +fannkuch 9,10,11 +fasta (substring) 250000,2500000,25000000 +fibo 12,24,32 +harmonic 6000000,8000000,10000000 +hash 40000,60000,80000,100000 +hash2 50,100,150,200 +heapsort 20000,40000,60000,80000,100000 +hello ? +knucleotide (without one simple regex) +lists (concat) @0 +matrix @0 +methcall @0 +nbody +nestedloop @0 +nsieve +nsievebits +objinst @0 +partialsums (sin, cos, pow) +random @0 +recursive +sieve @0 +spectralnorm (sqrt) +strcat @0 +sumcol (readline!) +takfp @0 Added: pypy/branch/js-refactoring/pypy/lang/js/bench/ackermann.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/ackermann.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,15 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by Sjoerd Visscher + +function ack(m, n) { + return (m == 0 + ? n + 1 + : (n == 0 + ? ack(m - 1, 1) + : ack(m - 1, ack(m, n - 1)))); +} + +var n = arguments[0]; +print("ack(3, " + n + "): " + ack(3, n)); Added: pypy/branch/js-refactoring/pypy/lang/js/bench/ary.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/ary.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,23 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by David Hedbor +// modified by Isaac Gouy + +var i, k; + +var n = arguments[0]; +var x = Array(n); +var y = Array(n); + +for (i = 0; i < n; i++) { + x[i] = i + 1; + y[i] = 0; // Need to set all entries in i to zero or the result will be NaN +} +for (k = 0 ; k < 1000; k++) { + for (i = n-1; i >= 0; i--) { + y[i] += x[i]; + } +} +print(y[0], y[n-1]); + Added: pypy/branch/js-refactoring/pypy/lang/js/bench/binarytrees.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/binarytrees.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,51 @@ +/* The Great Computer Language Shootout + http://shootout.alioth.debian.org/ + contributed by Isaac Gouy */ + +function TreeNode(left,right,item){ + this.left = left; + this.right = right; + this.item = item; +} + +TreeNode.prototype.itemCheck = function(){ + if (this.left==null) return this.item; + else return this.item + this.left.itemCheck() - this.right.itemCheck(); +} + +function bottomUpTree(item,depth){ + if (depth>0){ + return new TreeNode( + bottomUpTree(2*item-1, depth-1) + ,bottomUpTree(2*item, depth-1) + ,item + ); + } + else { + return new TreeNode(null,null,item); + } +} + + +var minDepth = 4; +var n = arguments[0]; +var maxDepth = Math.max(minDepth + 2, n); +var stretchDepth = maxDepth + 1; + +var check = bottomUpTree(0,stretchDepth).itemCheck(); +print("stretch tree of depth " + stretchDepth + "\t check: " + check); + +var longLivedTree = bottomUpTree(0,maxDepth); +for (var depth=minDepth; depth<=maxDepth; depth+=2){ + var iterations = 1 << (maxDepth - depth + minDepth); + + check = 0; + for (var i=1; i<=iterations; i++){ + check += bottomUpTree(i,depth).itemCheck(); + check += bottomUpTree(-i,depth).itemCheck(); + } + print(iterations*2 + "\t trees of depth " + depth + "\t check: " + check); +} + +print("long lived tree of depth " + maxDepth + "\t check: " + + longLivedTree.itemCheck()); Added: pypy/branch/js-refactoring/pypy/lang/js/bench/fannkuch.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/fannkuch.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,66 @@ +/* The Great Computer Language Shootout + http://shootout.alioth.debian.org/ + contributed by Isaac Gouy */ + +function fannkuch(n) { + var check = 0; + var perm = Array(n); + var perm1 = Array(n); + var count = Array(n); + var maxPerm = Array(n); + var maxFlipsCount = 0; + var m = n - 1; + + for (var i = 0; i < n; i++) perm1[i] = i; + var r = n; + + while (true) { + // write-out the first 30 permutations + if (check < 30){ + var s = ""; + for(var i=0; i> 1; + for (var i = 0; i < k2; i++) { + var temp = perm[i]; perm[i] = perm[k - i]; perm[k - i] = temp; + } + flipsCount++; + } + + if (flipsCount > maxFlipsCount) { + maxFlipsCount = flipsCount; + for (var i = 0; i < n; i++) maxPerm[i] = perm1[i]; + } + } + + while (true) { + if (r == n) return maxFlipsCount; + var perm0 = perm1[0]; + var i = 0; + while (i < r) { + var j = i + 1; + perm1[i] = perm1[j]; + i = j; + } + perm1[r] = perm0; + + count[r] = count[r] - 1; + if (count[r] > 0) break; + r++; + } + } +} + +var n = arguments[0]; +print("Pfannkuchen(" + n + ") = " + fannkuch(n)); Added: pypy/branch/js-refactoring/pypy/lang/js/bench/fasta.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/fasta.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,88 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org +// +// Contributed by Ian Osgood + +var last = 42, A = 3877, C = 29573, M = 139968; + +function rand(max) { + last = (last * A + C) % M; + return max * last / M; +} + +var ALU = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +var IUB = { + a:0.27, c:0.12, g:0.12, t:0.27, + B:0.02, D:0.02, H:0.02, K:0.02, + M:0.02, N:0.02, R:0.02, S:0.02, + V:0.02, W:0.02, Y:0.02 +} + +var HomoSap = { + a: 0.3029549426680, + c: 0.1979883004921, + g: 0.1975473066391, + t: 0.3015094502008 +} + +function makeCumulative(table) { + var last = null; + for (var c in table) { + if (last) table[c] += table[last]; + last = c; + } +} + +function fastaRepeat(n, seq) { + var seqi = 0, lenOut = 60; + while (n>0) { + if (n0) { + if (nONE Homo sapiens alu") +fastaRepeat(2*n, ALU) + +print(">TWO IUB ambiguity codes") +fastaRandom(3*n, IUB) + +print(">THREE Homo sapiens frequency") +fastaRandom(5*n, HomoSap) Added: pypy/branch/js-refactoring/pypy/lang/js/bench/fibo.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/fibo.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,14 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by David Hedbor +// modified by Isaac Gouy + +function fib(n) { + if (n < 2) return 1; + return fib(n-2) + fib(n-1); +} + +var n = arguments[0]; +print(fib(n)); + Added: pypy/branch/js-refactoring/pypy/lang/js/bench/harmonic.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/harmonic.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,9 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by Isaac Gouy + +var n = arguments[0], partialSum = 0.0; +for (var d = 1; d <= n; d++) partialSum += 1.0/d; +print(partialSum.toFixed(9)); + Added: pypy/branch/js-refactoring/pypy/lang/js/bench/hash.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/hash.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,18 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by David Hedbor +// modified by Isaac Gouy + +var i, c = 0; +var n = arguments[0]; + +var X = new Object(); +for (i=1; i<=n; i++) { + X[i.toString(16)] = i; +} +for (i=n; i>0; i--) { + if (X[i.toString()]) c++; +} +print(c); + Added: pypy/branch/js-refactoring/pypy/lang/js/bench/hash2.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/hash2.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,28 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by David Hedbor +// modified by Isaac Gouy + +var n = arguments[0]; +var hash1 = Object(); +var hash2 = Object(); +var arr = Array(10000); +var idx; + +for (i=0; i<10000; i++) { + idx = "foo_"+i; + hash1[idx] = i; + // Do this here and run loop below one less since += on an undefined + // entry == NaN. + hash2[idx] = hash1[idx]; +} + +for (i = 1; i < n; i++) { + for(a in hash1) { + hash2[a] += hash1[a]; + } +} + +print(hash1["foo_1"], hash1["foo_9999"], + hash2["foo_1"], hash2["foo_9999"]); Added: pypy/branch/js-refactoring/pypy/lang/js/bench/heapsort.javascript ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/heapsort.javascript Fri Apr 4 05:18:16 2008 @@ -0,0 +1,57 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by David Hedbor +// modified by Isaac Gouy + +var IM = 139968; +var IA = 3877; +var IC = 29573; + +var last = 42; + +function gen_random(max) { return(max * (last = (last * IA + IC) % IM) / IM); } + +function heapsort(n, ra) { + var l, j, ir, i; + var rra; + + l = (n >> 1) + 1; + ir = n; + for (;;) { + if (l > 1) { + rra = ra[--l]; + } else { + rra = ra[ir]; + ra[ir] = ra[1]; + if (--ir == 1) { + ra[1] = rra; + return; + } + } + i = l; + j = l << 1; + while (j <= ir) { + if (j < ir && ra[j] < ra[j+1]) { ++j; } + if (rra < ra[j]) { + ra[i] = ra[j]; + j += (i = j); + } else { + j = ir + 1; + } + } + ra[i] = rra; + } +} + + +var n = arguments[0]; +var ary, i; + +// create an array of N random floats +ary = Array(n+1); +for (i=1; i<=n; i++) { + ary[i] = gen_random(1.0); +} +heapsort(n, ary); +print(ary[n].toFixed(10)); From fijal at codespeak.net Fri Apr 4 05:35:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 05:35:24 +0200 (CEST) Subject: [pypy-svn] r53311 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080404033524.EA02716AA1A@codespeak.net> Author: fijal Date: Fri Apr 4 05:35:24 2008 New Revision: 53311 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: Good, test_interp passes :) this means that we don't have enough tests, but well... Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 05:35:24 2008 @@ -812,6 +812,29 @@ def eval(self, ctx, stack): ctx.pop_object() +# ------------------ delete ------------------------- + +class DELETE(Opcode): + def __init__(self, name): + self.name = name + + def eval(self, ctx, stack): + stack.append(newbool(ctx.delete_identifier(self.name))) + +class DELETE_MEMBER(Opcode): + def eval(self, ctx, stack): + what = stack.pop().ToString() + obj = stack.pop().ToObject(ctx) + try: + P = obj.propdict[what] + if P.ro: + stack.append(newbool(False)) + return + del obj.propdict[what] + stack.append(newbool(True)) + except KeyError: + stack.append(newbool(False)) + OpcodeMap = {} for name, value in locals().items(): Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri Apr 4 05:35:24 2008 @@ -531,6 +531,19 @@ # if not, we need to put this thing in current scope self.variable.Put(name, value) + def delete_identifier(self, name): + for obj in self.scope: + assert isinstance(obj, W_PrimitiveObject) + try: + P = obj.propdict[name] + if P.ro: + return False + del obj.propdict[name] + return True + except KeyError: + pass + return False + def put(self, name, value): assert name is not None self.variable.Put(name, value) Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 05:35:24 2008 @@ -489,6 +489,23 @@ self.pos = pos self.what = what + def emit(self, bytecode): + what = self.what + if isinstance(what, Identifier): + bytecode.emit('DELETE', what.name) + elif isinstance(what, MemberDot): + what.left.emit(bytecode) + # XXX optimize + bytecode.emit('LOAD_STRINGCONSTANT', what.name) + bytecode.emit('DELETE_MEMBER') + elif isinstance(what, Member): + what.left.emit(bytecode) + what.right.emit(bytecode) + bytecode.emit('DELETE_MEMBER') + else: + what.left.emit(bytecode) + bytecode.emit('LOAD_BOOLCONSTANT', True) + #def emit(self, bytecode): # Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri Apr 4 05:35:24 2008 @@ -466,7 +466,11 @@ assertp("print(+1);", '1') def test_delete(): - py.test.skip("Unsupported") + assertp(""" + x = 0; + delete x; + print(this.x) + """, 'undefined') assertp(""" var x = {}; x.y = 1; From fijal at codespeak.net Fri Apr 4 05:40:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 05:40:22 +0200 (CEST) Subject: [pypy-svn] r53312 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080404034022.B210E16AA0E@codespeak.net> Author: fijal Date: Fri Apr 4 05:40:22 2008 New Revision: 53312 Removed: pypy/branch/js-refactoring/pypy/lang/js/test/test_operations.py Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/test_astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py Log: fix tests, remove irrelevant one Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 05:40:22 2008 @@ -781,7 +781,7 @@ def emit(self, bytecode): startlabel = bytecode.emit_startloop_label() - end = bytecode.preallocate_endloop_label() + end = bytecode.prealocate_endloop_label() self.body.emit(bytecode) self.condition.emit(bytecode) bytecode.emit('JUMP_IF_TRUE', startlabel) Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_astbuilder.py Fri Apr 4 05:40:22 2008 @@ -31,8 +31,8 @@ def test_callcall(): p = to_ast('x()()') c1 = p.body.nodes[0] - assert isinstance(c1, Call) - assert isinstance(c1.left, Call) + assert isinstance(c1.expr, Call) + assert isinstance(c1.expr.left, Call) def test_sourcename(): p = to_ast('x()()').body Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py Fri Apr 4 05:40:22 2008 @@ -438,7 +438,8 @@ 'LOAD_VARIABLE "stuff"', 'POP', 'LOAD_VARIABLE "x"', - 'JUMP_IF_TRUE 0'],[ + 'JUMP_IF_TRUE 0', + 'LABEL 1'],[ 'LOAD_VARIABLE "stuff"', 'POP', 'LOAD_VARIABLE "x"', From fijal at codespeak.net Fri Apr 4 05:43:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 05:43:39 +0200 (CEST) Subject: [pypy-svn] r53313 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404034339.23C7C16AA14@codespeak.net> Author: fijal Date: Fri Apr 4 05:43:38 2008 New Revision: 53313 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: fix delete Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 05:43:38 2008 @@ -675,7 +675,7 @@ self.name = name def eval(self, ctx, stack): - ctx.put(self.name, w_Undefined) + ctx.put(self.name, w_Undefined, dd=True) def __repr__(self): return 'DECLARE_VAR "%s"' % (self.name,) @@ -825,15 +825,7 @@ def eval(self, ctx, stack): what = stack.pop().ToString() obj = stack.pop().ToObject(ctx) - try: - P = obj.propdict[what] - if P.ro: - stack.append(newbool(False)) - return - del obj.propdict[what] - stack.append(newbool(True)) - except KeyError: - stack.append(newbool(False)) + stack.append(newbool(obj.Delete(what))) OpcodeMap = {} Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri Apr 4 05:43:38 2008 @@ -536,7 +536,7 @@ assert isinstance(obj, W_PrimitiveObject) try: P = obj.propdict[name] - if P.ro: + if P.dd: return False del obj.propdict[name] return True @@ -544,9 +544,9 @@ pass return False - def put(self, name, value): + def put(self, name, value, dd=False): assert name is not None - self.variable.Put(name, value) + self.variable.Put(name, value, dd=dd) def get_global(self): return self.scope[-1] From fijal at codespeak.net Fri Apr 4 05:51:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 05:51:00 +0200 (CEST) Subject: [pypy-svn] r53314 - in pypy/branch/js-refactoring/pypy/lang/js: . test test/ecma Message-ID: <20080404035100.8C9E216AA28@codespeak.net> Author: fijal Date: Fri Apr 4 05:51:00 2008 New Revision: 53314 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: a test and a fix for x.x += stuff Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 05:51:00 2008 @@ -503,13 +503,22 @@ left = stack.pop() elem = stack.pop() value = stack.pop() - self.operation() - left.Put(elem.ToString(), value) + name = elem.ToString() + value = self.operation(ctx, left, name, value) + left.Put(name, value) stack.append(left) class STORE_MEMBER(BaseStoreMember): - def operation(self): - pass + def operation(self, ctx, left, elem, value): + return value + +class BaseStoreMemberAssign(BaseStoreMember): + def operation(self, ctx, left, name, value): + prev = left.Get(name) + return self.decision(ctx, value, prev) + +class STORE_MEMBER_ADD(BaseStoreMemberAssign): + decision = staticmethod(ADD.operation) class STORE_MEMBER_POSTINCR(BaseStoreMember): def operation(self): Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Fri Apr 4 05:51:00 2008 @@ -36,10 +36,9 @@ cls.tc.PutValue(W_IntNumber(0), cls.interp.global_context) cls.interp = Interpreter() - ctx = cls.interp.global_context shellpath = rootdir/'shell.js' t = load_file(str(shellpath)) - t.execute(ctx) + cls.interp.run(t) cls.testcases = cls.interp.global_context.resolve_identifier('testcases') cls.tc = cls.interp.global_context.resolve_identifier('tc') init_interp = classmethod(init_interp) Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri Apr 4 05:51:00 2008 @@ -268,6 +268,7 @@ def test_assignments(): yield assertv, "var x = 3; x += 4; x;", 7 yield assertv, "x = 8; x -= 3; x;", 5 + yield assertv, "x = {}; x.x = 3; x.x += 8; x.x", 8+3 def test_object_creation(): yield assertv, """ From fijal at codespeak.net Fri Apr 4 06:01:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 06:01:01 +0200 (CEST) Subject: [pypy-svn] r53315 - in pypy/branch/js-refactoring/pypy/lang/js: . test test/ecma Message-ID: <20080404040101.21F0316AA2F@codespeak.net> Author: fijal Date: Fri Apr 4 06:00:59 2008 New Revision: 53315 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: * fix ecma conftest * obscure hack for typeof Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 06:00:59 2008 @@ -382,6 +382,17 @@ one = stack.pop() stack.append(W_String(one.type())) +class TYPEOF_VARIABLE(Opcode): + def __init__(self, name): + self.name = name + + def eval(self, ctx, stack): + try: + var = ctx.resolve_identifier(self.name) + stack.append(var.type()) + except ThrowException: + stack.append(w_Undefined) + #class Typeof(UnaryOp): # def eval(self, ctx): # val = self.expr.eval(ctx) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri Apr 4 06:00:59 2008 @@ -375,8 +375,8 @@ def __init__(self, strval): self.strval = strval - def __str__(self): - return self.strval+"W" + def __repr__(self): + return 'W_String(%s)' % (self.strval,) def ToObject(self, ctx): return create_object(ctx, 'String', Value=self) Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 06:00:59 2008 @@ -470,19 +470,19 @@ StrictNe = create_binary_op('ISNOT') In = create_binary_op('IN') -Typeof = create_unary_op('TYPEOF') -# class Delete(UnaryOp): -# """ -# the delete op, erases properties from objects -# """ -# def eval(self, ctx): -# r1 = self.expr.eval(ctx) -# if not isinstance(r1, W_Reference): -# return W_Boolean(True) -# r3 = r1.GetBase() -# r4 = r1.GetPropertyName() -# return W_Boolean(r3.Delete(r4)) +class Typeof(Expression): + def __init__(self, pos, left): + self.pos = pos + self.left = left + + def emit(self, bytecode): + # obscure hack to be compatible + if isinstance(self.left, Identifier): + bytecode.emit('TYPEOF_VARIABLE', self.left.name) + else: + self.left.emit(bytecode) + bytecode.emit('TYPEOF') class Delete(Expression): def __init__(self, pos, what): Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Fri Apr 4 06:00:59 2008 @@ -57,7 +57,7 @@ #actually run the file :) t = load_file(str(self.fspath)) try: - t.execute(self.interp.global_context) + self.interp.run(t) except ParseError, e: raise Failed(msg=e.nice_error_message(filename=str(self.fspath)), excinfo=None) except JsBaseExcept: Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri Apr 4 06:00:59 2008 @@ -350,6 +350,9 @@ var x = 3; typeof x == 'number'; """, True) + assertv(""" + typeof x + """, 'undefined') def test_semicolon(): assertp(';', []) From fijal at codespeak.net Fri Apr 4 06:17:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 06:17:33 +0200 (CEST) Subject: [pypy-svn] r53316 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080404041733.167A416AA37@codespeak.net> Author: fijal Date: Fri Apr 4 06:17:30 2008 New Revision: 53316 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: Oops. Fix interactive interpreter Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri Apr 4 06:17:30 2008 @@ -114,12 +114,7 @@ bytecode = JsCode() node.emit(bytecode) - # XXX awful hack, we shall have a general way of doing that - from pypy.lang.js.jscode import POP - assert isinstance(bytecode.opcodes[-1], POP) - bytecode.opcodes.pop() - bytecode.run(ctx, check_stack=False) - return bytecode.stack[-1] + return bytecode.run(ctx, retlast=True) def parseIntjs(ctx, args, this): if len(args) < 1: @@ -263,12 +258,7 @@ ast = ASTBUILDER.dispatch(funcnode) bytecode = JsCode() ast.emit(bytecode) - # XXX awful hack - from pypy.lang.js.jscode import POP - assert isinstance(bytecode.opcodes[-1], POP) - bytecode.opcodes.pop() - bytecode.run(ctx, check_stack=False) - return bytecode.stack[-1] + return bytecode.run(ctx, retlast=True) def Construct(self, ctx, args=[]): return self.Call(ctx, args, this=None) @@ -559,12 +549,14 @@ self.w_Global = w_Global self.w_Object = w_Object - def run(self, script): + def run(self, script, interactive=False): """run the interpreter""" bytecode = JsCode() script.emit(bytecode) - bytecode.run(self.global_context) - # XXX not sure what this should return + if interactive: + return bytecode.run(self.global_context, retlast=True) + else: + bytecode.run(self.global_context) def wrap_arguments(pyargs): "receives a list of arguments and wrap then in their js equivalents" Modified: pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py Fri Apr 4 06:17:30 2008 @@ -69,7 +69,7 @@ res = self.interpreter.run(ast) if res not in (None, w_Undefined): try: - print res.GetValue().ToString(self.interpreter.w_Global) + print res.ToString(self.interpreter.w_Global) except ThrowException, exc: print exc.exception.ToString(self.interpreter.w_Global) except SystemExit: Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 06:17:30 2008 @@ -13,7 +13,10 @@ class AlreadyRun(Exception): pass -def run_bytecode(opcodes, ctx, stack, check_stack=True): +def run_bytecode(opcodes, ctx, stack, check_stack=True, retlast=False): + if retlast: + assert opcodes[-1] == 'POP' + opcodes.pop() i = 0 to_pop = 0 try: @@ -36,7 +39,10 @@ finally: for i in range(to_pop): ctx.pop_object() - + + if retlast: + assert len(stack) == 1 + return stack[0] if check_stack: assert not stack @@ -102,10 +108,10 @@ raise ValueError("Unknown opcode %s" % (operation,)) emit._annspecialcase_ = 'specialize:arg(1)' - def run(self, ctx, check_stack=True): + def run(self, ctx, check_stack=True, retlast=False): if self.has_labels: self.remove_labels() - run_bytecode(self.opcodes, ctx, self.stack, check_stack) + return run_bytecode(self.opcodes, ctx, self.stack, check_stack, retlast) def remove_labels(self): """ Basic optimization to remove all labels and change Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri Apr 4 06:17:30 2008 @@ -36,11 +36,7 @@ try: bytecode = JsCode() interpreter.load_source(code, '').emit(bytecode) - # XXX terrible hack - assert isinstance(bytecode.opcodes[-1], POP) - bytecode.opcodes.pop() - bytecode.run(ExecutionContext([ctx]), check_stack=False) - code_val = bytecode.stack[0] + code_val = bytecode.run(ExecutionContext([ctx]), retlast=True) except ThrowException, excpt: code_val = excpt.exception print code_val, value From fijal at codespeak.net Fri Apr 4 06:30:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 06:30:07 +0200 (CEST) Subject: [pypy-svn] r53317 - in pypy/branch/js-refactoring/pypy/lang/js: . test/ecma Message-ID: <20080404043007.2CCE116AA2F@codespeak.net> Author: fijal Date: Fri Apr 4 06:30:06 2008 New Revision: 53317 Modified: pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js Log: few minor fixes, print what ecma scripts do Modified: pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py Fri Apr 4 06:30:06 2008 @@ -66,7 +66,7 @@ traceback. """ try: - res = self.interpreter.run(ast) + res = self.interpreter.run(ast, interactive=True) if res not in (None, w_Undefined): try: print res.ToString(self.interpreter.w_Global) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 06:30:06 2008 @@ -2,7 +2,7 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\ W_Array, W_PrimitiveObject, ActivationObject,\ create_object, W_Object, w_Undefined, newbool,\ - w_True, w_False, W_List, w_Null, W_Iterator + w_True, w_False, W_List, w_Null, W_Iterator, W_Root from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException from pypy.rlib.unroll import unrolling_iterable from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ @@ -46,9 +46,16 @@ if check_stack: assert not stack +#def run_bytecode_unguarded(opcodes, ctx, stack, check_stack=True, retlast=False): +# try: +# run_bytecode(opcodes, ctx, stack, check_stack, retlast) +# except ThrowException: +# print +# raise + class T(list): def append(self, element): - assert element is not None + assert isinstance(element, W_Root) super(T, self).append(element) class JsCode(object): @@ -111,7 +118,12 @@ def run(self, ctx, check_stack=True, retlast=False): if self.has_labels: self.remove_labels() - return run_bytecode(self.opcodes, ctx, self.stack, check_stack, retlast) + if 1: + return run_bytecode(self.opcodes, ctx, self.stack, check_stack, + retlast) + else: + return run_bytecode_unguarded(self.opcodes, ctx, self,stack, + check_stack, retlast) def remove_labels(self): """ Basic optimization to remove all labels and change @@ -395,9 +407,9 @@ def eval(self, ctx, stack): try: var = ctx.resolve_identifier(self.name) - stack.append(var.type()) + stack.append(W_String(var.type())) except ThrowException: - stack.append(w_Undefined) + stack.append(W_String('undefined')) #class Typeof(UnaryOp): # def eval(self, ctx): Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Fri Apr 4 06:30:06 2008 @@ -66,7 +66,7 @@ raise Failed(excinfo=py.code.ExceptionInfo()) testcases = self.interp.global_context.resolve_identifier('testcases') self.tc = self.interp.global_context.resolve_identifier('tc') - testcount = testcases.GetValue().Get('length').GetValue().ToInt32() + testcount = testcases.Get('length').ToInt32() self.testcases = testcases return range(testcount) @@ -80,9 +80,9 @@ def run(self): ctx = JSTestFile.interp.global_context - r3 = ctx.resolve_identifier('run_test').GetValue() + r3 = ctx.resolve_identifier('run_test') w_test_number = W_IntNumber(self.number) - result = r3.Call(ctx=ctx, args=[w_test_number,]).GetValue().ToString() + result = r3.Call(ctx=ctx, args=[w_test_number,]).ToString() if result != "passed": raise Failed(msg=result) elif result == -1: Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js Fri Apr 4 06:30:06 2008 @@ -218,7 +218,7 @@ } function writeHeaderToLog( string ) { - // print( string ); + print( string ); } /* end of print functions */ From fijal at codespeak.net Fri Apr 4 06:40:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 06:40:51 +0200 (CEST) Subject: [pypy-svn] r53318 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080404044051.1779416AA44@codespeak.net> Author: fijal Date: Fri Apr 4 06:40:50 2008 New Revision: 53318 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: Small fix + debugging tools Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri Apr 4 06:40:50 2008 @@ -10,6 +10,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.streamio import open_file_as_stream from pypy.lang.js.jscode import JsCode +from pypy.rlib.rarithmetic import NAN, INFINITY ASTBUILDER = ASTBuilder() @@ -64,6 +65,8 @@ def Call(self, ctx, args=[], this=None): if len(args) >= 1 and not isnull_or_undefined(args[0]): return W_FloatNumber(args[0].ToNumber()) + elif isnull_or_undefined(args[0]): + return W_FloatNumber(NAN) else: return W_FloatNumber(0.0) @@ -553,6 +556,9 @@ """run the interpreter""" bytecode = JsCode() script.emit(bytecode) + if not we_are_translated(): + # debugging + self._code = bytecode if interactive: return bytecode.run(self.global_context, retlast=True) else: Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri Apr 4 06:40:50 2008 @@ -620,3 +620,6 @@ py.test.skip("I don't understand, but it does not work") assertv("pypy_repr(3);", 'W_IntNumber') assertv("pypy_repr(3.0);", 'W_FloatNumber') + +def test_number(): + assertp("print(Number(void 0))", "NaN") From fijal at codespeak.net Fri Apr 4 06:54:31 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 06:54:31 +0200 (CEST) Subject: [pypy-svn] r53319 - in pypy/branch/js-refactoring/pypy/lang/js: . test/ecma Message-ID: <20080404045431.956AC16AA55@codespeak.net> Author: fijal Date: Fri Apr 4 06:54:29 2008 New Revision: 53319 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js Log: * Minor fixes for getting tests right * Print test name Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri Apr 4 06:54:29 2008 @@ -63,9 +63,11 @@ class W_NumberObject(W_NativeObject): def Call(self, ctx, args=[], this=None): + import pdb + pdb.set_trace() if len(args) >= 1 and not isnull_or_undefined(args[0]): return W_FloatNumber(args[0].ToNumber()) - elif isnull_or_undefined(args[0]): + elif len(args) >= 1 and args[0] is w_Undefined: return W_FloatNumber(NAN) else: return W_FloatNumber(0.0) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 06:54:29 2008 @@ -15,8 +15,11 @@ def run_bytecode(opcodes, ctx, stack, check_stack=True, retlast=False): if retlast: - assert opcodes[-1] == 'POP' - opcodes.pop() + if opcodes[-1] == 'POP': + opcodes.pop() + popped = True + else: + popped = False i = 0 to_pop = 0 try: @@ -41,8 +44,12 @@ ctx.pop_object() if retlast: - assert len(stack) == 1 - return stack[0] + if popped: + assert len(stack) == 1 + return stack[0] + else: + assert not stack + return w_Undefined if check_stack: assert not stack Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri Apr 4 06:54:29 2008 @@ -46,10 +46,10 @@ return self def ToNumber(self): - return NaN + return 0.0 def ToInt32(self): - return 0 + return int(self.ToNumber()) def ToUInt32(self): return r_uint(0) @@ -393,6 +393,14 @@ def GetPropertyName(self): return self.ToString() + def ToNumber(self): + if not self.strval: + return 0.0 + try: + return float(self.strval) + except ValueError: + return NaN + class W_BaseNumber(W_Primitive): """ Base class for numbers, both known to be floats and those known to be integers Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js Fri Apr 4 06:54:29 2008 @@ -77,6 +77,7 @@ this.actual = a; this.passed = true; this.reason = ""; + print (n, d, e, a); this.bugnumber = BUGNUMBER; this.passed = getTestCaseResult( this.expect, this.actual ); From fijal at codespeak.net Fri Apr 4 07:03:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 07:03:09 +0200 (CEST) Subject: [pypy-svn] r53320 - in pypy/branch/js-refactoring/pypy/lang/js: . test Message-ID: <20080404050309.2CFF116AA3F@codespeak.net> Author: fijal Date: Fri Apr 4 07:03:08 2008 New Revision: 53320 Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: THIS is an important test. Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Fri Apr 4 07:03:08 2008 @@ -22,8 +22,8 @@ except OverflowError: return W_FloatNumber(float(ileft) + float(iright)) else: - fleft = nleft.ToNumber() - fright = nright.ToNumber() + fleft = nleft.ToNumber(ctx) + fright = nright.ToNumber(ctx) return W_FloatNumber(fleft + fright) def increment(ctx, nleft, constval=1): @@ -40,8 +40,8 @@ return W_IntNumber(ovfcheck(ileft - iright)) except OverflowError: return W_FloatNumber(float(ileft) - float(iright)) - fleft = nleft.ToNumber() - fright = nright.ToNumber() + fleft = nleft.ToNumber(ctx) + fright = nright.ToNumber(ctx) return W_FloatNumber(fleft - fright) def mult(ctx, nleft, nright): @@ -52,8 +52,8 @@ return W_IntNumber(ovfcheck(ileft * iright)) except OverflowError: return W_FloatNumber(float(ileft) * float(iright)) - fleft = nleft.ToNumber() - fright = nright.ToNumber() + fleft = nleft.ToNumber(ctx) + fright = nright.ToNumber(ctx) return W_FloatNumber(fleft * fright) def mod(ctx, nleft, nright): # XXX this one is really not following spec @@ -63,8 +63,8 @@ def division(ctx, nleft, nright): # XXX optimise for ints and floats - fleft = nleft.ToNumber() - fright = nright.ToNumber() + fleft = nleft.ToNumber(ctx) + fright = nright.ToNumber(ctx) if fright == 0: if fleft < 0: val = -INFINITY @@ -86,8 +86,8 @@ s1 = x.ToPrimitive(ctx, 'Number') s2 = y.ToPrimitive(ctx, 'Number') if not (isinstance(s1, W_String) and isinstance(s2, W_String)): - s4 = s1.ToNumber() - s5 = s2.ToNumber() + s4 = s1.ToNumber(ctx) + s5 = s2.ToNumber(ctx) if isnan(s4) or isnan(s5): return False return s4 > s5 @@ -106,8 +106,8 @@ s1 = x.ToPrimitive(ctx, 'Number') s2 = y.ToPrimitive(ctx, 'Number') if not (isinstance(s1, W_String) and isinstance(s2, W_String)): - s4 = s1.ToNumber() - s5 = s2.ToNumber() + s4 = s1.ToNumber(ctx) + s5 = s2.ToNumber(ctx) if isnan(s4) or isnan(s5): return False return s4 >= s5 @@ -133,8 +133,8 @@ if type1 == "undefined" or type1 == "null": return True if type1 == "number": - n1 = x.ToNumber() - n2 = y.ToNumber() + n1 = x.ToNumber(ctx) + n2 = y.ToNumber(ctx) if isnan(n1) or isnan(n2): return False if n1 == n2: @@ -151,13 +151,13 @@ (type1 == "null" and type2 == "undefined"): return True if type1 == "number" and type2 == "string": - return AbstractEC(ctx, x, W_FloatNumber(y.ToNumber())) + return AbstractEC(ctx, x, W_FloatNumber(y.ToNumber(ctx))) if type1 == "string" and type2 == "number": - return AbstractEC(ctx, W_FloatNumber(x.ToNumber()), y) + return AbstractEC(ctx, W_FloatNumber(x.ToNumber(ctx)), y) if type1 == "boolean": - return AbstractEC(ctx, W_FloatNumber(x.ToNumber()), y) + return AbstractEC(ctx, W_FloatNumber(x.ToNumber(ctx)), y) if type2 == "boolean": - return AbstractEC(ctx, x, W_FloatNumber(y.ToNumber())) + return AbstractEC(ctx, x, W_FloatNumber(y.ToNumber(ctx))) if (type1 == "string" or type1 == "number") and \ type2 == "object": return AbstractEC(ctx, x, y.ToPrimitive(ctx)) @@ -175,7 +175,7 @@ if isinstance(x, W_String) and isinstance(y, W_String): r = x.ToString(ctx) == y.ToString(ctx) else: - r = x.ToNumber() == y.ToNumber() + r = x.ToNumber(ctx) == y.ToNumber(ctx) return r def StrictEC(ctx, x, y): @@ -190,8 +190,8 @@ if type1 == "undefined" or type1 == "null": return True if type1 == "number": - n1 = x.ToNumber() - n2 = y.ToNumber() + n1 = x.ToNumber(ctx) + n2 = y.ToNumber(ctx) if isnan(n1) or isnan(n2): return False if n1 == n2: @@ -216,4 +216,4 @@ def uminus(obj): if isinstance(obj, W_IntNumber): return W_IntNumber(-obj.intval) - return W_FloatNumber(-obj.ToNumber()) + return W_FloatNumber(-obj.ToNumber(ctx)) Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri Apr 4 07:03:08 2008 @@ -10,7 +10,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.streamio import open_file_as_stream from pypy.lang.js.jscode import JsCode -from pypy.rlib.rarithmetic import NAN, INFINITY +from pypy.rlib.rarithmetic import NAN, INFINITY, isnan ASTBUILDER = ASTBuilder() @@ -63,18 +63,19 @@ class W_NumberObject(W_NativeObject): def Call(self, ctx, args=[], this=None): - import pdb - pdb.set_trace() if len(args) >= 1 and not isnull_or_undefined(args[0]): - return W_FloatNumber(args[0].ToNumber()) + return W_FloatNumber(args[0].ToNumber(ctx)) elif len(args) >= 1 and args[0] is w_Undefined: return W_FloatNumber(NAN) else: return W_FloatNumber(0.0) + def ToNumber(self, ctx): + return 0.0 + def Construct(self, ctx, args=[]): if len(args) >= 1 and not isnull_or_undefined(args[0]): - Value = W_FloatNumber(args[0].ToNumber()) + Value = W_FloatNumber(args[0].ToNumber(ctx)) return create_object(ctx, 'Number', Value = Value) return create_object(ctx, 'Number', Value = W_FloatNumber(0.0)) @@ -158,12 +159,12 @@ def isnanjs(ctx, args, this): if len(args) < 1: return W_Boolean(True) - return W_Boolean(args[0].ToNumber() == NaN) + return W_Boolean(isnan(args[0].ToNumber(ctx))) def isfinitejs(ctx, args, this): if len(args) < 1: return W_Boolean(True) - n = args[0].ToNumber() + n = args[0].ToNumber(ctx) if n == Infinity or n == -Infinity or n == NaN: return W_Boolean(False) else: @@ -188,7 +189,7 @@ def numberjs(ctx, args, this): if len(args) > 0: - return W_FloatNumber(args[0].ToNumber()) + return W_FloatNumber(args[0].ToNumber(ctx)) return W_IntNumber(0) def absjs(ctx, args, this): @@ -197,16 +198,16 @@ if val.intval > 0: return val # fast path return W_IntNumber(-val.intval) - return W_FloatNumber(abs(args[0].ToNumber())) + return W_FloatNumber(abs(args[0].ToNumber(ctx))) def floorjs(ctx, args, this): - return W_IntNumber(int(math.floor(args[0].ToNumber()))) + return W_IntNumber(int(math.floor(args[0].ToNumber(ctx)))) def powjs(ctx, args, this): - return W_FloatNumber(math.pow(args[0].ToNumber(), args[1].ToNumber())) + return W_FloatNumber(math.pow(args[0].ToNumber(ctx), args[1].ToNumber(ctx))) def sqrtjs(ctx, args, this): - return W_FloatNumber(math.sqrt(args[0].ToNumber())) + return W_FloatNumber(math.sqrt(args[0].ToNumber(ctx))) def versionjs(ctx, args, this): return w_Undefined Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri Apr 4 07:03:08 2008 @@ -45,17 +45,16 @@ # XXX should raise not implemented return self - def ToNumber(self): + def ToNumber(self, ctx): return 0.0 def ToInt32(self): - return int(self.ToNumber()) + return int(self.ToNumber(ctx)) def ToUInt32(self): return r_uint(0) def Get(self, P): - print P raise NotImplementedError def Put(self, P, V, dd=False, @@ -81,7 +80,7 @@ def __str__(self): return "w_undefined" - def ToNumber(self): + def ToNumber(self, ctx): return NaN def ToBoolean(self): @@ -246,6 +245,9 @@ W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) + def ToNumber(self, ctx): + return self.Get('valueOf').Call(ctx, args=[], this=self).ToNumber(ctx) + class W_NewBuiltin(W_PrimitiveObject): def __init__(self, ctx, Prototype=None, Class='function', Value=w_Undefined, callfunc=None): @@ -320,7 +322,7 @@ if P == 'length': try: res = V.ToUInt32() - if V.ToNumber() < 0: + if V.ToNumber(ctx) < 0: raise RangeError() self.propdict['length'].value = W_IntNumber(res) self.length = res @@ -357,7 +359,7 @@ return "true" return "false" - def ToNumber(self): + def ToNumber(self, ctx): if self.boolval: return 1.0 return 0.0 @@ -393,7 +395,7 @@ def GetPropertyName(self): return self.ToString() - def ToNumber(self): + def ToNumber(self, ctx): if not self.strval: return 0.0 try: @@ -426,7 +428,7 @@ def ToBoolean(self): return bool(self.intval) - def ToNumber(self): + def ToNumber(self, ctx): # XXX return float(self.intval) @@ -466,7 +468,7 @@ return False return bool(self.floatval) - def ToNumber(self): + def ToNumber(self, ctx): return self.floatval def ToInt32(self): Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri Apr 4 07:03:08 2008 @@ -13,7 +13,7 @@ bytecode.emit('LOAD_FLOATCONSTANT', 4) bytecode.emit('ADD') bytecode.run(ExecutionContext([W_Object()]), check_stack=False) - assert bytecode.stack[0].ToNumber() == 6.0 + assert bytecode.stack[0].ToNumber(None) == 6.0 def assertp(code, prints): l = [] @@ -47,7 +47,7 @@ elif isinstance(value, int): assert code_val.ToInt32() == value elif isinstance(value, float): - assert code_val.ToNumber() == value + assert code_val.ToNumber(None) == value else: assert code_val.ToString(ctx) == value @@ -623,3 +623,10 @@ def test_number(): assertp("print(Number(void 0))", "NaN") + assertp(""" + function MyObject( value ) { + this.value = value; + this.valueOf = new Function( "return this.value" ); + } + print (Number(new MyObject(100))); + """, "100") From fijal at codespeak.net Fri Apr 4 07:29:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 07:29:26 +0200 (CEST) Subject: [pypy-svn] r53321 - in pypy/branch/js-refactoring/pypy/lang/js: . test/ecma Message-ID: <20080404052926.AB46016AA4B@codespeak.net> Author: fijal Date: Fri Apr 4 07:29:25 2008 New Revision: 53321 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Log: * kill optimization that is wrong * fix some minor issues * fix post incr/decr Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 07:29:25 2008 @@ -285,6 +285,7 @@ self.identifier = identifier def eval(self, ctx, stack): + xxx scope = ctx.scope[self.depth] stack.append(scope.Get(self.identifier)) #stack.append(W_Reference(self.identifier, scope)) @@ -627,7 +628,14 @@ def process(self, ctx, name, stack): value = ctx.resolve_identifier(name) newval = increment(ctx, value) - stack.append(newval) + stack.append(value) + return newval + +class STORE_POSTDECR(BaseStore): + def process(self, ctx, name, stack): + value = ctx.resolve_identifier(name) + newval = increment(ctx, value, -1) + stack.append(value) return newval class LABEL(Opcode): Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Fri Apr 4 07:29:25 2008 @@ -215,38 +215,6 @@ self.what.emit(bytecode) bytecode.emit('STORE_MEMBER' + self._get_name()) -class StuffAssignment(Expression): - - def eval(self, ctx): - v1 = self.left.eval(ctx) - v3 = self.right.eval(ctx).GetValue() - op = self.type - if op == "=": - val = v3 - elif op == "*=": - val = mult(ctx, v1.GetValue(), v3) - elif op == "+=": - val = plus(ctx, v1.GetValue(), v3) - elif op == "-=": - val = sub(ctx, v1.GetValue(), v3) - elif op == "/=": - val = division(ctx, v1.GetValue(), v3) - elif op == "%=": - val = mod(ctx, v1.GetValue(), v3) - elif op == "&=": - val = W_IntNumber(v1.GetValue().ToInt32() & v3.ToInt32()) - elif op == "|=": - val = W_IntNumber(v1.GetValue().ToInt32() | v3.ToInt32()) - elif op == "^=": - val = W_IntNumber(v1.GetValue().ToInt32() ^ v3.ToInt32()) - else: - print op - raise NotImplementedError() - - v1.PutValue(val, ctx) - return val - - class Block(Statement): def __init__(self, pos, nodes): self.pos = pos @@ -308,13 +276,6 @@ self.condition = condition self.truepart = truepart self.falsepart = falsepart - - def eval(self, ctx): - if self.condition.eval(ctx).GetValue().ToBoolean(): - return self.truepart.eval(ctx).GetValue() - else: - return self.falsepart.eval(ctx).GetValue() - class Member(Expression): "this is for object[name]" @@ -709,14 +670,6 @@ bytecode.emit('STORE', self.identifier) else: return True - - def eval(self, ctx): - name = self.identifier.get_literal() - if self.expr is None: - ctx.variable.Put(name, w_Undefined, dd=True) - else: - ctx.variable.Put(name, self.expr.eval(ctx).GetValue(), dd=True) - return self.identifier.eval(ctx) class VariableIdentifier(Expression): def __init__(self, pos, depth, identifier): @@ -725,7 +678,7 @@ self.identifier = identifier def emit(self, bytecode): - bytecode.emit('LOAD_REALVAR', self.depth, self.identifier) + bytecode.emit('LOAD_VARIABLE', self.identifier) def get_literal(self): return self.identifier Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Fri Apr 4 07:29:25 2008 @@ -82,7 +82,7 @@ ctx = JSTestFile.interp.global_context r3 = ctx.resolve_identifier('run_test') w_test_number = W_IntNumber(self.number) - result = r3.Call(ctx=ctx, args=[w_test_number,]).ToString() + result = r3.Call(ctx=ctx, args=[w_test_number]).ToString() if result != "passed": raise Failed(msg=result) elif result == -1: From fijal at codespeak.net Fri Apr 4 07:48:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 07:48:46 +0200 (CEST) Subject: [pypy-svn] r53322 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080404054846.E596216AA52@codespeak.net> Author: fijal Date: Fri Apr 4 07:48:46 2008 New Revision: 53322 Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py Log: Some fixes in order to pass most of Number test suite. more follows... Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Fri Apr 4 07:48:46 2008 @@ -213,7 +213,7 @@ raise ThrowException(W_String('it is not a constructor')) return res -def uminus(obj): +def uminus(obj, ctx): if isinstance(obj, W_IntNumber): return W_IntNumber(-obj.intval) return W_FloatNumber(-obj.ToNumber(ctx)) Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri Apr 4 07:48:46 2008 @@ -474,10 +474,18 @@ put_values(w_Number, { 'constructor': w_FncPrototype, 'prototype': w_NumPrototype, - 'NaN': W_FloatNumber(NaN), - 'POSITIVE_INFINITY': W_FloatNumber(Infinity), - 'NEGATIVE_INFINITY': W_FloatNumber(-Infinity), }) + w_Number.propdict['prototype'].ro = True + w_Number.Put('MAX_VALUE', W_FloatNumber(1.7976931348623157e308), + ro=True, dd=True) + w_Number.Put('MIN_VALUE', W_FloatNumber(0), ro=True, dd=True) + w_Number.Put('NaN', W_FloatNumber(NaN), ro=True, dd=True) + # ^^^ this is exactly in test case suite + w_Number.Put('POSITIVE_INFINITY', W_FloatNumber(Infinity), + ro=True, dd=True) + w_Number.Put('NEGATIVE_INFINITY', W_FloatNumber(-Infinity), + ro=True, dd=True) + w_Global.Put('Number', w_Number) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Fri Apr 4 07:48:46 2008 @@ -490,7 +490,7 @@ class UMINUS(BaseUnaryOperation): def eval(self, ctx, stack): - stack.append(uminus(stack.pop())) + stack.append(uminus(stack.pop(), ctx)) class NOT(BaseUnaryOperation): def eval(self, ctx, stack): @@ -543,7 +543,7 @@ name = elem.ToString() value = self.operation(ctx, left, name, value) left.Put(name, value) - stack.append(left) + stack.append(value) class STORE_MEMBER(BaseStoreMember): def operation(self, ctx, left, elem, value): From jared.grubb at codespeak.net Fri Apr 4 07:58:11 2008 From: jared.grubb at codespeak.net (jared.grubb at codespeak.net) Date: Fri, 4 Apr 2008 07:58:11 +0200 (CEST) Subject: [pypy-svn] r53323 - in pypy/dist/pypy/rlib/parsing: . test Message-ID: <20080404055811.8C05D16AA4D@codespeak.net> Author: jared.grubb Date: Fri Apr 4 07:58:08 2008 New Revision: 53323 Modified: pypy/dist/pypy/rlib/parsing/regexparse.py pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle Log: Got DFA PCRE tests passing (a few dont pass, because '.' even matches newline in our version); changes is regexparse are to allow '-' as a character to match and to handle '\' better in class expressions Modified: pypy/dist/pypy/rlib/parsing/regexparse.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/regexparse.py (original) +++ pypy/dist/pypy/rlib/parsing/regexparse.py Fri Apr 4 07:58:08 2008 @@ -116,6 +116,10 @@ return {regex.StringExpression(c)} | '.' return {regex.RangeExpression(chr(0), chr(255))} + | '-' + return {regex.StringExpression('-')} + | '\' + return {regex.StringExpression('\\')} | ']' return {regex.StringExpression(']')}; @@ -126,10 +130,10 @@ return {c}; QUOTEDCHAR: - `(\\x[0-9a-fA-F]{2})|(\\[0-3]?[0-7][0-7])|(\\c.)|(\\.)`; + `(\\x[0-9a-fA-F]{2})|(\\[0-3]?[0-7][0-7])|(\\c.)|(\\[^dswDSW])`; CHAR: - `[^\*\+\(\)\[\]\{\|\.\-\?\^]`; + `[^\*\+\(\)\[\]\{\|\.\-\?\^\\]`; range: '[' @@ -742,12 +746,28 @@ self._pos = _choice6 _choice7 = self._pos try: + _result = self.__chars__('-') + _result = (regex.StringExpression('-')) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice7 + _choice8 = self._pos + try: + _result = self.__chars__('\\') + _result = (regex.StringExpression('\\')) + break + except BacktrackException, _exc: + _error = self._combine_errors(_error, _exc.error) + self._pos = _choice8 + _choice9 = self._pos + try: _result = self.__chars__(']') _result = (regex.StringExpression(']')) break except BacktrackException, _exc: _error = self._combine_errors(_error, _exc.error) - self._pos = _choice7 + self._pos = _choice9 raise BacktrackException(_error) _result = self.__chars__(']') _result = (regex.StringExpression(']')) @@ -876,7 +896,7 @@ try: _result = None _error = None - _result = self._regex1192240515() + _result = self._regex1423754537() assert _status.status != _status.LEFTRECURSION _status.status = _status.NORMAL _status.pos = self._pos @@ -908,7 +928,7 @@ try: _result = None _error = None - _result = self._regex100349762() + _result = self._regex2132196932() assert _status.status != _status.LEFTRECURSION _status.status = _status.NORMAL _status.pos = self._pos @@ -1615,10 +1635,10 @@ self._dict_NUM = {} self._pos = 0 self._inputstream = inputstream - def _regex100349762(self): + def _regex2132196932(self): _choice0 = self._pos _runner = self._Runner(self._inputstream, self._pos) - _i = _runner.recognize_100349762(self._pos) + _i = _runner.recognize_2132196932(self._pos) if _runner.last_matched_state == -1: self._pos = _choice0 raise BacktrackException @@ -1629,10 +1649,10 @@ _result = self._inputstream[_pos: _upto] self._pos = _upto return _result - def _regex1192240515(self): + def _regex1166214427(self): _choice1 = self._pos _runner = self._Runner(self._inputstream, self._pos) - _i = _runner.recognize_1192240515(self._pos) + _i = _runner.recognize_1166214427(self._pos) if _runner.last_matched_state == -1: self._pos = _choice1 raise BacktrackException @@ -1643,10 +1663,10 @@ _result = self._inputstream[_pos: _upto] self._pos = _upto return _result - def _regex1166214427(self): + def _regex1423754537(self): _choice2 = self._pos _runner = self._Runner(self._inputstream, self._pos) - _i = _runner.recognize_1166214427(self._pos) + _i = _runner.recognize_1423754537(self._pos) if _runner.last_matched_state == -1: self._pos = _choice2 raise BacktrackException @@ -1664,7 +1684,7 @@ self.last_matched_state = -1 self.last_matched_index = -1 self.state = -1 - def recognize_100349762(runner, i): + def recognize_2132196932(runner, i): #auto-generated code, don't edit assert i >= 0 input = runner.text @@ -1689,8 +1709,6 @@ state = 1 elif char == ',': state = 1 - elif char == '\\': - state = 1 else: break runner.last_matched_state = state @@ -1703,7 +1721,7 @@ break runner.state = state return ~i - def recognize_1192240515(runner, i): + def recognize_1166214427(runner, i): #auto-generated code, don't edit assert i >= 0 input = runner.text @@ -1716,64 +1734,95 @@ except IndexError: runner.state = 0 return ~i - if char == '\\': - state = 6 + if char == '0': + state = 1 + elif '1' <= char <= '9': + state = 2 else: break - if state == 1: + if state == 2: runner.last_matched_index = i - 1 runner.last_matched_state = state try: char = input[i] i += 1 except IndexError: - runner.state = 1 + runner.state = 2 return i - if '0' <= char <= '7': - state = 4 + if '0' <= char <= '9': + state = 2 + continue else: break - if state == 2: + runner.last_matched_state = state + runner.last_matched_index = i - 1 + runner.state = state + if i == len(input): + return i + else: + return ~i + break + runner.state = state + return ~i + def recognize_1423754537(runner, i): + #auto-generated code, don't edit + assert i >= 0 + input = runner.text + state = 0 + while 1: + if state == 0: + try: + char = input[i] + i += 1 + except IndexError: + runner.state = 0 + return ~i + if char == '\\': + state = 5 + else: + break + if state == 1: runner.last_matched_index = i - 1 runner.last_matched_state = state try: char = input[i] i += 1 except IndexError: - runner.state = 2 + runner.state = 1 return i if '0' <= char <= '9': - state = 5 + state = 6 elif 'A' <= char <= 'F': - state = 5 + state = 6 elif 'a' <= char <= 'f': - state = 5 + state = 6 else: break - if state == 3: + if state == 2: runner.last_matched_index = i - 1 runner.last_matched_state = state try: char = input[i] i += 1 except IndexError: - runner.state = 3 + runner.state = 2 return i - if '\x00' <= char <= '\xff': - state = 7 + if '0' <= char <= '7': + state = 4 else: break - if state == 4: + if state == 3: runner.last_matched_index = i - 1 runner.last_matched_state = state try: char = input[i] i += 1 except IndexError: - runner.state = 4 + runner.state = 3 return i if '0' <= char <= '7': - state = 7 + state = 2 + continue else: break if state == 5: @@ -1783,84 +1832,61 @@ except IndexError: runner.state = 5 return ~i - if '0' <= char <= '9': - state = 7 - elif 'A' <= char <= 'F': - state = 7 - elif 'a' <= char <= 'f': - state = 7 - else: - break - if state == 6: - try: - char = input[i] - i += 1 - except IndexError: - runner.state = 6 - return ~i - if '0' <= char <= '3': + if char == 'x': state = 1 continue - elif char == 'x': + elif '4' <= char <= '7': state = 2 continue - elif char == 'c': + elif '0' <= char <= '3': state = 3 continue - elif '4' <= char <= '7': - state = 4 - continue elif 'y' <= char <= '\xff': - state = 7 + state = 4 elif '\x00' <= char <= '/': - state = 7 - elif '8' <= char <= 'b': - state = 7 - elif 'd' <= char <= 'w': + state = 4 + elif 'E' <= char <= 'R': + state = 4 + elif 'e' <= char <= 'r': + state = 4 + elif '8' <= char <= 'C': + state = 4 + elif 'X' <= char <= 'b': + state = 4 + elif 'T' <= char <= 'V': + state = 4 + elif 't' <= char <= 'v': + state = 4 + elif char == 'c': state = 7 else: break - runner.last_matched_state = state - runner.last_matched_index = i - 1 - runner.state = state - if i == len(input): - return i - else: - return ~i - break - runner.state = state - return ~i - def recognize_1166214427(runner, i): - #auto-generated code, don't edit - assert i >= 0 - input = runner.text - state = 0 - while 1: - if state == 0: + if state == 6: try: char = input[i] i += 1 except IndexError: - runner.state = 0 + runner.state = 6 return ~i - if char == '0': - state = 1 - elif '1' <= char <= '9': - state = 2 + if '0' <= char <= '9': + state = 4 + elif 'A' <= char <= 'F': + state = 4 + elif 'a' <= char <= 'f': + state = 4 else: break - if state == 2: + if state == 7: runner.last_matched_index = i - 1 runner.last_matched_state = state try: char = input[i] i += 1 except IndexError: - runner.state = 2 + runner.state = 7 return i - if '0' <= char <= '9': - state = 2 - continue + if '\x00' <= char <= '\xff': + state = 4 else: break runner.last_matched_state = state @@ -1931,6 +1957,14 @@ + + + + + + + + def test_generate(): f = py.magic.autopath() oldcontent = f.read() Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Fri Apr 4 07:58:08 2008 @@ -99,7 +99,8 @@ greedy_ops = re.compile(no_escape + r'[*?+}\(]\?') # Look for *? +? }? (? back_refs = re.compile(no_escape + r'\(.*' + no_escape + r'\\1') # find a \1 caret_in_middle = re.compile(no_escape + r'[^\[\\]\^') - substr_quotes = re.compile(no_escape + r'(\\Q|\\E)') # PCRE allows \Q.....\E to quote substrings, we dont. + posix_char_classes = re.compile(no_escape + r'\[[^]]*\[:[^]]+:\][^]]*\]') # like [[:digit:]] + bad_backslashes = re.compile(no_escape + r'(\\Q|\\E|\\G|\\P|\\8|\\9|\\A|\\Z|\\F|\\R|\\B|\\b|\\h|\\H|\\v|\\V|\\z|\\N)') # PCRE allows \Q.....\E to quote substrings, we dont. # Perl allows single-digit hex escapes. Change \x0 -> \x00, for example expand_perl_hex = re.compile(r'\\x([0-9a-fA-F]{1})(?=[^0-9a-fA-F]|$)') @@ -139,7 +140,11 @@ flags = matches[0][-1] # Get the flags for the regex regex = expand_perl_hex.sub(lambda m: r'\x0'+m.group(1), regex) - + if regex.startswith('\\A'): + regex = '^' + regex[2:] # We treat \A like ^ + if regex.startswith('\\Z'): + regex = regex[:-2] + '$' # We treat \Z like $ + tests = [] if greedy_ops.search(regex) or back_refs.search(regex): # Suppress complex features we can't do @@ -147,9 +152,11 @@ elif flags: # Suppress any test that requires PCRE flags pass + elif posix_char_classes.search(regex): + pass elif caret_in_middle.search(regex): pass - elif substr_quotes.search(regex): + elif bad_backslashes.search(regex): pass else: # In any other case, we're going to add the test @@ -166,10 +173,15 @@ if not test.endswith('\\\\'): # Two \'s means a real \ test = test[:-1] test = expand_perl_hex.sub(lambda m: r'\x0'+m.group(1), test) + + disqualify_test = bad_backslashes.search(test) + try: test = unescape(test) except Exception: + disqualify_test = True print "Warning: could not unescape %r" % test + # Third line in the OUTPUT is the result, either: # ' 0: ...' for a match (but this is ONLY escaped by \x__ types) @@ -178,7 +190,7 @@ while lines: match = lines.pop(0).rstrip('\r\n') match = re.sub(r'\\x([0-9a-fA-F]{2})', lambda m: chr(int(m.group(1),16)), match) - if match.startswith('No match') or match.startswith('Error'): + if match.startswith('No match') or match.startswith('Error') or match.startswith('Partial'): break elif match.startswith(' 0:'): # Now we need to eat any further lines like: @@ -193,7 +205,8 @@ elif not match: print " *** %r ***" % match raise Exception("Lost sync in output.") - tests.append((test,match)) + if not disqualify_test: + tests.append((test,match)) pickle.dump(suite, picklefile) def get_pcre_pickle(file): @@ -220,6 +233,7 @@ runner = make_runner(regex_to_use) # Now run the test expressions against the Regex for test, match in tests: + print "/%r/%r/"%(test, match) expect_match = (match != 'No match') # Create possible subsequences that we should test @@ -232,7 +246,7 @@ subseq_gen = ( (start, len(test)) for start in start_range ) else: # Go backwards to simulate greediness - subseq_gen = ( (start, end) for start in start_range for end in range(len(test)+1, start, -1) ) + subseq_gen = ( (start, end) for start in start_range for end in range(len(test)+1, start-1, -1) ) # Search the possibilities for a match... for start, end in subseq_gen: Modified: pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle (original) +++ pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle Fri Apr 4 07:58:08 2008 @@ -80,668 +80,668 @@ S' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' p48 tp49 -a(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaF' -p50 -S' 0: ' -p51 -tp52 -aaa(lp53 +aaa(lp50 S'(a|abcd|african)' -p54 +p51 ag3 -a(lp55 +a(lp52 (g41 S' 0: a' +p53 +tp54 +a(S'abcd' +p55 +S' 0: abcd' p56 tp57 -a(S'abcd' +a(S'african' p58 -S' 0: abcd' +S' 0: african' p59 tp60 -a(S'african' -p61 -S' 0: african' -p62 -tp63 -aaa(lp64 +aaa(lp61 S'^abc' -p65 +p62 ag3 -a(lp66 +a(lp63 (S'abcdef' -p67 +p64 S' 0: abc' +p65 +tp66 +a(S'*** Failers' +p67 +S'No match' p68 tp69 -a(S'*** Failers' +a(S'xyzabc' p70 S'No match' p71 tp72 -a(S'xyzabc' +a(S'xyz\nabc' p73 S'No match' p74 tp75 -a(S'xyz\nabc' -p76 -S'No match' +aaa(lp76 +S'^abc' p77 -tp78 -aaa(lp79 -S'\\Aabc' -p80 ag3 -a(lp81 +a(lp78 (S'abcdef' -p82 +p79 S' 0: abc' +p80 +tp81 +a(S'*** Failers' +p82 +S'No match' p83 tp84 -a(S'*** Failers' +a(S'xyzabc' p85 S'No match' p86 tp87 -a(S'xyzabc' +a(S'xyz\nabc' p88 S'No match' p89 tp90 -a(S'xyz\nabc' -p91 -S'No match' +aaa(lp91 +S'x\\dy\\Dz' p92 -tp93 -aaa(lp94 -S'\\Gabc' -p95 ag3 -a(lp96 -(S'abcdef' +a(lp93 +(S'x9yzz' +p94 +S' 0: x9yzz' +p95 +tp96 +a(S'x0y+z' p97 -S' 0: abc' +S' 0: x0y+z' p98 tp99 -a(S'xyzabc>3' +a(S'*** Failers' p100 -S' 0: abc' +S'No match' p101 tp102 -a(S'*** Failers' +a(S'xyz' p103 S'No match' p104 tp105 -a(S'xyzabc' +a(S'xxy0z' p106 S'No match' p107 tp108 -a(S'xyzabc>2' -p109 -S'No match' +aaa(lp109 +S'x\\sy\\Sz' p110 -tp111 -aaa(lp112 -S'x\\dy\\Dz' -p113 ag3 -a(lp114 -(S'x9yzz' +a(lp111 +(S'x yzz' +p112 +S' 0: x yzz' +p113 +tp114 +a(S'x y+z' p115 -S' 0: x9yzz' +S' 0: x y+z' p116 tp117 -a(S'x0y+z' +a(S'*** Failers' p118 -S' 0: x0y+z' +S'No match' p119 tp120 -a(S'*** Failers' +a(S'xyz' p121 S'No match' p122 tp123 -a(S'xyz' +a(S'xxyyz' p124 S'No match' p125 tp126 -a(S'xxy0z' -p127 -S'No match' +aaa(lp127 +S'x\\wy\\Wz' p128 -tp129 -aaa(lp130 -S'x\\sy\\Sz' -p131 ag3 -a(lp132 -(S'x yzz' +a(lp129 +(S'xxy+z' +p130 +S' 0: xxy+z' +p131 +tp132 +a(S'*** Failers' p133 -S' 0: x yzz' +S'No match' p134 tp135 -a(S'x y+z' +a(S'xxy0z' p136 -S' 0: x y+z' +S'No match' p137 tp138 -a(S'*** Failers' +a(S'x+y+z' p139 S'No match' p140 tp141 -a(S'xyz' -p142 -S'No match' +aaa(lp142 +S'x.y' p143 -tp144 -a(S'xxyyz' +ag3 +a(lp144 +(S'x+y' p145 -S'No match' +S' 0: x+y' p146 tp147 -aaa(lp148 -S'x\\wy\\Wz' +a(S'x-y' +p148 +S' 0: x-y' p149 -ag3 -a(lp150 -(S'xxy+z' +tp150 +a(S'*** Failers' p151 -S' 0: xxy+z' +S'No match' p152 tp153 -a(S'*** Failers' +a(S'x\ny' p154 S'No match' p155 tp156 -a(S'xxy0z' -p157 -S'No match' +aaa(lp157 +S'a\\d$' p158 -tp159 -a(S'x+y+z' +ag3 +a(lp159 +(S'ba0' p160 -S'No match' +S' 0: a0' p161 tp162 -aaa(lp163 -S'x.y' +a(S'ba0\n' +p163 +S' 0: a0' p164 -ag3 -a(lp165 -(S'x+y' +tp165 +a(S'*** Failers' p166 -S' 0: x+y' +S'No match' p167 tp168 -a(S'x-y' +a(S'ba0\ncd' p169 -S' 0: x-y' +S'No match' p170 tp171 -a(S'*** Failers' -p172 -S'No match' +aaa(lp172 +S'[^a]' p173 -tp174 -a(S'x\ny' +ag3 +a(lp174 +(S'abcd' p175 -S'No match' +S' 0: b' p176 tp177 aaa(lp178 -S'a\\d\\z' +S'ab?\\w' p179 ag3 a(lp180 -(S'ba0' +(S'abz' p181 -S' 0: a0' +S' 0: abz' p182 tp183 -a(S'*** Failers' +a(S'abbz' p184 -S'No match' +S' 0: abb' p185 tp186 -a(S'ba0\n' +a(S'azz' p187 -S'No match' +S' 0: az' p188 tp189 -a(S'ba0\ncd' -p190 -S'No match' +aaa(lp190 +S'x{0,3}yz' p191 -tp192 -aaa(lp193 -S'a\\d\\Z' -p194 ag3 -a(lp195 -(S'ba0' +a(lp192 +(S'ayzq' +p193 +S' 0: yz' +p194 +tp195 +a(S'axyzq' p196 -S' 0: a0' +S' 0: xyz' p197 tp198 -a(S'ba0\n' +a(S'axxyz' p199 -S' 0: a0' +S' 0: xxyz' p200 tp201 -a(S'*** Failers' +a(S'axxxyzq' p202 -S'No match' +S' 0: xxxyz' p203 tp204 -a(S'ba0\ncd' +a(S'axxxxyzq' p205 -S'No match' +S' 0: xxxyz' p206 tp207 -aaa(lp208 -S'a\\d$' +a(S'*** Failers' +p208 +S'No match' p209 -ag3 -a(lp210 -(S'ba0' +tp210 +a(S'ax' p211 -S' 0: a0' +S'No match' p212 tp213 -a(S'ba0\n' +a(S'axx' p214 -S' 0: a0' +S'No match' p215 tp216 -a(S'*** Failers' -p217 -S'No match' +aaa(lp217 +S'x{3}yz' p218 -tp219 -a(S'ba0\ncd' +ag3 +a(lp219 +(S'axxxyzq' p220 -S'No match' +S' 0: xxxyz' p221 tp222 -aaa(lp223 -S'[^a]' +a(S'axxxxyzq' +p223 +S' 0: xxxyz' p224 -ag3 -a(lp225 -(S'abcd' +tp225 +a(S'*** Failers' p226 -S' 0: b' +S'No match' p227 tp228 -aaa(lp229 -S'ab?\\w' +a(S'ax' +p229 +S'No match' p230 -ag3 -a(lp231 -(S'abz' +tp231 +a(S'axx' p232 -S' 0: abz' +S'No match' p233 tp234 -a(S'abbz' +a(S'ayzq' p235 -S' 0: abb' +S'No match' p236 tp237 -a(S'azz' +a(S'axyzq' p238 -S' 0: az' +S'No match' p239 tp240 -aaa(lp241 -S'x{0,3}yz' +a(S'axxyz' +p241 +S'No match' p242 -ag3 -a(lp243 -(S'ayzq' -p244 -S' 0: yz' +tp243 +aaa(lp244 +S'x{2,3}yz' p245 -tp246 -a(S'axyzq' +ag3 +a(lp246 +(S'axxyz' p247 -S' 0: xyz' +S' 0: xxyz' p248 tp249 -a(S'axxyz' +a(S'axxxyzq' p250 -S' 0: xxyz' +S' 0: xxxyz' p251 tp252 -a(S'axxxyzq' +a(S'axxxxyzq' p253 S' 0: xxxyz' p254 tp255 -a(S'axxxxyzq' +a(S'*** Failers' p256 -S' 0: xxxyz' +S'No match' p257 tp258 -a(S'*** Failers' +a(S'ax' p259 S'No match' p260 tp261 -a(S'ax' +a(S'axx' p262 S'No match' p263 tp264 -a(S'axx' +a(S'ayzq' p265 S'No match' p266 tp267 -aaa(lp268 -S'x{3}yz' +a(S'axyzq' +p268 +S'No match' p269 -ag3 -a(lp270 -(S'axxxyzq' -p271 -S' 0: xxxyz' +tp270 +aaa(lp271 +S'[^a]+' p272 -tp273 -a(S'axxxxyzq' +ag3 +a(lp273 +(S'bac' p274 -S' 0: xxxyz' +S' 0: b' p275 tp276 -a(S'*** Failers' +a(S'bcdefax' p277 -S'No match' +S' 0: bcdef' p278 tp279 -a(S'ax' +a(S'*** Failers' p280 -S'No match' +S' 0: *** F' p281 tp282 -a(S'axx' +a(S'aaaaa' p283 S'No match' p284 tp285 -a(S'ayzq' -p286 -S'No match' +aaa(lp286 +S'[^a]*' p287 -tp288 -a(S'axyzq' +ag3 +a(lp288 +(S'bac' p289 -S'No match' +S' 0: b' p290 tp291 -a(S'axxyz' +a(S'bcdefax' p292 -S'No match' +S' 0: bcdef' p293 tp294 -aaa(lp295 -S'x{2,3}yz' +a(S'*** Failers' +p295 +S' 0: *** F' p296 -ag3 -a(lp297 -(S'axxyz' +tp297 +a(S'aaaaa' p298 -S' 0: xxyz' +S' 0: ' p299 tp300 -a(S'axxxyzq' -p301 -S' 0: xxxyz' +aaa(lp301 +S'[^a]{3,5}' p302 -tp303 -a(S'axxxxyzq' +ag3 +a(lp303 +(S'xyz' p304 -S' 0: xxxyz' +S' 0: xyz' p305 tp306 -a(S'*** Failers' +a(S'awxyza' p307 -S'No match' +S' 0: wxyz' p308 tp309 -a(S'ax' +a(S'abcdefa' p310 -S'No match' +S' 0: bcdef' p311 tp312 -a(S'axx' +a(S'abcdefghijk' p313 -S'No match' +S' 0: bcdef' p314 tp315 -a(S'ayzq' +a(S'*** Failers' p316 -S'No match' +S' 0: *** F' p317 tp318 -a(S'axyzq' +a(S'axya' p319 S'No match' p320 tp321 -aaa(lp322 -S'[^a]+' +a(S'axa' +p322 +S'No match' p323 -ag3 -a(lp324 -(S'bac' +tp324 +a(S'aaaaa' p325 -S' 0: b' +S'No match' p326 tp327 -a(S'bcdefax' -p328 -S' 0: bcdef' +aaa(lp328 +S'\\d*' p329 -tp330 -a(S'*** Failers' +ag3 +a(lp330 +(S'1234b567' p331 -S' 0: *** F' +S' 0: 1234' p332 tp333 -a(S'aaaaa' +a(S'xyz' p334 -S'No match' +S' 0: ' p335 tp336 aaa(lp337 -S'[^a]*' +S'\\D*' p338 ag3 a(lp339 -(S'bac' +(S'a1234b567' p340 -S' 0: b' +S' 0: a' p341 tp342 -a(S'bcdefax' +a(S'xyz' p343 -S' 0: bcdef' +S' 0: xyz' p344 tp345 -a(S'*** Failers' -p346 -S' 0: *** F' +aaa(lp346 +S'\\d+' p347 -tp348 -a(S'aaaaa' +ag3 +a(lp348 +(S'ab1234c56' p349 -S' 0: ' +S' 0: 1234' p350 tp351 -aaa(lp352 -S'[^a]{3,5}' +a(S'*** Failers' +p352 +S'No match' p353 -ag3 -a(lp354 -(S'xyz' +tp354 +a(S'xyz' p355 -S' 0: xyz' +S'No match' p356 tp357 -a(S'awxyza' -p358 -S' 0: wxyz' +aaa(lp358 +S'\\D+' p359 -tp360 -a(S'abcdefa' +ag3 +a(lp360 +(S'ab123c56' p361 -S' 0: bcdef' +S' 0: ab' p362 tp363 -a(S'abcdefghijk' +a(S'*** Failers' p364 -S' 0: bcdef' +S' 0: *** Failers' p365 tp366 -a(S'*** Failers' +a(S'789' p367 -S' 0: *** F' +S'No match' p368 tp369 -a(S'axya' -p370 -S'No match' +aaa(lp370 +S'\\d?A' p371 -tp372 -a(S'axa' +ag3 +a(lp372 +(S'045ABC' p373 -S'No match' +S' 0: 5A' p374 tp375 -a(S'aaaaa' +a(S'ABC' p376 -S'No match' +S' 0: A' p377 tp378 -aaa(lp379 -S'\\d*' +a(S'*** Failers' +p379 +S'No match' p380 -ag3 -a(lp381 -(S'1234b567' +tp381 +a(S'XYZ' p382 -S' 0: 1234' +S'No match' p383 tp384 -a(S'xyz' -p385 -S' 0: ' +aaa(lp385 +S'\\D?A' p386 -tp387 -aaa(lp388 -S'\\D*' -p389 ag3 -a(lp390 -(S'a1234b567' +a(lp387 +(S'ABC' +p388 +S' 0: A' +p389 +tp390 +a(S'BAC' p391 -S' 0: a' +S' 0: BA' p392 tp393 -a(S'xyz' +a(S'9ABC' p394 -S' 0: xyz' +S' 0: A' p395 tp396 -aaa(lp397 -S'\\d+' +a(S'*** Failers' +p397 +S'No match' p398 -ag3 -a(lp399 -(S'ab1234c56' -p400 -S' 0: 1234' +tp399 +aaa(lp400 +S'a+' p401 -tp402 -a(S'*** Failers' +ag3 +a(lp402 +(S'aaaa' p403 -S'No match' +S' 0: aaaa' p404 tp405 -a(S'xyz' -p406 -S'No match' +aaa(lp406 +S'^.*xyz' p407 -tp408 -aaa(lp409 -S'\\D+' -p410 ag3 -a(lp411 -(S'ab123c56' +a(lp408 +(S'xyz' +p409 +S' 0: xyz' +p410 +tp411 +a(S'ggggggggxyz' p412 -S' 0: ab' +S' 0: ggggggggxyz' p413 tp414 -a(S'*** Failers' -p415 -S' 0: *** Failers' +aaa(lp415 +S'^.+xyz' p416 -tp417 -a(S'789' +ag3 +a(lp417 +(S'abcdxyz' p418 -S'No match' +S' 0: abcdxyz' p419 tp420 -aaa(lp421 -S'\\d?A' +a(S'axyz' +p421 +S' 0: axyz' p422 -ag3 -a(lp423 -(S'045ABC' +tp423 +a(S'*** Failers' p424 -S' 0: 5A' +S'No match' p425 tp426 -a(S'ABC' +a(S'xyz' p427 -S' 0: A' +S'No match' p428 tp429 -a(S'*** Failers' -p430 -S'No match' +aaa(lp430 +S'^.?xyz' p431 -tp432 -a(S'XYZ' +ag3 +a(lp432 +(S'xyz' p433 -S'No match' +S' 0: xyz' p434 tp435 -aaa(lp436 -S'\\D?A' +a(S'cxyz' +p436 +S' 0: cxyz' p437 -ag3 -a(lp438 -(S'ABC' -p439 -S' 0: A' +tp438 +aaa(lp439 +S'^\\d{2,3}X' p440 -tp441 -a(S'BAC' +ag3 +a(lp441 +(S'12X' p442 -S' 0: BA' +S' 0: 12X' p443 tp444 -a(S'9ABC' +a(S'123X' p445 -S' 0: A' +S' 0: 123X' p446 tp447 a(S'*** Failers' @@ -749,44 +749,44 @@ S'No match' p449 tp450 -aaa(lp451 -S'a+' +a(S'X' +p451 +S'No match' p452 -ag3 -a(lp453 -(S'aaaa' +tp453 +a(S'1X' p454 -S' 0: aaaa' +S'No match' p455 tp456 -aaa(lp457 -S'^.*xyz' +a(S'1234X' +p457 +S'No match' p458 -ag3 -a(lp459 -(S'xyz' -p460 -S' 0: xyz' +tp459 +aaa(lp460 +S'^[abcd]\\d' p461 -tp462 -a(S'ggggggggxyz' +ag3 +a(lp462 +(S'a45' p463 -S' 0: ggggggggxyz' +S' 0: a4' p464 tp465 -aaa(lp466 -S'^.+xyz' +a(S'b93' +p466 +S' 0: b9' p467 -ag3 -a(lp468 -(S'abcdxyz' +tp468 +a(S'c99z' p469 -S' 0: abcdxyz' +S' 0: c9' p470 tp471 -a(S'axyz' +a(S'd04' p472 -S' 0: axyz' +S' 0: d0' p473 tp474 a(S'*** Failers' @@ -794,399 +794,399 @@ S'No match' p476 tp477 -a(S'xyz' +a(S'e45' p478 S'No match' p479 tp480 -aaa(lp481 -S'^.?xyz' +a(S'abcd' +p481 +S'No match' p482 -ag3 -a(lp483 -(S'xyz' +tp483 +a(S'abcd1234' p484 -S' 0: xyz' +S'No match' p485 tp486 -a(S'cxyz' +a(S'1234' p487 -S' 0: cxyz' +S'No match' p488 tp489 aaa(lp490 -S'^\\d{2,3}X' +S'^[abcd]*\\d' p491 ag3 a(lp492 -(S'12X' +(S'a45' p493 -S' 0: 12X' +S' 0: a4' p494 tp495 -a(S'123X' +a(S'b93' p496 -S' 0: 123X' +S' 0: b9' p497 tp498 -a(S'*** Failers' +a(S'c99z' p499 -S'No match' +S' 0: c9' p500 tp501 -a(S'X' +a(S'd04' p502 -S'No match' +S' 0: d0' p503 tp504 -a(S'1X' +a(S'abcd1234' p505 -S'No match' +S' 0: abcd1' p506 tp507 -a(S'1234X' +a(S'1234' p508 -S'No match' +S' 0: 1' p509 tp510 -aaa(lp511 -S'^[abcd]\\d' +a(S'*** Failers' +p511 +S'No match' p512 -ag3 -a(lp513 -(S'a45' +tp513 +a(S'e45' p514 -S' 0: a4' +S'No match' p515 tp516 -a(S'b93' +a(S'abcd' p517 -S' 0: b9' +S'No match' p518 tp519 -a(S'c99z' -p520 -S' 0: c9' +aaa(lp520 +S'^[abcd]+\\d' p521 -tp522 -a(S'd04' +ag3 +a(lp522 +(S'a45' p523 -S' 0: d0' +S' 0: a4' p524 tp525 -a(S'*** Failers' +a(S'b93' p526 -S'No match' +S' 0: b9' p527 tp528 -a(S'e45' +a(S'c99z' p529 -S'No match' +S' 0: c9' p530 tp531 -a(S'abcd' +a(S'd04' p532 -S'No match' +S' 0: d0' p533 tp534 a(S'abcd1234' p535 -S'No match' +S' 0: abcd1' p536 tp537 -a(S'1234' +a(S'*** Failers' p538 S'No match' p539 tp540 -aaa(lp541 -S'^[abcd]*\\d' +a(S'1234' +p541 +S'No match' p542 -ag3 -a(lp543 -(S'a45' +tp543 +a(S'e45' p544 -S' 0: a4' +S'No match' p545 tp546 -a(S'b93' +a(S'abcd' p547 -S' 0: b9' +S'No match' p548 tp549 -a(S'c99z' -p550 -S' 0: c9' +aaa(lp550 +S'^a+X' p551 -tp552 -a(S'd04' +ag3 +a(lp552 +(S'aX' p553 -S' 0: d0' +S' 0: aX' p554 tp555 -a(S'abcd1234' +a(S'aaX' p556 -S' 0: abcd1' +S' 0: aaX' p557 tp558 -a(S'1234' -p559 -S' 0: 1' +aaa(lp559 +S'^[abcd]?\\d' p560 -tp561 -a(S'*** Failers' +ag3 +a(lp561 +(S'a45' p562 -S'No match' +S' 0: a4' p563 tp564 -a(S'e45' +a(S'b93' p565 -S'No match' +S' 0: b9' p566 tp567 -a(S'abcd' +a(S'c99z' p568 -S'No match' +S' 0: c9' p569 tp570 -aaa(lp571 -S'^[abcd]+\\d' +a(S'd04' +p571 +S' 0: d0' p572 -ag3 -a(lp573 -(S'a45' +tp573 +a(S'1234' p574 -S' 0: a4' +S' 0: 1' p575 tp576 -a(S'b93' +a(S'*** Failers' p577 -S' 0: b9' +S'No match' p578 tp579 -a(S'c99z' +a(S'abcd1234' p580 -S' 0: c9' +S'No match' p581 tp582 -a(S'd04' +a(S'e45' p583 -S' 0: d0' +S'No match' p584 tp585 -a(S'abcd1234' -p586 -S' 0: abcd1' +aaa(lp586 +S'^[abcd]{2,3}\\d' p587 -tp588 -a(S'*** Failers' +ag3 +a(lp588 +(S'ab45' p589 -S'No match' +S' 0: ab4' p590 tp591 -a(S'1234' +a(S'bcd93' p592 -S'No match' +S' 0: bcd9' p593 tp594 -a(S'e45' +a(S'*** Failers' p595 S'No match' p596 tp597 -a(S'abcd' +a(S'1234' p598 S'No match' p599 tp600 -aaa(lp601 -S'^a+X' +a(S'a36' +p601 +S'No match' p602 -ag3 -a(lp603 -(S'aX' +tp603 +a(S'abcd1234' p604 -S' 0: aX' +S'No match' p605 tp606 -a(S'aaX' +a(S'ee45' p607 -S' 0: aaX' +S'No match' p608 tp609 aaa(lp610 -S'^[abcd]?\\d' +S'^(abc)*\\d' p611 ag3 a(lp612 -(S'a45' +(S'abc45' p613 -S' 0: a4' +S' 0: abc4' p614 tp615 -a(S'b93' +a(S'abcabcabc45' p616 -S' 0: b9' +S' 0: abcabcabc4' p617 tp618 -a(S'c99z' +a(S'42xyz' p619 -S' 0: c9' +S' 0: 4' p620 tp621 -a(S'd04' +a(S'*** Failers' p622 -S' 0: d0' +S'No match' p623 tp624 -a(S'1234' -p625 -S' 0: 1' +aaa(lp625 +S'^(abc)+\\d' p626 -tp627 -a(S'*** Failers' +ag3 +a(lp627 +(S'abc45' p628 -S'No match' +S' 0: abc4' p629 tp630 -a(S'abcd1234' +a(S'abcabcabc45' p631 -S'No match' +S' 0: abcabcabc4' p632 tp633 -a(S'e45' +a(S'*** Failers' p634 S'No match' p635 tp636 -aaa(lp637 -S'^[abcd]{2,3}\\d' +a(S'42xyz' +p637 +S'No match' p638 -ag3 -a(lp639 -(S'ab45' -p640 -S' 0: ab4' +tp639 +aaa(lp640 +S'^(abc)?\\d' p641 -tp642 -a(S'bcd93' +ag3 +a(lp642 +(S'abc45' p643 -S' 0: bcd9' +S' 0: abc4' p644 tp645 -a(S'*** Failers' +a(S'42xyz' p646 -S'No match' +S' 0: 4' p647 tp648 -a(S'1234' +a(S'*** Failers' p649 S'No match' p650 tp651 -a(S'a36' +a(S'abcabcabc45' p652 S'No match' p653 tp654 -a(S'abcd1234' -p655 -S'No match' +aaa(lp655 +S'^(abc){2,3}\\d' p656 -tp657 -a(S'ee45' +ag3 +a(lp657 +(S'abcabc45' p658 -S'No match' +S' 0: abcabc4' p659 tp660 -aaa(lp661 -S'^(abc)*\\d' +a(S'abcabcabc45' +p661 +S' 0: abcabcabc4' p662 -ag3 -a(lp663 -(S'abc45' +tp663 +a(S'*** Failers' p664 -S' 0: abc4' +S'No match' p665 tp666 -a(S'abcabcabc45' +a(S'abcabcabcabc45' p667 -S' 0: abcabcabc4' +S'No match' p668 tp669 -a(S'42xyz' +a(S'abc45' p670 -S' 0: 4' +S'No match' p671 tp672 -a(S'*** Failers' +a(S'42xyz' p673 S'No match' p674 tp675 aaa(lp676 -S'^(abc)+\\d' +S'^(a*\\w|ab)=(a*\\w|ab)' p677 ag3 a(lp678 -(S'abc45' +(S'ab=ab' p679 -S' 0: abc4' +S' 0: ab=ab' p680 tp681 -a(S'abcabcabc45' -p682 -S' 0: abcabcabc4' +aaa(lp682 +S'^abc' p683 -tp684 -a(S'*** Failers' +ag3 +a(lp684 +(S'abcdef' p685 -S'No match' +S' 0: abc' p686 tp687 -a(S'42xyz' +a(S'*** Failers' p688 S'No match' p689 tp690 aaa(lp691 -S'^(abc)?\\d' +S'^(a*|xyz)' p692 ag3 a(lp693 -(S'abc45' +(S'bcd' p694 -S' 0: abc4' +S' 0: ' p695 tp696 -a(S'42xyz' +a(S'aaabcd' p697 -S' 0: 4' +S' 0: aaa' p698 tp699 -a(S'*** Failers' +a(S'xyz' p700 -S'No match' +S' 0: xyz' p701 tp702 -a(S'abcabcabc45' +a(S'*** Failers' p703 -S'No match' +S' 0: ' p704 tp705 aaa(lp706 -S'^(abc){2,3}\\d' +S'xyz$' p707 ag3 a(lp708 -(S'abcabc45' +(S'xyz' p709 -S' 0: abcabc4' +S' 0: xyz' p710 tp711 -a(S'abcabcabc45' +a(S'xyz\n' p712 -S' 0: abcabcabc4' +S' 0: xyz' p713 tp714 a(S'*** Failers' @@ -1194,5045 +1194,4441 @@ S'No match' p716 tp717 -a(S'abcabcabcabc45' -p718 -S'No match' +aaa(lp718 +S'^abcdef' p719 -tp720 -a(S'abc45' +ag3 +a(lp720 +(S'*** Failers' p721 S'No match' p722 tp723 -a(S'42xyz' -p724 -S'No match' +aaa(lp724 +S'^a{2,4}\\d+z' p725 -tp726 -aaa(lp727 -S'^(a*\\w|ab)=(a*\\w|ab)' -p728 ag3 -a(lp729 -(S'ab=ab' -p730 -S' 0: ab=ab' +a(lp726 +(S'*** Failers' +p727 +S'No match' +p728 +tp729 +aaa(lp730 +S'^abcdef' p731 -tp732 -aaa(lp733 -S'^abc' +ag3 +a(lp732 +aa(lp733 +S'(ab*(cd|ef))+X' p734 ag3 a(lp735 -(S'abcdef' -p736 -S' 0: abc' +aa(lp736 +S'the quick brown fox' p737 -tp738 -a(S'*** Failers' +ag3 +a(lp738 +(S'the quick brown fox' p739 -S'No match' +S' 0: the quick brown fox' p740 tp741 -a(S'abcdefB' +a(S'The quick brown FOX' p742 S'No match' p743 tp744 -aaa(lp745 -S'^(a*|xyz)' +a(S'What do you know about the quick brown fox?' +p745 +S' 0: the quick brown fox' p746 -ag3 -a(lp747 -(S'bcd' +tp747 +a(S'What do you know about THE QUICK BROWN FOX?' p748 -S' 0: ' +S'No match' p749 tp750 -a(S'aaabcd' -p751 -S' 0: aaa' +aaa(lp751 +S'abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz' p752 -tp753 -a(S'xyz' +ag3 +a(lp753 +(S'abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz' p754 -S' 0: xyz' +S' 0: abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz' p755 tp756 -a(S'xyzN' -p757 -S' 0: xyz' +aaa(lp757 +S'a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz' p758 -tp759 -a(S'*** Failers' +ag3 +a(lp759 +(S'abxyzpqrrrabbxyyyypqAzz' p760 -S' 0: ' +S' 0: abxyzpqrrrabbxyyyypqAzz' p761 tp762 -a(S'bcdN' +a(S'abxyzpqrrrabbxyyyypqAzz' p763 -S'No match' +S' 0: abxyzpqrrrabbxyyyypqAzz' p764 tp765 -aaa(lp766 -S'xyz$' +a(S'aabxyzpqrrrabbxyyyypqAzz' +p766 +S' 0: aabxyzpqrrrabbxyyyypqAzz' p767 -ag3 -a(lp768 -(S'xyz' +tp768 +a(S'aaabxyzpqrrrabbxyyyypqAzz' p769 -S' 0: xyz' +S' 0: aaabxyzpqrrrabbxyyyypqAzz' p770 tp771 -a(S'xyz\n' +a(S'aaaabxyzpqrrrabbxyyyypqAzz' p772 -S' 0: xyz' +S' 0: aaaabxyzpqrrrabbxyyyypqAzz' p773 tp774 -a(S'*** Failers' +a(S'abcxyzpqrrrabbxyyyypqAzz' p775 -S'No match' +S' 0: abcxyzpqrrrabbxyyyypqAzz' p776 tp777 -a(S'xyzZ' +a(S'aabcxyzpqrrrabbxyyyypqAzz' p778 -S'No match' +S' 0: aabcxyzpqrrrabbxyyyypqAzz' p779 tp780 -a(S'xyz\nZ' +a(S'aaabcxyzpqrrrabbxyyyypAzz' p781 -S'No match' +S' 0: aaabcxyzpqrrrabbxyyyypAzz' p782 tp783 -aaa(lp784 -S'\\Gabc' +a(S'aaabcxyzpqrrrabbxyyyypqAzz' +p784 +S' 0: aaabcxyzpqrrrabbxyyyypqAzz' p785 -ag3 -a(lp786 -(S'abcdef' +tp786 +a(S'aaabcxyzpqrrrabbxyyyypqqAzz' p787 -S' 0: abc' +S' 0: aaabcxyzpqrrrabbxyyyypqqAzz' p788 tp789 -a(S'defabcxyz>3' +a(S'aaabcxyzpqrrrabbxyyyypqqqAzz' p790 -S' 0: abc' +S' 0: aaabcxyzpqrrrabbxyyyypqqqAzz' p791 tp792 -a(S'*** Failers' +a(S'aaabcxyzpqrrrabbxyyyypqqqqAzz' p793 -S'No match' +S' 0: aaabcxyzpqrrrabbxyyyypqqqqAzz' p794 tp795 -a(S'defabcxyz' +a(S'aaabcxyzpqrrrabbxyyyypqqqqqAzz' p796 -S'No match' +S' 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz' p797 tp798 -aaa(lp799 -S'^abcdef' +a(S'aaabcxyzpqrrrabbxyyyypqqqqqqAzz' +p799 +S' 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz' p800 -ag3 -a(lp801 -(S'abP' +tp801 +a(S'aaaabcxyzpqrrrabbxyyyypqAzz' p802 -S' 0: abcdef' +S' 0: aaaabcxyzpqrrrabbxyyyypqAzz' p803 tp804 -a(S'*** Failers' +a(S'abxyzzpqrrrabbxyyyypqAzz' p805 -S'No match' +S' 0: abxyzzpqrrrabbxyyyypqAzz' p806 tp807 -a(S'abxP' +a(S'aabxyzzzpqrrrabbxyyyypqAzz' p808 -S'No match' +S' 0: aabxyzzzpqrrrabbxyyyypqAzz' p809 tp810 -aaa(lp811 -S'^a{2,4}\\d+z' +a(S'aaabxyzzzzpqrrrabbxyyyypqAzz' +p811 +S' 0: aaabxyzzzzpqrrrabbxyyyypqAzz' p812 -ag3 -a(lp813 -(S'aP' +tp813 +a(S'aaaabxyzzzzpqrrrabbxyyyypqAzz' p814 -S' 0: aa0z' +S' 0: aaaabxyzzzzpqrrrabbxyyyypqAzz' p815 tp816 -a(S'aaaa4444444444444zP' +a(S'abcxyzzpqrrrabbxyyyypqAzz' p817 -S' 0: aaaa4444444444444z' +S' 0: abcxyzzpqrrrabbxyyyypqAzz' p818 tp819 -a(S'*** Failers' +a(S'aabcxyzzzpqrrrabbxyyyypqAzz' p820 -S'No match' +S' 0: aabcxyzzzpqrrrabbxyyyypqAzz' p821 tp822 -a(S'azP' +a(S'aaabcxyzzzzpqrrrabbxyyyypqAzz' p823 -S'No match' +S' 0: aaabcxyzzzzpqrrrabbxyyyypqAzz' p824 tp825 -a(S'aaaaaP' +a(S'aaaabcxyzzzzpqrrrabbxyyyypqAzz' p826 -S'No match' +S' 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz' p827 tp828 -a(S'a56P' +a(S'aaaabcxyzzzzpqrrrabbbxyyyypqAzz' p829 -S'No match' +S' 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz' p830 tp831 -aaa(lp832 -S'^abcdef' +a(S'aaaabcxyzzzzpqrrrabbbxyyyyypqAzz' +p832 +S' 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz' p833 -ag3 -a(lp834 -(S'abcP' +tp834 +a(S'aaabcxyzpqrrrabbxyyyypABzz' p835 -S' 0: def' +S' 0: aaabcxyzpqrrrabbxyyyypABzz' p836 tp837 -aaa(lp838 -S'(ab*(cd|ef))+X' +a(S'aaabcxyzpqrrrabbxyyyypABBzz' +p838 +S' 0: aaabcxyzpqrrrabbxyyyypABBzz' p839 -ag3 -a(lp840 -(S'adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkjPZ' +tp840 +a(S'>>>aaabxyzpqrrrabbxyyyypqAzz' p841 -S'No match' +S' 0: aaabxyzpqrrrabbxyyyypqAzz' p842 tp843 -a(S'lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefaPBZ' +a(S'>aaaabxyzpqrrrabbxyyyypqAzz' p844 -S' 0: bbbbbbbbbbbbcdX' +S' 0: aaaabxyzpqrrrabbxyyyypqAzz' p845 tp846 -aaa(lp847 -S'the quick brown fox' +a(S'>>>>abcxyzpqrrrabbxyyyypqAzz' +p847 +S' 0: abcxyzpqrrrabbxyyyypqAzz' p848 -ag3 -a(lp849 -(S'the quick brown fox' +tp849 +a(S'*** Failers' p850 -S' 0: the quick brown fox' +S'No match' p851 tp852 -a(S'The quick brown FOX' +a(S'abxyzpqrrabbxyyyypqAzz' p853 S'No match' p854 tp855 -a(S'What do you know about the quick brown fox?' +a(S'abxyzpqrrrrabbxyyyypqAzz' p856 -S' 0: the quick brown fox' +S'No match' p857 tp858 -a(S'What do you know about THE QUICK BROWN FOX?' +a(S'abxyzpqrrrabxyyyypqAzz' p859 S'No match' p860 tp861 -aaa(lp862 -S'abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz' +a(S'aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz' +p862 +S'No match' p863 -ag3 -a(lp864 -(S'abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz' +tp864 +a(S'aaaabcxyzzzzpqrrrabbbxyyypqAzz' p865 -S' 0: abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz' +S'No match' p866 tp867 -aaa(lp868 -S'a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz' +a(S'aaabcxyzpqrrrabbxyyyypqqqqqqqAzz' +p868 +S'No match' p869 -ag3 -a(lp870 -(S'abxyzpqrrrabbxyyyypqAzz' -p871 -S' 0: abxyzpqrrrabbxyyyypqAzz' +tp870 +aaa(lp871 +S'^(abc){1,2}zz' p872 -tp873 -a(S'abxyzpqrrrabbxyyyypqAzz' +ag3 +a(lp873 +(S'abczz' p874 -S' 0: abxyzpqrrrabbxyyyypqAzz' +S' 0: abczz' p875 tp876 -a(S'aabxyzpqrrrabbxyyyypqAzz' +a(S'abcabczz' p877 -S' 0: aabxyzpqrrrabbxyyyypqAzz' +S' 0: abcabczz' p878 tp879 -a(S'aaabxyzpqrrrabbxyyyypqAzz' +a(S'*** Failers' p880 -S' 0: aaabxyzpqrrrabbxyyyypqAzz' +S'No match' p881 tp882 -a(S'aaaabxyzpqrrrabbxyyyypqAzz' +a(S'zz' p883 -S' 0: aaaabxyzpqrrrabbxyyyypqAzz' +S'No match' p884 tp885 -a(S'abcxyzpqrrrabbxyyyypqAzz' +a(S'abcabcabczz' p886 -S' 0: abcxyzpqrrrabbxyyyypqAzz' +S'No match' p887 tp888 -a(S'aabcxyzpqrrrabbxyyyypqAzz' +a(S'>>abczz' p889 -S' 0: aabcxyzpqrrrabbxyyyypqAzz' +S'No match' p890 tp891 -a(S'aaabcxyzpqrrrabbxyyyypAzz' -p892 -S' 0: aaabcxyzpqrrrabbxyyyypAzz' +aaa(lp892 +S'^(b+|a){1,2}c' p893 -tp894 -a(S'aaabcxyzpqrrrabbxyyyypqAzz' +ag3 +a(lp894 +(S'bc' p895 -S' 0: aaabcxyzpqrrrabbxyyyypqAzz' +S' 0: bc' p896 tp897 -a(S'aaabcxyzpqrrrabbxyyyypqqAzz' +a(S'bbc' p898 -S' 0: aaabcxyzpqrrrabbxyyyypqqAzz' +S' 0: bbc' p899 tp900 -a(S'aaabcxyzpqrrrabbxyyyypqqqAzz' +a(S'bbbc' p901 -S' 0: aaabcxyzpqrrrabbxyyyypqqqAzz' +S' 0: bbbc' p902 tp903 -a(S'aaabcxyzpqrrrabbxyyyypqqqqAzz' +a(S'bac' p904 -S' 0: aaabcxyzpqrrrabbxyyyypqqqqAzz' +S' 0: bac' p905 tp906 -a(S'aaabcxyzpqrrrabbxyyyypqqqqqAzz' +a(S'bbac' p907 -S' 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz' +S' 0: bbac' p908 tp909 -a(S'aaabcxyzpqrrrabbxyyyypqqqqqqAzz' +a(S'aac' p910 -S' 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz' +S' 0: aac' p911 tp912 -a(S'aaaabcxyzpqrrrabbxyyyypqAzz' +a(S'abbbbbbbbbbbc' p913 -S' 0: aaaabcxyzpqrrrabbxyyyypqAzz' +S' 0: abbbbbbbbbbbc' p914 tp915 -a(S'abxyzzpqrrrabbxyyyypqAzz' +a(S'bbbbbbbbbbbac' p916 -S' 0: abxyzzpqrrrabbxyyyypqAzz' +S' 0: bbbbbbbbbbbac' p917 tp918 -a(S'aabxyzzzpqrrrabbxyyyypqAzz' +a(S'*** Failers' p919 -S' 0: aabxyzzzpqrrrabbxyyyypqAzz' +S'No match' p920 tp921 -a(S'aaabxyzzzzpqrrrabbxyyyypqAzz' +a(S'aaac' p922 -S' 0: aaabxyzzzzpqrrrabbxyyyypqAzz' +S'No match' p923 tp924 -a(S'aaaabxyzzzzpqrrrabbxyyyypqAzz' +a(S'abbbbbbbbbbbac' p925 -S' 0: aaaabxyzzzzpqrrrabbxyyyypqAzz' +S'No match' p926 tp927 -a(S'abcxyzzpqrrrabbxyyyypqAzz' -p928 -S' 0: abcxyzzpqrrrabbxyyyypqAzz' +aaa(lp928 +S'^\\ca\\cA\\c[\\c{\\c:' p929 -tp930 -a(S'aabcxyzzzpqrrrabbxyyyypqAzz' +ag3 +a(lp930 +(S'\x01\x01\x1b;z' p931 -S' 0: aabcxyzzzpqrrrabbxyyyypqAzz' +S' 0: \x01\x01\x1b;z' p932 tp933 -a(S'aaabcxyzzzzpqrrrabbxyyyypqAzz' -p934 -S' 0: aaabcxyzzzzpqrrrabbxyyyypqAzz' +aaa(lp934 +S'^[ab\\]cde]' p935 -tp936 -a(S'aaaabcxyzzzzpqrrrabbxyyyypqAzz' +ag3 +a(lp936 +(S'athing' p937 -S' 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz' +S' 0: a' p938 tp939 -a(S'aaaabcxyzzzzpqrrrabbbxyyyypqAzz' +a(S'bthing' p940 -S' 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz' +S' 0: b' p941 tp942 -a(S'aaaabcxyzzzzpqrrrabbbxyyyyypqAzz' +a(S']thing' p943 -S' 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz' +S' 0: ]' p944 tp945 -a(S'aaabcxyzpqrrrabbxyyyypABzz' +a(S'cthing' p946 -S' 0: aaabcxyzpqrrrabbxyyyypABzz' +S' 0: c' p947 tp948 -a(S'aaabcxyzpqrrrabbxyyyypABBzz' +a(S'dthing' p949 -S' 0: aaabcxyzpqrrrabbxyyyypABBzz' +S' 0: d' p950 tp951 -a(S'>>>aaabxyzpqrrrabbxyyyypqAzz' +a(S'ething' p952 -S' 0: aaabxyzpqrrrabbxyyyypqAzz' +S' 0: e' p953 tp954 -a(S'>aaaabxyzpqrrrabbxyyyypqAzz' +a(S'*** Failers' p955 -S' 0: aaaabxyzpqrrrabbxyyyypqAzz' +S'No match' p956 tp957 -a(S'>>>>abcxyzpqrrrabbxyyyypqAzz' +a(S'fthing' p958 -S' 0: abcxyzpqrrrabbxyyyypqAzz' +S'No match' p959 tp960 -a(S'*** Failers' +a(S'[thing' p961 S'No match' p962 tp963 -a(S'abxyzpqrrabbxyyyypqAzz' +a(S'\\thing' p964 S'No match' p965 tp966 -a(S'abxyzpqrrrrabbxyyyypqAzz' -p967 -S'No match' +aaa(lp967 +S'^[]cde]' p968 -tp969 -a(S'abxyzpqrrrabxyyyypqAzz' +ag3 +a(lp969 +(S']thing' p970 -S'No match' +S' 0: ]' p971 tp972 -a(S'aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz' +a(S'cthing' p973 -S'No match' +S' 0: c' p974 tp975 -a(S'aaaabcxyzzzzpqrrrabbbxyyypqAzz' +a(S'dthing' p976 -S'No match' +S' 0: d' p977 tp978 -a(S'aaabcxyzpqrrrabbxyyyypqqqqqqqAzz' +a(S'ething' p979 -S'No match' +S' 0: e' p980 tp981 -aaa(lp982 -S'^(abc){1,2}zz' +a(S'*** Failers' +p982 +S'No match' p983 -ag3 -a(lp984 -(S'abczz' +tp984 +a(S'athing' p985 -S' 0: abczz' +S'No match' p986 tp987 -a(S'abcabczz' +a(S'fthing' p988 -S' 0: abcabczz' +S'No match' p989 tp990 -a(S'*** Failers' -p991 -S'No match' +aaa(lp991 +S'^[^ab\\]cde]' p992 -tp993 -a(S'zz' +ag3 +a(lp993 +(S'fthing' p994 -S'No match' +S' 0: f' p995 tp996 -a(S'abcabcabczz' +a(S'[thing' p997 -S'No match' +S' 0: [' p998 tp999 -a(S'>>abczz' +a(S'\\thing' p1000 -S'No match' +S' 0: \\' p1001 tp1002 -aaa(lp1003 -S'^(b+|a){1,2}c' +a(S'*** Failers' +p1003 +S' 0: *' p1004 -ag3 -a(lp1005 -(S'bc' +tp1005 +a(S'athing' p1006 -S' 0: bc' +S'No match' p1007 tp1008 -a(S'bbc' +a(S'bthing' p1009 -S' 0: bbc' +S'No match' p1010 tp1011 -a(S'bbbc' +a(S']thing' p1012 -S' 0: bbbc' +S'No match' p1013 tp1014 -a(S'bac' +a(S'cthing' p1015 -S' 0: bac' +S'No match' p1016 tp1017 -a(S'bbac' +a(S'dthing' p1018 -S' 0: bbac' +S'No match' p1019 tp1020 -a(S'aac' +a(S'ething' p1021 -S' 0: aac' +S'No match' p1022 tp1023 -a(S'abbbbbbbbbbbc' -p1024 -S' 0: abbbbbbbbbbbc' +aaa(lp1024 +S'^[^]cde]' p1025 -tp1026 -a(S'bbbbbbbbbbbac' +ag3 +a(lp1026 +(S'athing' p1027 -S' 0: bbbbbbbbbbbac' +S' 0: a' p1028 tp1029 -a(S'*** Failers' +a(S'fthing' p1030 -S'No match' +S' 0: f' p1031 tp1032 -a(S'aaac' +a(S'*** Failers' p1033 -S'No match' +S' 0: *' p1034 tp1035 -a(S'abbbbbbbbbbbac' +a(S']thing' p1036 S'No match' p1037 tp1038 -aaa(lp1039 -S'^\\ca\\cA\\c[\\c{\\c:' +a(S'cthing' +p1039 +S'No match' p1040 -ag3 -a(lp1041 -(S'\x01\x01\x1b;z' +tp1041 +a(S'dthing' p1042 -S' 0: \x01\x01\x1b;z' +S'No match' p1043 tp1044 -aaa(lp1045 -S'^[ab\\]cde]' +a(S'ething' +p1045 +S'No match' p1046 -ag3 -a(lp1047 -(S'athing' -p1048 -S' 0: a' +tp1047 +aaa(lp1048 +S'^\\\x81' p1049 -tp1050 -a(S'bthing' +ag3 +a(lp1050 +(S'\x81' p1051 -S' 0: b' +S' 0: \x81' p1052 tp1053 -a(S']thing' -p1054 -S' 0: ]' +aaa(lp1054 +S'^\xff' p1055 -tp1056 -a(S'cthing' +ag3 +a(lp1056 +(S'\xff' p1057 -S' 0: c' +S' 0: \xff' p1058 tp1059 -a(S'dthing' -p1060 -S' 0: d' +aaa(lp1060 +S'^[0-9]+$' p1061 -tp1062 -a(S'ething' +ag3 +a(lp1062 +(S'0' p1063 -S' 0: e' +S' 0: 0' p1064 tp1065 -a(S'*** Failers' +a(S'1' p1066 -S'No match' +S' 0: 1' p1067 tp1068 -a(S'fthing' +a(S'2' p1069 -S'No match' +S' 0: 2' p1070 tp1071 -a(S'[thing' +a(S'3' p1072 -S'No match' +S' 0: 3' p1073 tp1074 -a(S'\\thing' +a(S'4' p1075 -S'No match' +S' 0: 4' p1076 tp1077 -aaa(lp1078 -S'^[]cde]' +a(S'5' +p1078 +S' 0: 5' p1079 -ag3 -a(lp1080 -(S']thing' +tp1080 +a(S'6' p1081 -S' 0: ]' +S' 0: 6' p1082 tp1083 -a(S'cthing' +a(S'7' p1084 -S' 0: c' +S' 0: 7' p1085 tp1086 -a(S'dthing' +a(S'8' p1087 -S' 0: d' +S' 0: 8' p1088 tp1089 -a(S'ething' +a(S'9' p1090 -S' 0: e' +S' 0: 9' p1091 tp1092 -a(S'*** Failers' +a(S'10' p1093 -S'No match' +S' 0: 10' p1094 tp1095 -a(S'athing' +a(S'100' p1096 -S'No match' +S' 0: 100' p1097 tp1098 -a(S'fthing' +a(S'*** Failers' p1099 S'No match' p1100 tp1101 -aaa(lp1102 -S'^[^ab\\]cde]' +a(S'abc' +p1102 +S'No match' p1103 -ag3 -a(lp1104 -(S'fthing' -p1105 -S' 0: f' +tp1104 +aaa(lp1105 +S'^.*nter' p1106 -tp1107 -a(S'[thing' +ag3 +a(lp1107 +(S'enter' p1108 -S' 0: [' +S' 0: enter' p1109 tp1110 -a(S'\\thing' +a(S'inter' p1111 -S' 0: \\' +S' 0: inter' p1112 tp1113 -a(S'*** Failers' +a(S'uponter' p1114 -S' 0: *' +S' 0: uponter' p1115 tp1116 -a(S'athing' -p1117 -S'No match' +aaa(lp1117 +S'^xxx[0-9]+$' p1118 -tp1119 -a(S'bthing' +ag3 +a(lp1119 +(S'xxx0' p1120 -S'No match' +S' 0: xxx0' p1121 tp1122 -a(S']thing' +a(S'xxx1234' p1123 -S'No match' +S' 0: xxx1234' p1124 tp1125 -a(S'cthing' +a(S'*** Failers' p1126 S'No match' p1127 tp1128 -a(S'dthing' +a(S'xxx' p1129 S'No match' p1130 tp1131 -a(S'ething' -p1132 -S'No match' +aaa(lp1132 +S'^.+[0-9][0-9][0-9]$' p1133 -tp1134 -aaa(lp1135 -S'^[^]cde]' -p1136 ag3 -a(lp1137 -(S'athing' +a(lp1134 +(S'x123' +p1135 +S' 0: x123' +p1136 +tp1137 +a(S'xx123' p1138 -S' 0: a' +S' 0: xx123' p1139 tp1140 -a(S'fthing' +a(S'123456' p1141 -S' 0: f' +S' 0: 123456' p1142 tp1143 a(S'*** Failers' p1144 -S' 0: *' +S'No match' p1145 tp1146 -a(S']thing' +a(S'123' p1147 S'No match' p1148 tp1149 -a(S'cthing' +a(S'x1234' p1150 -S'No match' +S' 0: x1234' p1151 tp1152 -a(S'dthing' -p1153 -S'No match' +aaa(lp1153 +S'^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$' p1154 -tp1155 -a(S'ething' +ag3 +a(lp1155 +(S'abc!pqr=apquxz.ixr.zzz.ac.uk' p1156 -S'No match' +S' 0: abc!pqr=apquxz.ixr.zzz.ac.uk' p1157 tp1158 -aaa(lp1159 -S'^\\\x81' +a(S'*** Failers' +p1159 +S'No match' p1160 -ag3 -a(lp1161 -(S'\x81' +tp1161 +a(S'!pqr=apquxz.ixr.zzz.ac.uk' p1162 -S' 0: \x81' +S'No match' p1163 tp1164 -aaa(lp1165 -S'^\xff' +a(S'abc!=apquxz.ixr.zzz.ac.uk' +p1165 +S'No match' p1166 -ag3 -a(lp1167 -(S'\xff' +tp1167 +a(S'abc!pqr=apquxz:ixr.zzz.ac.uk' p1168 -S' 0: \xff' +S'No match' p1169 tp1170 -aaa(lp1171 -S'^[0-9]+$' +a(S'abc!pqr=apquxz.ixr.zzz.ac.ukk' +p1171 +S'No match' p1172 -ag3 -a(lp1173 -(S'0' -p1174 -S' 0: 0' +tp1173 +aaa(lp1174 +S':' p1175 -tp1176 -a(S'1' +ag3 +a(lp1176 +(S'Well, we need a colon: somewhere' p1177 -S' 0: 1' +S' 0: :' p1178 tp1179 -a(S'2' +a(S"*** Fail if we don't" p1180 -S' 0: 2' +S'No match' p1181 tp1182 -a(S'3' -p1183 -S' 0: 3' +aaa(lp1183 +S'^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$' p1184 -tp1185 -a(S'4' +ag3 +a(lp1185 +(S'.1.2.3' p1186 -S' 0: 4' +S' 0: .1.2.3' p1187 tp1188 -a(S'5' +a(S'A.12.123.0' p1189 -S' 0: 5' +S' 0: A.12.123.0' p1190 tp1191 -a(S'6' +a(S'*** Failers' p1192 -S' 0: 6' +S'No match' p1193 tp1194 -a(S'7' +a(S'.1.2.3333' p1195 -S' 0: 7' +S'No match' p1196 tp1197 -a(S'8' +a(S'1.2.3' p1198 -S' 0: 8' +S'No match' p1199 tp1200 -a(S'9' +a(S'1234.2.3' p1201 -S' 0: 9' +S'No match' p1202 tp1203 -a(S'10' -p1204 -S' 0: 10' +aaa(lp1204 +S'^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$' p1205 -tp1206 -a(S'100' +ag3 +a(lp1206 +(S'1 IN SOA non-sp1 non-sp2(' p1207 -S' 0: 100' +S' 0: 1 IN SOA non-sp1 non-sp2(' p1208 tp1209 -a(S'*** Failers' +a(S'1 IN SOA non-sp1 non-sp2 (' p1210 -S'No match' +S' 0: 1 IN SOA non-sp1 non-sp2 (' p1211 tp1212 -a(S'abc' +a(S'*** Failers' p1213 S'No match' p1214 tp1215 -aaa(lp1216 -S'^.*nter' +a(S'1IN SOA non-sp1 non-sp2(' +p1216 +S'No match' p1217 -ag3 -a(lp1218 -(S'enter' -p1219 -S' 0: enter' +tp1218 +aaa(lp1219 +S'^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$' p1220 -tp1221 -a(S'inter' +ag3 +a(lp1221 +(S'a.' p1222 -S' 0: inter' +S' 0: a.' p1223 tp1224 -a(S'uponter' +a(S'Z.' p1225 -S' 0: uponter' +S' 0: Z.' p1226 tp1227 -aaa(lp1228 -S'^xxx[0-9]+$' +a(S'2.' +p1228 +S' 0: 2.' p1229 -ag3 -a(lp1230 -(S'xxx0' +tp1230 +a(S'ab-c.pq-r.' p1231 -S' 0: xxx0' +S' 0: ab-c.pq-r.' p1232 tp1233 -a(S'xxx1234' +a(S'sxk.zzz.ac.uk.' p1234 -S' 0: xxx1234' +S' 0: sxk.zzz.ac.uk.' p1235 tp1236 -a(S'*** Failers' +a(S'x-.y-.' p1237 -S'No match' +S' 0: x-.y-.' p1238 tp1239 -a(S'xxx' +a(S'*** Failers' p1240 S'No match' p1241 tp1242 -aaa(lp1243 -S'^.+[0-9][0-9][0-9]$' +a(S'-abc.peq.' +p1243 +S'No match' p1244 -ag3 -a(lp1245 -(S'x123' -p1246 -S' 0: x123' +tp1245 +aaa(lp1246 +S'^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$' p1247 -tp1248 -a(S'xx123' +ag3 +a(lp1248 +(S'*.a' p1249 -S' 0: xx123' +S' 0: *.a' p1250 tp1251 -a(S'123456' +a(S'*.b0-a' p1252 -S' 0: 123456' +S' 0: *.b0-a' p1253 tp1254 -a(S'*** Failers' +a(S'*.c3-b.c' p1255 -S'No match' +S' 0: *.c3-b.c' p1256 tp1257 -a(S'123' +a(S'*.c-a.b-c' p1258 -S'No match' +S' 0: *.c-a.b-c' p1259 tp1260 -a(S'x1234' +a(S'*** Failers' p1261 -S' 0: x1234' +S'No match' p1262 tp1263 -aaa(lp1264 -S'^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$' +a(S'*.0' +p1264 +S'No match' p1265 -ag3 -a(lp1266 -(S'abc!pqr=apquxz.ixr.zzz.ac.uk' +tp1266 +a(S'*.a-' p1267 -S' 0: abc!pqr=apquxz.ixr.zzz.ac.uk' +S'No match' p1268 tp1269 -a(S'*** Failers' +a(S'*.a-b.c-' p1270 S'No match' p1271 tp1272 -a(S'!pqr=apquxz.ixr.zzz.ac.uk' +a(S'*.c-a.0-c' p1273 S'No match' p1274 tp1275 -a(S'abc!=apquxz.ixr.zzz.ac.uk' -p1276 -S'No match' +aaa(lp1276 +S'^\\".*\\"\\s*(;.*)?$' p1277 -tp1278 -a(S'abc!pqr=apquxz:ixr.zzz.ac.uk' +ag3 +a(lp1278 +(S'"1234"' p1279 -S'No match' +S' 0: "1234"' p1280 tp1281 -a(S'abc!pqr=apquxz.ixr.zzz.ac.ukk' +a(S'"abcd" ;' p1282 -S'No match' +S' 0: "abcd" ;' p1283 tp1284 -aaa(lp1285 -S':' +a(S'"" ; rhubarb' +p1285 +S' 0: "" ; rhubarb' p1286 -ag3 -a(lp1287 -(S'Well, we need a colon: somewhere' +tp1287 +a(S'*** Failers' p1288 -S' 0: :' +S'No match' p1289 tp1290 -a(S"*** Fail if we don't" +a(S'"1234" : things' p1291 S'No match' p1292 tp1293 aaa(lp1294 -S'^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$' +S'^$' p1295 ag3 a(lp1296 -(S'.1.2.3' +(g3 +S' 0: ' p1297 -S' 0: .1.2.3' -p1298 -tp1299 -a(S'A.12.123.0' -p1300 -S' 0: A.12.123.0' -p1301 -tp1302 +tp1298 a(S'*** Failers' -p1303 +p1299 S'No match' -p1304 -tp1305 -a(S'.1.2.3333' +p1300 +tp1301 +aaa(lp1302 +S'^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$' +p1303 +ag3 +a(lp1304 +(S'abcdefhijklm' +p1305 +S' 0: abcdefhijklm' p1306 -S'No match' -p1307 -tp1308 -a(S'1.2.3' +tp1307 +aaa(lp1308 +S'^a*\\w' p1309 -S'No match' -p1310 -tp1311 -a(S'1234.2.3' -p1312 -S'No match' -p1313 -tp1314 -aaa(lp1315 -S'^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$' -p1316 ag3 -a(lp1317 -(S'1 IN SOA non-sp1 non-sp2(' -p1318 -S' 0: 1 IN SOA non-sp1 non-sp2(' -p1319 -tp1320 -a(S'1 IN SOA non-sp1 non-sp2 (' -p1321 -S' 0: 1 IN SOA non-sp1 non-sp2 (' -p1322 -tp1323 -a(S'*** Failers' -p1324 -S'No match' -p1325 -tp1326 -a(S'1IN SOA non-sp1 non-sp2(' -p1327 -S'No match' -p1328 -tp1329 -aaa(lp1330 -S'^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$' -p1331 -ag3 -a(lp1332 -(S'a.' -p1333 -S' 0: a.' -p1334 -tp1335 -a(S'Z.' -p1336 -S' 0: Z.' -p1337 -tp1338 -a(S'2.' -p1339 -S' 0: 2.' -p1340 -tp1341 -a(S'ab-c.pq-r.' -p1342 -S' 0: ab-c.pq-r.' -p1343 -tp1344 -a(S'sxk.zzz.ac.uk.' -p1345 -S' 0: sxk.zzz.ac.uk.' -p1346 -tp1347 -a(S'x-.y-.' -p1348 -S' 0: x-.y-.' -p1349 -tp1350 -a(S'*** Failers' -p1351 -S'No match' -p1352 -tp1353 -a(S'-abc.peq.' -p1354 -S'No match' -p1355 -tp1356 -aaa(lp1357 -S'^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$' -p1358 -ag3 -a(lp1359 -(S'*.a' -p1360 -S' 0: *.a' -p1361 -tp1362 -a(S'*.b0-a' -p1363 -S' 0: *.b0-a' -p1364 -tp1365 -a(S'*.c3-b.c' -p1366 -S' 0: *.c3-b.c' -p1367 -tp1368 -a(S'*.c-a.b-c' -p1369 -S' 0: *.c-a.b-c' -p1370 -tp1371 -a(S'*** Failers' -p1372 -S'No match' -p1373 -tp1374 -a(S'*.0' -p1375 -S'No match' -p1376 -tp1377 -a(S'*.a-' -p1378 -S'No match' -p1379 -tp1380 -a(S'*.a-b.c-' -p1381 -S'No match' -p1382 -tp1383 -a(S'*.c-a.0-c' -p1384 -S'No match' -p1385 -tp1386 -aaa(lp1387 -S'^\\".*\\"\\s*(;.*)?$' -p1388 -ag3 -a(lp1389 -(S'"1234"' -p1390 -S' 0: "1234"' -p1391 -tp1392 -a(S'"abcd" ;' -p1393 -S' 0: "abcd" ;' -p1394 -tp1395 -a(S'"" ; rhubarb' -p1396 -S' 0: "" ; rhubarb' -p1397 -tp1398 -a(S'*** Failers' -p1399 -S'No match' -p1400 -tp1401 -a(S'"1234" : things' -p1402 -S'No match' -p1403 -tp1404 -aaa(lp1405 -S'^$' -p1406 -ag3 -a(lp1407 -(g3 -S' 0: ' -p1408 -tp1409 -a(S'*** Failers' -p1410 -S'No match' -p1411 -tp1412 -aaa(lp1413 -S'^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$' -p1414 -ag3 -a(lp1415 -(S'abcdefhijklm' -p1416 -S' 0: abcdefhijklm' -p1417 -tp1418 -aaa(lp1419 -S'^[\\w][\\W][\\s][\\S][\\d][\\D][\\b][\\n][\\c]][\\022]' -p1420 -ag3 -a(lp1421 -(S'a+ Z0+\x08\n\x1d\x12' -p1422 -S' 0: a+ Z0+\x08\n\x1d\x12' -p1423 -tp1424 -aaa(lp1425 -S'^a*\\w' -p1426 -ag3 -a(lp1427 +a(lp1310 (S'z' -p1428 +p1311 S' 0: z' -p1429 -tp1430 +p1312 +tp1313 a(S'az' -p1431 +p1314 S' 0: az' -p1432 -tp1433 +p1315 +tp1316 a(S'aaaz' -p1434 +p1317 S' 0: aaaz' -p1435 -tp1436 +p1318 +tp1319 a(g41 S' 0: a' -p1437 -tp1438 +p1320 +tp1321 a(S'aa' -p1439 +p1322 S' 0: aa' -p1440 -tp1441 +p1323 +tp1324 a(S'aaaa' -p1442 +p1325 S' 0: aaaa' -p1443 -tp1444 +p1326 +tp1327 a(S'a+' -p1445 +p1328 S' 0: a' -p1446 -tp1447 +p1329 +tp1330 a(S'aa+' -p1448 +p1331 S' 0: aa' -p1449 -tp1450 -aaa(lp1451 +p1332 +tp1333 +aaa(lp1334 S'^a+\\w' -p1452 +p1335 ag3 -a(lp1453 +a(lp1336 (S'az' -p1454 +p1337 S' 0: az' -p1455 -tp1456 +p1338 +tp1339 a(S'aaaz' -p1457 +p1340 S' 0: aaaz' -p1458 -tp1459 +p1341 +tp1342 a(S'aa' -p1460 +p1343 S' 0: aa' -p1461 -tp1462 +p1344 +tp1345 a(S'aaaa' -p1463 +p1346 S' 0: aaaa' -p1464 -tp1465 +p1347 +tp1348 a(S'aa+' -p1466 +p1349 S' 0: aa' -p1467 -tp1468 -aaa(lp1469 +p1350 +tp1351 +aaa(lp1352 S'^\\d{8}\\w{2,}' -p1470 +p1353 ag3 -a(lp1471 +a(lp1354 (S'1234567890' -p1472 +p1355 S' 0: 1234567890' -p1473 -tp1474 +p1356 +tp1357 a(S'12345678ab' -p1475 +p1358 S' 0: 12345678ab' -p1476 -tp1477 +p1359 +tp1360 a(S'12345678__' -p1478 +p1361 S' 0: 12345678__' -p1479 -tp1480 +p1362 +tp1363 a(S'*** Failers' -p1481 +p1364 S'No match' -p1482 -tp1483 +p1365 +tp1366 a(S'1234567' -p1484 +p1367 S'No match' -p1485 -tp1486 -aaa(lp1487 +p1368 +tp1369 +aaa(lp1370 S'^[aeiou\\d]{4,5}$' -p1488 +p1371 ag3 -a(lp1489 +a(lp1372 (S'uoie' -p1490 +p1373 S' 0: uoie' -p1491 -tp1492 +p1374 +tp1375 a(S'1234' -p1493 +p1376 S' 0: 1234' -p1494 -tp1495 +p1377 +tp1378 a(S'12345' -p1496 +p1379 S' 0: 12345' -p1497 -tp1498 +p1380 +tp1381 a(S'aaaaa' -p1499 +p1382 S' 0: aaaaa' -p1500 -tp1501 +p1383 +tp1384 a(S'*** Failers' -p1502 +p1385 S'No match' -p1503 -tp1504 +p1386 +tp1387 a(S'123456' -p1505 +p1388 S'No match' -p1506 -tp1507 -aaa(lp1508 +p1389 +tp1390 +aaa(lp1391 S'^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]' -p1509 +p1392 ag3 -a(lp1510 +a(lp1393 (S'From abcd Mon Sep 01 12:33:02 1997' -p1511 +p1394 S' 0: From abcd Mon Sep 01 12:33' -p1512 -tp1513 -aaa(lp1514 +p1395 +tp1396 +aaa(lp1397 S'^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d' -p1515 +p1398 ag3 -a(lp1516 +a(lp1399 (S'From abcd Mon Sep 01 12:33:02 1997' -p1517 +p1400 S' 0: From abcd Mon Sep 01 12:33' -p1518 -tp1519 +p1401 +tp1402 a(S'From abcd Mon Sep 1 12:33:02 1997' -p1520 +p1403 S' 0: From abcd Mon Sep 1 12:33' -p1521 -tp1522 +p1404 +tp1405 a(S'*** Failers' -p1523 +p1406 S'No match' -p1524 -tp1525 +p1407 +tp1408 a(S'From abcd Sep 01 12:33:02 1997' -p1526 +p1409 S'No match' -p1527 -tp1528 -aaa(lp1529 +p1410 +tp1411 +aaa(lp1412 S'^[ab]{1,3}(ab*|b)' -p1530 +p1413 ag3 -a(lp1531 +a(lp1414 (S'aabbbbb' -p1532 +p1415 S' 0: aabbbbb' -p1533 -tp1534 -aaa(lp1535 +p1416 +tp1417 +aaa(lp1418 S'abc\\0def\\00pqr\\000xyz\\0000AB' -p1536 +p1419 ag3 -a(lp1537 +a(lp1420 (S'abc\x00def\x00pqr\x00xyz\x000AB' -p1538 +p1421 S' 0: abc\x00def\x00pqr\x00xyz\x000AB' -p1539 -tp1540 +p1422 +tp1423 a(S'abc456 abc\x00def\x00pqr\x00xyz\x000ABCDE' -p1541 +p1424 S' 0: abc\x00def\x00pqr\x00xyz\x000AB' -p1542 -tp1543 -aaa(lp1544 +p1425 +tp1426 +aaa(lp1427 S'abc\\x0def\\x00pqr\\x000xyz\\x0000AB' -p1545 +p1428 ag3 -a(lp1546 +a(lp1429 (S'abc\ref\x00pqr\x000xyz\x0000AB' -p1547 +p1430 S' 0: abc\ref\x00pqr\x000xyz\x0000AB' -p1548 -tp1549 +p1431 +tp1432 a(S'abc456 abc\ref\x00pqr\x000xyz\x0000ABCDE' -p1550 +p1433 S' 0: abc\ref\x00pqr\x000xyz\x0000AB' -p1551 -tp1552 -aaa(lp1553 +p1434 +tp1435 +aaa(lp1436 S'^[\\000-\\037]' -p1554 +p1437 ag3 -a(lp1555 +a(lp1438 (S'\x00A' -p1556 +p1439 S' 0: \x00' -p1557 -tp1558 +p1440 +tp1441 a(S'\x01B' -p1559 +p1442 S' 0: \x01' -p1560 -tp1561 +p1443 +tp1444 a(S'\x1fC' -p1562 +p1445 S' 0: \x1f' -p1563 -tp1564 -aaa(lp1565 +p1446 +tp1447 +aaa(lp1448 S'\\0*' -p1566 +p1449 ag3 -a(lp1567 +a(lp1450 (S'\x00\x00\x00\x00' -p1568 +p1451 S' 0: \x00\x00\x00\x00' -p1569 -tp1570 -aaa(lp1571 +p1452 +tp1453 +aaa(lp1454 S'A\\x00{2,3}Z' -p1572 +p1455 ag3 -a(lp1573 +a(lp1456 (S'The A\x00\x00Z' -p1574 +p1457 S' 0: A\x00\x00Z' -p1575 -tp1576 +p1458 +tp1459 a(S'An A\x00\x00\x00Z' -p1577 +p1460 S' 0: A\x00\x00\x00Z' -p1578 -tp1579 +p1461 +tp1462 a(S'*** Failers' -p1580 +p1463 S'No match' -p1581 -tp1582 +p1464 +tp1465 a(S'A\x00Z' -p1583 +p1466 S'No match' -p1584 -tp1585 +p1467 +tp1468 a(S'A\x00\x00\x00\x00Z' -p1586 +p1469 S'No match' -p1587 -tp1588 -aaa(lp1589 +p1470 +tp1471 +aaa(lp1472 S'^\\s' -p1590 +p1473 ag3 -a(lp1591 +a(lp1474 (S' abc' -p1592 +p1475 S' 0: ' -p1593 -tp1594 +p1476 +tp1477 a(S'\x0cabc' -p1595 +p1478 S' 0: \x0c' -p1596 -tp1597 +p1479 +tp1480 a(S'\nabc' -p1598 +p1481 S' 0: \n' -p1599 -tp1600 +p1482 +tp1483 a(S'\rabc' -p1601 +p1484 S' 0: \r' -p1602 -tp1603 +p1485 +tp1486 a(S'\tabc' -p1604 +p1487 S' 0: \t' -p1605 -tp1606 +p1488 +tp1489 a(S'*** Failers' -p1607 +p1490 S'No match' -p1608 -tp1609 +p1491 +tp1492 a(S'abc' -p1610 +p1493 S'No match' -p1611 -tp1612 -aaa(lp1613 +p1494 +tp1495 +aaa(lp1496 S'ab{1,3}bc' -p1614 +p1497 ag3 -a(lp1615 +a(lp1498 (S'abbbbc' -p1616 +p1499 S' 0: abbbbc' -p1617 -tp1618 +p1500 +tp1501 a(S'abbbc' -p1619 +p1502 S' 0: abbbc' -p1620 -tp1621 +p1503 +tp1504 a(S'abbc' -p1622 +p1505 S' 0: abbc' -p1623 -tp1624 +p1506 +tp1507 a(S'*** Failers' -p1625 +p1508 S'No match' -p1626 -tp1627 +p1509 +tp1510 a(S'abc' -p1628 +p1511 S'No match' -p1629 -tp1630 +p1512 +tp1513 a(S'abbbbbc' -p1631 +p1514 S'No match' -p1632 -tp1633 -aaa(lp1634 +p1515 +tp1516 +aaa(lp1517 S'([^.]*)\\.([^:]*):[T ]+(.*)' -p1635 +p1518 ag3 -a(lp1636 +a(lp1519 (S'track1.title:TBlah blah blah' -p1637 +p1520 S' 0: track1.title:TBlah blah blah' -p1638 -tp1639 -aaa(lp1640 +p1521 +tp1522 +aaa(lp1523 S'^[W-c]+$' -p1641 +p1524 ag3 -a(lp1642 +a(lp1525 (S'WXY_^abc' -p1643 +p1526 S' 0: WXY_^abc' -p1644 -tp1645 +p1527 +tp1528 a(S'*** Failers' -p1646 +p1529 S'No match' -p1647 -tp1648 +p1530 +tp1531 a(S'wxy' -p1649 +p1532 S'No match' -p1650 -tp1651 -aaa(lp1652 +p1533 +tp1534 +aaa(lp1535 S'^abc$' -p1653 +p1536 ag3 -a(lp1654 +a(lp1537 (S'abc' -p1655 +p1538 S' 0: abc' -p1656 -tp1657 +p1539 +tp1540 a(S'*** Failers' -p1658 +p1541 S'No match' -p1659 -tp1660 +p1542 +tp1543 a(S'qqq\nabc' -p1661 +p1544 S'No match' -p1662 -tp1663 +p1545 +tp1546 a(S'abc\nzzz' -p1664 +p1547 S'No match' -p1665 -tp1666 +p1548 +tp1549 a(S'qqq\nabc\nzzz' -p1667 +p1550 S'No match' -p1668 -tp1669 -aaa(lp1670 +p1551 +tp1552 +aaa(lp1553 S'[-az]+' -p1671 +p1554 ag3 -a(lp1672 +a(lp1555 (S'az-' -p1673 +p1556 S' 0: az-' -p1674 -tp1675 +p1557 +tp1558 a(S'*** Failers' -p1676 +p1559 S' 0: a' -p1677 -tp1678 +p1560 +tp1561 a(S'b' -p1679 +p1562 S'No match' -p1680 -tp1681 -aaa(lp1682 +p1563 +tp1564 +aaa(lp1565 S'[az-]+' -p1683 +p1566 ag3 -a(lp1684 +a(lp1567 (S'za-' -p1685 +p1568 S' 0: za-' -p1686 -tp1687 +p1569 +tp1570 a(S'*** Failers' -p1688 +p1571 S' 0: a' -p1689 -tp1690 -a(g1679 +p1572 +tp1573 +a(g1562 S'No match' -p1691 -tp1692 -aaa(lp1693 +p1574 +tp1575 +aaa(lp1576 S'[a\\-z]+' -p1694 +p1577 ag3 -a(lp1695 +a(lp1578 (S'a-z' -p1696 +p1579 S' 0: a-z' -p1697 -tp1698 +p1580 +tp1581 a(S'*** Failers' -p1699 +p1582 S' 0: a' -p1700 -tp1701 -a(g1679 +p1583 +tp1584 +a(g1562 S'No match' -p1702 -tp1703 -aaa(lp1704 +p1585 +tp1586 +aaa(lp1587 S'[a-z]+' -p1705 +p1588 ag3 -a(lp1706 +a(lp1589 (S'abcdxyz' -p1707 +p1590 S' 0: abcdxyz' -p1708 -tp1709 -aaa(lp1710 +p1591 +tp1592 +aaa(lp1593 S'[\\d-]+' -p1711 +p1594 ag3 -a(lp1712 +a(lp1595 (S'12-34' -p1713 +p1596 S' 0: 12-34' -p1714 -tp1715 +p1597 +tp1598 a(S'*** Failers' -p1716 +p1599 S'No match' -p1717 -tp1718 +p1600 +tp1601 a(S'aaa' -p1719 +p1602 S'No match' -p1720 -tp1721 -aaa(lp1722 +p1603 +tp1604 +aaa(lp1605 S'[\\d-z]+' -p1723 +p1606 ag3 -a(lp1724 +a(lp1607 (S'12-34z' -p1725 +p1608 S' 0: 12-34z' -p1726 -tp1727 +p1609 +tp1610 a(S'*** Failers' -p1728 +p1611 S'No match' -p1729 -tp1730 +p1612 +tp1613 a(S'aaa' -p1731 +p1614 S'No match' -p1732 -tp1733 -aaa(lp1734 +p1615 +tp1616 +aaa(lp1617 S'\\x5c' -p1735 +p1618 ag3 -a(lp1736 +a(lp1619 (S'\\' -p1737 +p1620 S' 0: \\' -p1738 -tp1739 -aaa(lp1740 +p1621 +tp1622 +aaa(lp1623 S'\\x20Z' -p1741 +p1624 ag3 -a(lp1742 +a(lp1625 (S'the Zoo' -p1743 +p1626 S' 0: Z' -p1744 -tp1745 +p1627 +tp1628 a(S'*** Failers' -p1746 +p1629 S'No match' -p1747 -tp1748 +p1630 +tp1631 a(S'Zulu' -p1749 +p1632 S'No match' -p1750 -tp1751 -aaa(lp1752 +p1633 +tp1634 +aaa(lp1635 S'ab{3cd' -p1753 +p1636 ag3 -a(lp1754 +a(lp1637 (S'ab{3cd' -p1755 +p1638 S' 0: ab{3cd' -p1756 -tp1757 -aaa(lp1758 +p1639 +tp1640 +aaa(lp1641 S'ab{3,cd' -p1759 +p1642 ag3 -a(lp1760 +a(lp1643 (S'ab{3,cd' -p1761 +p1644 S' 0: ab{3,cd' -p1762 -tp1763 -aaa(lp1764 +p1645 +tp1646 +aaa(lp1647 S'ab{3,4a}cd' -p1765 +p1648 ag3 -a(lp1766 +a(lp1649 (S'ab{3,4a}cd' -p1767 +p1650 S' 0: ab{3,4a}cd' -p1768 -tp1769 -aaa(lp1770 +p1651 +tp1652 +aaa(lp1653 S'{4,5a}bc' -p1771 +p1654 ag3 -a(lp1772 +a(lp1655 (S'{4,5a}bc' -p1773 +p1656 S' 0: {4,5a}bc' -p1774 -tp1775 -aaa(lp1776 +p1657 +tp1658 +aaa(lp1659 S'abc$' -p1777 +p1660 ag3 -a(lp1778 +a(lp1661 (S'abc' -p1779 +p1662 S' 0: abc' -p1780 -tp1781 +p1663 +tp1664 a(S'abc\n' -p1782 +p1665 S' 0: abc' -p1783 -tp1784 +p1666 +tp1667 a(S'*** Failers' -p1785 +p1668 S'No match' -p1786 -tp1787 +p1669 +tp1670 a(S'abc\ndef' -p1788 +p1671 S'No match' -p1789 -tp1790 -aaa(lp1791 +p1672 +tp1673 +aaa(lp1674 S'(abc)\\223' -p1792 +p1675 ag3 -a(lp1793 +a(lp1676 (S'abc\x93' -p1794 +p1677 S' 0: abc\x93' -p1795 -tp1796 -aaa(lp1797 +p1678 +tp1679 +aaa(lp1680 S'(abc)\\323' -p1798 +p1681 ag3 -a(lp1799 +a(lp1682 (S'abc\xd3' -p1800 +p1683 S' 0: abc\xd3' -p1801 -tp1802 -aaa(lp1803 -S'abc\\81' -p1804 -ag3 -a(lp1805 -(S'abc\x0081' -p1806 -S' 0: abc\x0081' -p1807 -tp1808 -a(S'abc\x0081' -p1809 -S' 0: abc\x0081' -p1810 -tp1811 -aaa(lp1812 -S'abc\\91' -p1813 -ag3 -a(lp1814 -(S'abc\x0091' -p1815 -S' 0: abc\x0091' -p1816 -tp1817 -a(S'abc\x0091' -p1818 -S' 0: abc\x0091' -p1819 -tp1820 -aaa(lp1821 +p1684 +tp1685 +aaa(lp1686 S'ab\\idef' -p1822 +p1687 ag3 -a(lp1823 +a(lp1688 (S'abidef' -p1824 +p1689 S' 0: abidef' -p1825 -tp1826 -aaa(lp1827 +p1690 +tp1691 +aaa(lp1692 S'a{0}bc' -p1828 +p1693 ag3 -a(lp1829 +a(lp1694 (S'bc' -p1830 +p1695 S' 0: bc' -p1831 -tp1832 -aaa(lp1833 +p1696 +tp1697 +aaa(lp1698 S'abc[\\10]de' -p1834 +p1699 ag3 -a(lp1835 +a(lp1700 (S'abc\x08de' -p1836 +p1701 S' 0: abc\x08de' -p1837 -tp1838 -aaa(lp1839 +p1702 +tp1703 +aaa(lp1704 S'abc[\\1]de' -p1840 +p1705 ag3 -a(lp1841 +a(lp1706 (S'abc\x01de' -p1842 +p1707 S' 0: abc\x01de' -p1843 -tp1844 -aaa(lp1845 -S'^([^a])([^\\b])([^c]*)([^d]{3,4})' -p1846 -ag3 -a(lp1847 -(S'baNOTccccd' -p1848 -S' 0: baNOTcccc' -p1849 -tp1850 -a(S'baNOTcccd' -p1851 -S' 0: baNOTccc' -p1852 -tp1853 -a(S'baNOTccd' -p1854 -S' 0: baNOTcc' -p1855 -tp1856 -a(S'bacccd' -p1857 -S' 0: baccc' -p1858 -tp1859 -a(S'*** Failers' -p1860 -S' 0: *** Failers' -p1861 -tp1862 -a(S'anything' -p1863 -S'No match' -p1864 -tp1865 -a(S'b\x08c' -p1866 -S'No match' -p1867 -tp1868 -a(S'baccd' -p1869 -S'No match' -p1870 -tp1871 -aaa(lp1872 +p1708 +tp1709 +aaa(lp1710 S'[^a]' -p1873 +p1711 ag3 -a(lp1874 +a(lp1712 (S'Abc' -p1875 +p1713 S' 0: A' -p1876 -tp1877 -aaa(lp1878 +p1714 +tp1715 +aaa(lp1716 S'[^a]+' -p1879 +p1717 ag3 -a(lp1880 +a(lp1718 (S'AAAaAbc' -p1881 +p1719 S' 0: AAA' -p1882 -tp1883 -aaa(lp1884 +p1720 +tp1721 +aaa(lp1722 S'[^a]+' -p1885 +p1723 ag3 -a(lp1886 +a(lp1724 (S'bbb\nccc' -p1887 +p1725 S' 0: bbb\nccc' -p1888 -tp1889 -aaa(lp1890 +p1726 +tp1727 +aaa(lp1728 S'[^k]$' -p1891 +p1729 ag3 -a(lp1892 +a(lp1730 (S'abc' -p1893 +p1731 S' 0: c' -p1894 -tp1895 +p1732 +tp1733 a(S'*** Failers' -p1896 +p1734 S' 0: s' -p1897 -tp1898 +p1735 +tp1736 a(S'abk' -p1899 +p1737 S'No match' -p1900 -tp1901 -aaa(lp1902 +p1738 +tp1739 +aaa(lp1740 S'[^k]{2,3}$' -p1903 +p1741 ag3 -a(lp1904 +a(lp1742 (S'abc' -p1905 +p1743 S' 0: abc' -p1906 -tp1907 +p1744 +tp1745 a(S'kbc' -p1908 +p1746 S' 0: bc' -p1909 -tp1910 +p1747 +tp1748 a(S'kabc' -p1911 +p1749 S' 0: abc' -p1912 -tp1913 +p1750 +tp1751 a(S'*** Failers' -p1914 +p1752 S' 0: ers' -p1915 -tp1916 +p1753 +tp1754 a(S'abk' -p1917 +p1755 S'No match' -p1918 -tp1919 +p1756 +tp1757 a(S'akb' -p1920 +p1758 S'No match' -p1921 -tp1922 +p1759 +tp1760 a(S'akk' -p1923 +p1761 S'No match' -p1924 -tp1925 -aaa(lp1926 +p1762 +tp1763 +aaa(lp1764 S'^\\d{8,}\\@.+[^k]$' -p1927 +p1765 ag3 -a(lp1928 +a(lp1766 (S'12345678 at a.b.c.d' -p1929 +p1767 S' 0: 12345678 at a.b.c.d' -p1930 -tp1931 +p1768 +tp1769 a(S'123456789 at x.y.z' -p1932 +p1770 S' 0: 123456789 at x.y.z' -p1933 -tp1934 +p1771 +tp1772 a(S'*** Failers' -p1935 +p1773 S'No match' -p1936 -tp1937 +p1774 +tp1775 a(S'12345678 at x.y.uk' -p1938 +p1776 S'No match' -p1939 -tp1940 +p1777 +tp1778 a(S'1234567 at a.b.c.d' -p1941 +p1779 S'No match' -p1942 -tp1943 -aaa(lp1944 +p1780 +tp1781 +aaa(lp1782 S'[^a]' -p1945 +p1783 ag3 -a(lp1946 +a(lp1784 (S'aaaabcd' -p1947 +p1785 S' 0: b' -p1948 -tp1949 +p1786 +tp1787 a(S'aaAabcd' -p1950 +p1788 S' 0: A' -p1951 -tp1952 -aaa(lp1953 +p1789 +tp1790 +aaa(lp1791 S'[^az]' -p1954 +p1792 ag3 -a(lp1955 +a(lp1793 (S'aaaabcd' -p1956 +p1794 S' 0: b' -p1957 -tp1958 +p1795 +tp1796 a(S'aaAabcd' -p1959 +p1797 S' 0: A' -p1960 -tp1961 -aaa(lp1962 +p1798 +tp1799 +aaa(lp1800 S'\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377' -p1963 +p1801 ag3 -a(lp1964 +a(lp1802 (S'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' -p1965 +p1803 S' 0: \x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' -p1966 -tp1967 -aaa(lp1968 +p1804 +tp1805 +aaa(lp1806 S'(\\.\\d\\d[1-9]?)\\d+' -p1969 +p1807 ag3 -a(lp1970 +a(lp1808 (S'1.230003938' -p1971 +p1809 S' 0: .230003938' -p1972 -tp1973 +p1810 +tp1811 a(S'1.875000282' -p1974 +p1812 S' 0: .875000282' -p1975 -tp1976 +p1813 +tp1814 a(S'1.235' -p1977 +p1815 S' 0: .235' -p1978 -tp1979 -aaa(lp1980 +p1816 +tp1817 +aaa(lp1818 S'foo(.*)bar' -p1981 +p1819 ag3 -a(lp1982 +a(lp1820 (S'The food is under the bar in the barn.' -p1983 +p1821 S' 0: food is under the bar in the bar' -p1984 -tp1985 -aaa(lp1986 +p1822 +tp1823 +aaa(lp1824 S'(.*)(\\d*)' -p1987 +p1825 ag3 -a(lp1988 +a(lp1826 (S'I have 2 numbers: 53147' -p1989 +p1827 S' 0: I have 2 numbers: 53147' -p1990 -tp1991 -aaa(lp1992 +p1828 +tp1829 +aaa(lp1830 S'(.*)(\\d+)' -p1993 +p1831 ag3 -a(lp1994 +a(lp1832 (S'I have 2 numbers: 53147' -p1995 +p1833 S' 0: I have 2 numbers: 53147' -p1996 -tp1997 -aaa(lp1998 +p1834 +tp1835 +aaa(lp1836 S'(.*)(\\d+)$' -p1999 -ag3 -a(lp2000 -(S'I have 2 numbers: 53147' -p2001 -S' 0: I have 2 numbers: 53147' -p2002 -tp2003 -aaa(lp2004 -S'(.*)\\b(\\d+)$' -p2005 +p1837 ag3 -a(lp2006 +a(lp1838 (S'I have 2 numbers: 53147' -p2007 +p1839 S' 0: I have 2 numbers: 53147' -p2008 -tp2009 -aaa(lp2010 +p1840 +tp1841 +aaa(lp1842 S'(.*\\D)(\\d+)$' -p2011 +p1843 ag3 -a(lp2012 +a(lp1844 (S'I have 2 numbers: 53147' -p2013 +p1845 S' 0: I have 2 numbers: 53147' -p2014 -tp2015 -aaa(lp2016 +p1846 +tp1847 +aaa(lp1848 S'^[W-]46]' -p2017 +p1849 ag3 -a(lp2018 +a(lp1850 (S'W46]789' -p2019 +p1851 S' 0: W46]' -p2020 -tp2021 +p1852 +tp1853 a(S'-46]789' -p2022 +p1854 S' 0: -46]' -p2023 -tp2024 +p1855 +tp1856 a(S'*** Failers' -p2025 +p1857 S'No match' -p2026 -tp2027 +p1858 +tp1859 a(S'Wall' -p2028 +p1860 S'No match' -p2029 -tp2030 +p1861 +tp1862 a(S'Zebra' -p2031 +p1863 S'No match' -p2032 -tp2033 +p1864 +tp1865 a(S'42' -p2034 +p1866 S'No match' -p2035 -tp2036 +p1867 +tp1868 a(S'[abcd]' -p2037 +p1869 S'No match' -p2038 -tp2039 +p1870 +tp1871 a(S']abcd[' -p2040 +p1872 S'No match' -p2041 -tp2042 -aaa(lp2043 +p1873 +tp1874 +aaa(lp1875 S'^[W-\\]46]' -p2044 +p1876 ag3 -a(lp2045 +a(lp1877 (S'W46]789' -p2046 +p1878 S' 0: W' -p2047 -tp2048 +p1879 +tp1880 a(S'Wall' -p2049 +p1881 S' 0: W' -p2050 -tp2051 +p1882 +tp1883 a(S'Zebra' -p2052 +p1884 S' 0: Z' -p2053 -tp2054 +p1885 +tp1886 a(S'Xylophone' -p2055 +p1887 S' 0: X' -p2056 -tp2057 +p1888 +tp1889 a(S'42' -p2058 +p1890 S' 0: 4' -p2059 -tp2060 +p1891 +tp1892 a(S'[abcd]' -p2061 +p1893 S' 0: [' -p2062 -tp2063 +p1894 +tp1895 a(S']abcd[' -p2064 +p1896 S' 0: ]' -p2065 -tp2066 +p1897 +tp1898 a(S'\\backslash' -p2067 +p1899 S' 0: \\' -p2068 -tp2069 +p1900 +tp1901 a(S'*** Failers' -p2070 +p1902 S'No match' -p2071 -tp2072 +p1903 +tp1904 a(S'-46]789' -p2073 +p1905 S'No match' -p2074 -tp2075 +p1906 +tp1907 a(S'well' -p2076 +p1908 S'No match' -p2077 -tp2078 -aaa(lp2079 +p1909 +tp1910 +aaa(lp1911 S'\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d' -p2080 +p1912 ag3 -a(lp2081 +a(lp1913 (S'01/01/2000' -p2082 +p1914 S' 0: 01/01/2000' -p2083 -tp2084 -aaa(lp2085 +p1915 +tp1916 +aaa(lp1917 S'^(a){0,0}' -p2086 +p1918 ag3 -a(lp2087 +a(lp1919 (S'bcd' -p2088 +p1920 S' 0: ' -p2089 -tp2090 +p1921 +tp1922 a(S'abc' -p2091 +p1923 S' 0: ' -p2092 -tp2093 +p1924 +tp1925 a(S'aab' -p2094 +p1926 S' 0: ' -p2095 -tp2096 -aaa(lp2097 +p1927 +tp1928 +aaa(lp1929 S'^(a){0,1}' -p2098 +p1930 ag3 -a(lp2099 +a(lp1931 (S'bcd' -p2100 +p1932 S' 0: ' -p2101 -tp2102 +p1933 +tp1934 a(S'abc' -p2103 +p1935 S' 0: a' -p2104 -tp2105 +p1936 +tp1937 a(S'aab' -p2106 +p1938 S' 0: a' -p2107 -tp2108 -aaa(lp2109 +p1939 +tp1940 +aaa(lp1941 S'^(a){0,2}' -p2110 +p1942 ag3 -a(lp2111 +a(lp1943 (S'bcd' -p2112 +p1944 S' 0: ' -p2113 -tp2114 +p1945 +tp1946 a(S'abc' -p2115 +p1947 S' 0: a' -p2116 -tp2117 +p1948 +tp1949 a(S'aab' -p2118 +p1950 S' 0: aa' -p2119 -tp2120 -aaa(lp2121 +p1951 +tp1952 +aaa(lp1953 S'^(a){0,3}' -p2122 +p1954 ag3 -a(lp2123 +a(lp1955 (S'bcd' -p2124 +p1956 S' 0: ' -p2125 -tp2126 +p1957 +tp1958 a(S'abc' -p2127 +p1959 S' 0: a' -p2128 -tp2129 +p1960 +tp1961 a(S'aab' -p2130 +p1962 S' 0: aa' -p2131 -tp2132 +p1963 +tp1964 a(S'aaa' -p2133 +p1965 S' 0: aaa' -p2134 -tp2135 -aaa(lp2136 +p1966 +tp1967 +aaa(lp1968 S'^(a){0,}' -p2137 +p1969 ag3 -a(lp2138 +a(lp1970 (S'bcd' -p2139 +p1971 S' 0: ' -p2140 -tp2141 +p1972 +tp1973 a(S'abc' -p2142 +p1974 S' 0: a' -p2143 -tp2144 +p1975 +tp1976 a(S'aab' -p2145 +p1977 S' 0: aa' -p2146 -tp2147 +p1978 +tp1979 a(S'aaa' -p2148 +p1980 S' 0: aaa' -p2149 -tp2150 +p1981 +tp1982 a(S'aaaaaaaa' -p2151 +p1983 S' 0: aaaaaaaa' -p2152 -tp2153 -aaa(lp2154 +p1984 +tp1985 +aaa(lp1986 S'^(a){1,1}' -p2155 +p1987 ag3 -a(lp2156 +a(lp1988 (S'bcd' -p2157 +p1989 S'No match' -p2158 -tp2159 +p1990 +tp1991 a(S'abc' -p2160 +p1992 S' 0: a' -p2161 -tp2162 +p1993 +tp1994 a(S'aab' -p2163 +p1995 S' 0: a' -p2164 -tp2165 -aaa(lp2166 +p1996 +tp1997 +aaa(lp1998 S'^(a){1,2}' -p2167 +p1999 ag3 -a(lp2168 +a(lp2000 (S'bcd' -p2169 +p2001 S'No match' -p2170 -tp2171 +p2002 +tp2003 a(S'abc' -p2172 +p2004 S' 0: a' -p2173 -tp2174 +p2005 +tp2006 a(S'aab' -p2175 +p2007 S' 0: aa' -p2176 -tp2177 -aaa(lp2178 +p2008 +tp2009 +aaa(lp2010 S'^(a){1,3}' -p2179 +p2011 ag3 -a(lp2180 +a(lp2012 (S'bcd' -p2181 +p2013 S'No match' -p2182 -tp2183 +p2014 +tp2015 a(S'abc' -p2184 +p2016 S' 0: a' -p2185 -tp2186 +p2017 +tp2018 a(S'aab' -p2187 +p2019 S' 0: aa' -p2188 -tp2189 +p2020 +tp2021 a(S'aaa' -p2190 +p2022 S' 0: aaa' -p2191 -tp2192 -aaa(lp2193 +p2023 +tp2024 +aaa(lp2025 S'^(a){1,}' -p2194 +p2026 ag3 -a(lp2195 +a(lp2027 (S'bcd' -p2196 +p2028 S'No match' -p2197 -tp2198 +p2029 +tp2030 a(S'abc' -p2199 +p2031 S' 0: a' -p2200 -tp2201 +p2032 +tp2033 a(S'aab' -p2202 +p2034 S' 0: aa' -p2203 -tp2204 +p2035 +tp2036 a(S'aaa' -p2205 +p2037 S' 0: aaa' -p2206 -tp2207 +p2038 +tp2039 a(S'aaaaaaaa' -p2208 +p2040 S' 0: aaaaaaaa' -p2209 -tp2210 -aaa(lp2211 +p2041 +tp2042 +aaa(lp2043 S'.*\\.gif' -p2212 +p2044 ag3 -a(lp2213 +a(lp2045 (S'borfle\nbib.gif\nno' -p2214 +p2046 S' 0: bib.gif' -p2215 -tp2216 -aaa(lp2217 +p2047 +tp2048 +aaa(lp2049 S'.{0,}\\.gif' -p2218 +p2050 ag3 -a(lp2219 +a(lp2051 (S'borfle\nbib.gif\nno' -p2220 +p2052 S' 0: bib.gif' -p2221 -tp2222 -aaa(lp2223 +p2053 +tp2054 +aaa(lp2055 S'.*$' -p2224 +p2056 ag3 -a(lp2225 +a(lp2057 (S'borfle\nbib.gif\nno' -p2226 +p2058 S' 0: no' -p2227 -tp2228 -aaa(lp2229 +p2059 +tp2060 +aaa(lp2061 S'.*$' -p2230 +p2062 ag3 -a(lp2231 +a(lp2063 (S'borfle\nbib.gif\nno\n' -p2232 +p2064 S' 0: no' -p2233 -tp2234 -aaa(lp2235 +p2065 +tp2066 +aaa(lp2067 S'^.*B' -p2236 +p2068 ag3 -a(lp2237 +a(lp2069 (S'**** Failers' -p2238 +p2070 S'No match' -p2239 -tp2240 +p2071 +tp2072 a(S'abc\nB' -p2241 +p2073 S'No match' -p2242 -tp2243 -aaa(lp2244 +p2074 +tp2075 +aaa(lp2076 S'^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' -p2245 +p2077 ag3 -a(lp2246 +a(lp2078 (S'123456654321' -p2247 +p2079 S' 0: 123456654321' -p2248 -tp2249 -aaa(lp2250 +p2080 +tp2081 +aaa(lp2082 S'^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d' -p2251 +p2083 ag3 -a(lp2252 +a(lp2084 (S'123456654321' -p2253 +p2085 S' 0: 123456654321' -p2254 -tp2255 -aaa(lp2256 +p2086 +tp2087 +aaa(lp2088 S'^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]' -p2257 +p2089 ag3 -a(lp2258 +a(lp2090 (S'123456654321' -p2259 +p2091 S' 0: 123456654321' -p2260 -tp2261 -aaa(lp2262 +p2092 +tp2093 +aaa(lp2094 S'^[abc]{12}' -p2263 +p2095 ag3 -a(lp2264 +a(lp2096 (S'abcabcabcabc' -p2265 +p2097 S' 0: abcabcabcabc' -p2266 -tp2267 -aaa(lp2268 +p2098 +tp2099 +aaa(lp2100 S'^[a-c]{12}' -p2269 +p2101 ag3 -a(lp2270 +a(lp2102 (S'abcabcabcabc' -p2271 +p2103 S' 0: abcabcabcabc' -p2272 -tp2273 -aaa(lp2274 +p2104 +tp2105 +aaa(lp2106 S'^(a|b|c){12}' -p2275 +p2107 ag3 -a(lp2276 +a(lp2108 (S'abcabcabcabc' -p2277 +p2109 S' 0: abcabcabcabc' -p2278 -tp2279 -aaa(lp2280 +p2110 +tp2111 +aaa(lp2112 S'^[abcdefghijklmnopqrstuvwxy0123456789]' -p2281 +p2113 ag3 -a(lp2282 +a(lp2114 (S'n' -p2283 +p2115 S' 0: n' -p2284 -tp2285 +p2116 +tp2117 a(S'*** Failers' -p2286 +p2118 S'No match' -p2287 -tp2288 -a(g1428 +p2119 +tp2120 +a(g1311 S'No match' -p2289 -tp2290 -aaa(lp2291 +p2121 +tp2122 +aaa(lp2123 S'abcde{0,0}' -p2292 +p2124 ag3 -a(lp2293 +a(lp2125 (S'abcd' -p2294 +p2126 S' 0: abcd' -p2295 -tp2296 +p2127 +tp2128 a(S'*** Failers' -p2297 +p2129 S'No match' -p2298 -tp2299 +p2130 +tp2131 a(S'abce' -p2300 +p2132 S'No match' -p2301 -tp2302 -aaa(lp2303 +p2133 +tp2134 +aaa(lp2135 S'ab[cd]{0,0}e' -p2304 +p2136 ag3 -a(lp2305 +a(lp2137 (S'abe' -p2306 +p2138 S' 0: abe' -p2307 -tp2308 +p2139 +tp2140 a(S'*** Failers' -p2309 +p2141 S'No match' -p2310 -tp2311 +p2142 +tp2143 a(S'abcde' -p2312 +p2144 S'No match' -p2313 -tp2314 -aaa(lp2315 +p2145 +tp2146 +aaa(lp2147 S'ab(c){0,0}d' -p2316 +p2148 ag3 -a(lp2317 +a(lp2149 (S'abd' -p2318 +p2150 S' 0: abd' -p2319 -tp2320 +p2151 +tp2152 a(S'*** Failers' -p2321 +p2153 S'No match' -p2322 -tp2323 +p2154 +tp2155 a(S'abcd' -p2324 +p2156 S'No match' -p2325 -tp2326 -aaa(lp2327 +p2157 +tp2158 +aaa(lp2159 S'a(b*)' -p2328 +p2160 ag3 -a(lp2329 +a(lp2161 (g41 S' 0: a' -p2330 -tp2331 +p2162 +tp2163 a(S'ab' -p2332 +p2164 S' 0: ab' -p2333 -tp2334 +p2165 +tp2166 a(S'abbbb' -p2335 +p2167 S' 0: abbbb' -p2336 -tp2337 +p2168 +tp2169 a(S'*** Failers' -p2338 +p2170 S' 0: a' -p2339 -tp2340 +p2171 +tp2172 a(S'bbbbb' -p2341 +p2173 S'No match' -p2342 -tp2343 -aaa(lp2344 +p2174 +tp2175 +aaa(lp2176 S'ab\\d{0}e' -p2345 +p2177 ag3 -a(lp2346 +a(lp2178 (S'abe' -p2347 +p2179 S' 0: abe' -p2348 -tp2349 +p2180 +tp2181 a(S'*** Failers' -p2350 +p2182 S'No match' -p2351 -tp2352 +p2183 +tp2184 a(S'ab1e' -p2353 +p2185 S'No match' -p2354 -tp2355 -aaa(lp2356 +p2186 +tp2187 +aaa(lp2188 S'"([^\\\\"]+|\\\\.)*"' -p2357 +p2189 ag3 -a(lp2358 +a(lp2190 (S'the "quick" brown fox' -p2359 +p2191 S' 0: "quick"' -p2360 -tp2361 +p2192 +tp2193 a(S'"the \\"quick\\" brown fox"' -p2362 +p2194 S' 0: "the \\"quick\\" brown fox"' -p2363 -tp2364 -aaa(lp2365 +p2195 +tp2196 +aaa(lp2197 S'a[^a]b' -p2366 +p2198 ag3 -a(lp2367 +a(lp2199 (S'acb' -p2368 +p2200 S' 0: acb' -p2369 -tp2370 +p2201 +tp2202 a(S'a\nb' -p2371 +p2203 S' 0: a\nb' -p2372 -tp2373 -aaa(lp2374 +p2204 +tp2205 +aaa(lp2206 S'a.b' -p2375 +p2207 ag3 -a(lp2376 +a(lp2208 (S'acb' -p2377 +p2209 S' 0: acb' -p2378 -tp2379 +p2210 +tp2211 a(S'*** Failers' -p2380 +p2212 S'No match' -p2381 -tp2382 +p2213 +tp2214 a(S'a\nb' -p2383 +p2215 S'No match' -p2384 -tp2385 -aaa(lp2386 +p2216 +tp2217 +aaa(lp2218 S'\\x00{ab}' -p2387 +p2219 ag3 -a(lp2388 +a(lp2220 (S'\x00{ab}' -p2389 +p2221 S' 0: \x00{ab}' -p2390 -tp2391 -aaa(lp2392 +p2222 +tp2223 +aaa(lp2224 S'(A|B)*CD' -p2393 +p2225 ag3 -a(lp2394 +a(lp2226 (S'CD' -p2395 +p2227 S' 0: CD' -p2396 -tp2397 -aaa(lp2398 +p2228 +tp2229 +aaa(lp2230 S'(\\d+)(\\w)' -p2399 +p2231 ag3 -a(lp2400 +a(lp2232 (S'12345a' -p2401 +p2233 S' 0: 12345a' -p2402 -tp2403 +p2234 +tp2235 a(S'12345+' -p2404 +p2236 S' 0: 12345' -p2405 -tp2406 -aaa(lp2407 +p2237 +tp2238 +aaa(lp2239 S'(a+|b+|c+)*c' -p2408 +p2240 ag3 -a(lp2409 +a(lp2241 (S'aaabbbbccccd' -p2410 +p2242 S' 0: aaabbbbcccc' -p2411 -tp2412 -aaa(lp2413 +p2243 +tp2244 +aaa(lp2245 S'(abc|)+' -p2414 +p2246 ag3 -a(lp2415 +a(lp2247 (S'abc' -p2416 +p2248 S' 0: abc' -p2417 -tp2418 +p2249 +tp2250 a(S'abcabc' -p2419 +p2251 S' 0: abcabc' -p2420 -tp2421 +p2252 +tp2253 a(S'abcabcabc' -p2422 +p2254 S' 0: abcabcabc' -p2423 -tp2424 +p2255 +tp2256 a(S'xyz' -p2425 +p2257 S' 0: ' -p2426 -tp2427 -aaa(lp2428 +p2258 +tp2259 +aaa(lp2260 S'([a]*)*' -p2429 +p2261 ag3 -a(lp2430 +a(lp2262 (g41 S' 0: a' -p2431 -tp2432 +p2263 +tp2264 a(S'aaaaa' -p2433 +p2265 S' 0: aaaaa' -p2434 -tp2435 -aaa(lp2436 +p2266 +tp2267 +aaa(lp2268 S'([ab]*)*' -p2437 +p2269 ag3 -a(lp2438 +a(lp2270 (g41 S' 0: a' -p2439 -tp2440 -a(g1679 +p2271 +tp2272 +a(g1562 S' 0: b' -p2441 -tp2442 +p2273 +tp2274 a(S'ababab' -p2443 +p2275 S' 0: ababab' -p2444 -tp2445 +p2276 +tp2277 a(S'aaaabcde' -p2446 +p2278 S' 0: aaaab' -p2447 -tp2448 +p2279 +tp2280 a(S'bbbb' -p2449 +p2281 S' 0: bbbb' -p2450 -tp2451 -aaa(lp2452 +p2282 +tp2283 +aaa(lp2284 S'([^a]*)*' -p2453 +p2285 ag3 -a(lp2454 -(g1679 +a(lp2286 +(g1562 S' 0: b' -p2455 -tp2456 +p2287 +tp2288 a(S'bbbb' -p2457 +p2289 S' 0: bbbb' -p2458 -tp2459 +p2290 +tp2291 a(S'aaa' -p2460 +p2292 S' 0: ' -p2461 -tp2462 -aaa(lp2463 +p2293 +tp2294 +aaa(lp2295 S'([^ab]*)*' -p2464 +p2296 ag3 -a(lp2465 +a(lp2297 (S'cccc' -p2466 +p2298 S' 0: cccc' -p2467 -tp2468 +p2299 +tp2300 a(S'abab' -p2469 +p2301 S' 0: ' -p2470 -tp2471 -aaa(lp2472 +p2302 +tp2303 +aaa(lp2304 S'The following tests are taken from the Perl 5.005 test suite; some of them' -p2473 +p2305 ag3 -a(lp2474 +a(lp2306 (S"/are compatible with 5.004, but I'd rather not have to sort them out./" -p2475 +p2307 S'No match' -p2476 -tp2477 -aaa(lp2478 +p2308 +tp2309 +aaa(lp2310 S'abc' -p2479 +p2311 ag3 -a(lp2480 +a(lp2312 (S'abc' -p2481 +p2313 S' 0: abc' -p2482 -tp2483 +p2314 +tp2315 a(S'xabcy' -p2484 +p2316 S' 0: abc' -p2485 -tp2486 +p2317 +tp2318 a(S'ababc' -p2487 +p2319 S' 0: abc' -p2488 -tp2489 +p2320 +tp2321 a(S'*** Failers' -p2490 +p2322 S'No match' -p2491 -tp2492 +p2323 +tp2324 a(S'xbc' -p2493 +p2325 S'No match' -p2494 -tp2495 +p2326 +tp2327 a(S'axc' -p2496 +p2328 S'No match' -p2497 -tp2498 +p2329 +tp2330 a(S'abx' -p2499 +p2331 S'No match' -p2500 -tp2501 -aaa(lp2502 +p2332 +tp2333 +aaa(lp2334 S'ab*c' -p2503 +p2335 ag3 -a(lp2504 +a(lp2336 (S'abc' -p2505 +p2337 S' 0: abc' -p2506 -tp2507 -aaa(lp2508 +p2338 +tp2339 +aaa(lp2340 S'ab*bc' -p2509 +p2341 ag3 -a(lp2510 +a(lp2342 (S'abc' -p2511 +p2343 S' 0: abc' -p2512 -tp2513 +p2344 +tp2345 a(S'abbc' -p2514 +p2346 S' 0: abbc' -p2515 -tp2516 +p2347 +tp2348 a(S'abbbbc' -p2517 +p2349 S' 0: abbbbc' -p2518 -tp2519 -aaa(lp2520 +p2350 +tp2351 +aaa(lp2352 S'.{1}' -p2521 +p2353 ag3 -a(lp2522 +a(lp2354 (S'abbbbc' -p2523 +p2355 S' 0: a' -p2524 -tp2525 -aaa(lp2526 +p2356 +tp2357 +aaa(lp2358 S'.{3,4}' -p2527 +p2359 ag3 -a(lp2528 +a(lp2360 (S'abbbbc' -p2529 +p2361 S' 0: abbb' -p2530 -tp2531 -aaa(lp2532 +p2362 +tp2363 +aaa(lp2364 S'ab{0,}bc' -p2533 +p2365 ag3 -a(lp2534 +a(lp2366 (S'abbbbc' -p2535 +p2367 S' 0: abbbbc' -p2536 -tp2537 -aaa(lp2538 +p2368 +tp2369 +aaa(lp2370 S'ab+bc' -p2539 +p2371 ag3 -a(lp2540 +a(lp2372 (S'abbc' -p2541 +p2373 S' 0: abbc' -p2542 -tp2543 +p2374 +tp2375 a(S'*** Failers' -p2544 +p2376 S'No match' -p2545 -tp2546 +p2377 +tp2378 a(S'abc' -p2547 +p2379 S'No match' -p2548 -tp2549 +p2380 +tp2381 a(S'abq' -p2550 +p2382 S'No match' -p2551 -tp2552 -aaa(lp2553 +p2383 +tp2384 +aaa(lp2385 S'ab{1,}bc' -p2554 +p2386 ag3 -a(lp2555 -aa(lp2556 +a(lp2387 +aa(lp2388 S'ab+bc' -p2557 +p2389 ag3 -a(lp2558 +a(lp2390 (S'abbbbc' -p2559 +p2391 S' 0: abbbbc' -p2560 -tp2561 -aaa(lp2562 +p2392 +tp2393 +aaa(lp2394 S'ab{1,}bc' -p2563 +p2395 ag3 -a(lp2564 +a(lp2396 (S'abbbbc' -p2565 +p2397 S' 0: abbbbc' -p2566 -tp2567 -aaa(lp2568 +p2398 +tp2399 +aaa(lp2400 S'ab{1,3}bc' -p2569 +p2401 ag3 -a(lp2570 +a(lp2402 (S'abbbbc' -p2571 +p2403 S' 0: abbbbc' -p2572 -tp2573 -aaa(lp2574 +p2404 +tp2405 +aaa(lp2406 S'ab{3,4}bc' -p2575 +p2407 ag3 -a(lp2576 +a(lp2408 (S'abbbbc' -p2577 +p2409 S' 0: abbbbc' -p2578 -tp2579 -aaa(lp2580 +p2410 +tp2411 +aaa(lp2412 S'ab{4,5}bc' -p2581 +p2413 ag3 -a(lp2582 +a(lp2414 (S'*** Failers' -p2583 +p2415 S'No match' -p2584 -tp2585 +p2416 +tp2417 a(S'abq' -p2586 +p2418 S'No match' -p2587 -tp2588 +p2419 +tp2420 a(S'abbbbc' -p2589 +p2421 S'No match' -p2590 -tp2591 -aaa(lp2592 +p2422 +tp2423 +aaa(lp2424 S'ab?bc' -p2593 +p2425 ag3 -a(lp2594 +a(lp2426 (S'abbc' -p2595 +p2427 S' 0: abbc' -p2596 -tp2597 +p2428 +tp2429 a(S'abc' -p2598 +p2430 S' 0: abc' -p2599 -tp2600 -aaa(lp2601 +p2431 +tp2432 +aaa(lp2433 S'ab{0,1}bc' -p2602 +p2434 ag3 -a(lp2603 +a(lp2435 (S'abc' -p2604 +p2436 S' 0: abc' -p2605 -tp2606 -aaa(lp2607 +p2437 +tp2438 +aaa(lp2439 S'ab?bc' -p2608 +p2440 ag3 -a(lp2609 -aa(lp2610 +a(lp2441 +aa(lp2442 S'ab?c' -p2611 +p2443 ag3 -a(lp2612 +a(lp2444 (S'abc' -p2613 +p2445 S' 0: abc' -p2614 -tp2615 -aaa(lp2616 +p2446 +tp2447 +aaa(lp2448 S'ab{0,1}c' -p2617 +p2449 ag3 -a(lp2618 +a(lp2450 (S'abc' -p2619 +p2451 S' 0: abc' -p2620 -tp2621 -aaa(lp2622 +p2452 +tp2453 +aaa(lp2454 S'^abc$' -p2623 +p2455 ag3 -a(lp2624 +a(lp2456 (S'abc' -p2625 +p2457 S' 0: abc' -p2626 -tp2627 +p2458 +tp2459 a(S'*** Failers' -p2628 +p2460 S'No match' -p2629 -tp2630 +p2461 +tp2462 a(S'abbbbc' -p2631 +p2463 S'No match' -p2632 -tp2633 +p2464 +tp2465 a(S'abcc' -p2634 +p2466 S'No match' -p2635 -tp2636 -aaa(lp2637 +p2467 +tp2468 +aaa(lp2469 S'^abc' -p2638 +p2470 ag3 -a(lp2639 +a(lp2471 (S'abcc' -p2640 -S' 0: abc' -p2641 -tp2642 -aaa(lp2643 +p2472 +S' 0: abc' +p2473 +tp2474 +aaa(lp2475 S'^abc$' -p2644 +p2476 ag3 -a(lp2645 -aa(lp2646 +a(lp2477 +aa(lp2478 S'abc$' -p2647 +p2479 ag3 -a(lp2648 +a(lp2480 (S'aabc' -p2649 +p2481 S' 0: abc' -p2650 -tp2651 +p2482 +tp2483 a(S'*** Failers' -p2652 +p2484 S'No match' -p2653 -tp2654 +p2485 +tp2486 a(S'aabc' -p2655 +p2487 S' 0: abc' -p2656 -tp2657 +p2488 +tp2489 a(S'aabcd' -p2658 +p2490 S'No match' -p2659 -tp2660 -aaa(lp2661 +p2491 +tp2492 +aaa(lp2493 S'^' -p2662 +p2494 ag3 -a(lp2663 +a(lp2495 (S'abc' -p2664 +p2496 S' 0: ' -p2665 -tp2666 -aaa(lp2667 +p2497 +tp2498 +aaa(lp2499 S'$' -p2668 +p2500 ag3 -a(lp2669 +a(lp2501 (S'abc' -p2670 +p2502 S' 0: ' -p2671 -tp2672 -aaa(lp2673 +p2503 +tp2504 +aaa(lp2505 S'a.c' -p2674 +p2506 ag3 -a(lp2675 +a(lp2507 (S'abc' -p2676 +p2508 S' 0: abc' -p2677 -tp2678 +p2509 +tp2510 a(S'axc' -p2679 +p2511 S' 0: axc' -p2680 -tp2681 -aaa(lp2682 +p2512 +tp2513 +aaa(lp2514 S'a.*c' -p2683 +p2515 ag3 -a(lp2684 +a(lp2516 (S'axyzc' -p2685 +p2517 S' 0: axyzc' -p2686 -tp2687 -aaa(lp2688 +p2518 +tp2519 +aaa(lp2520 S'a[bc]d' -p2689 +p2521 ag3 -a(lp2690 +a(lp2522 (S'abd' -p2691 +p2523 S' 0: abd' -p2692 -tp2693 +p2524 +tp2525 a(S'*** Failers' -p2694 +p2526 S'No match' -p2695 -tp2696 +p2527 +tp2528 a(S'axyzd' -p2697 +p2529 S'No match' -p2698 -tp2699 +p2530 +tp2531 a(S'abc' -p2700 +p2532 S'No match' -p2701 -tp2702 -aaa(lp2703 +p2533 +tp2534 +aaa(lp2535 S'a[b-d]e' -p2704 +p2536 ag3 -a(lp2705 +a(lp2537 (S'ace' -p2706 +p2538 S' 0: ace' -p2707 -tp2708 -aaa(lp2709 +p2539 +tp2540 +aaa(lp2541 S'a[b-d]' -p2710 +p2542 ag3 -a(lp2711 +a(lp2543 (S'aac' -p2712 +p2544 S' 0: ac' -p2713 -tp2714 -aaa(lp2715 +p2545 +tp2546 +aaa(lp2547 S'a[-b]' -p2716 +p2548 ag3 -a(lp2717 +a(lp2549 (S'a-' -p2718 +p2550 S' 0: a-' -p2719 -tp2720 -aaa(lp2721 +p2551 +tp2552 +aaa(lp2553 S'a[b-]' -p2722 +p2554 ag3 -a(lp2723 +a(lp2555 (S'a-' -p2724 +p2556 S' 0: a-' -p2725 -tp2726 -aaa(lp2727 +p2557 +tp2558 +aaa(lp2559 S'a]' -p2728 +p2560 ag3 -a(lp2729 +a(lp2561 (S'a]' -p2730 +p2562 S' 0: a]' -p2731 -tp2732 -aaa(lp2733 +p2563 +tp2564 +aaa(lp2565 S'a[]]b' -p2734 +p2566 ag3 -a(lp2735 +a(lp2567 (S'a]b' -p2736 +p2568 S' 0: a]b' -p2737 -tp2738 -aaa(lp2739 +p2569 +tp2570 +aaa(lp2571 S'a[^bc]d' -p2740 +p2572 ag3 -a(lp2741 +a(lp2573 (S'aed' -p2742 +p2574 S' 0: aed' -p2743 -tp2744 +p2575 +tp2576 a(S'*** Failers' -p2745 +p2577 S'No match' -p2746 -tp2747 +p2578 +tp2579 a(S'abd' -p2748 +p2580 S'No match' -p2749 -tp2750 +p2581 +tp2582 a(S'abd' -p2751 +p2583 S'No match' -p2752 -tp2753 -aaa(lp2754 +p2584 +tp2585 +aaa(lp2586 S'a[^-b]c' -p2755 +p2587 ag3 -a(lp2756 +a(lp2588 (S'adc' -p2757 +p2589 S' 0: adc' -p2758 -tp2759 -aaa(lp2760 +p2590 +tp2591 +aaa(lp2592 S'a[^]b]c' -p2761 +p2593 ag3 -a(lp2762 +a(lp2594 (S'adc' -p2763 +p2595 S' 0: adc' -p2764 -tp2765 +p2596 +tp2597 a(S'*** Failers' -p2766 +p2598 S'No match' -p2767 -tp2768 +p2599 +tp2600 a(S'a-c' -p2769 +p2601 S' 0: a-c' -p2770 -tp2771 +p2602 +tp2603 a(S'a]c' -p2772 -S'No match' -p2773 -tp2774 -aaa(lp2775 -S'\\ba\\b' -p2776 -ag3 -a(lp2777 -(S'a-' -p2778 -S' 0: a' -p2779 -tp2780 -a(S'-a' -p2781 -S' 0: a' -p2782 -tp2783 -a(S'-a-' -p2784 -S' 0: a' -p2785 -tp2786 -aaa(lp2787 -S'\\by\\b' -p2788 -ag3 -a(lp2789 -(S'*** Failers' -p2790 -S'No match' -p2791 -tp2792 -a(S'xy' -p2793 -S'No match' -p2794 -tp2795 -a(S'yz' -p2796 -S'No match' -p2797 -tp2798 -a(S'xyz' -p2799 -S'No match' -p2800 -tp2801 -aaa(lp2802 -S'\\Ba\\B' -p2803 -ag3 -a(lp2804 -(S'*** Failers' -p2805 -S' 0: a' -p2806 -tp2807 -a(S'a-' -p2808 -S'No match' -p2809 -tp2810 -a(S'-a' -p2811 -S'No match' -p2812 -tp2813 -a(S'-a-' -p2814 +p2604 S'No match' -p2815 -tp2816 -aaa(lp2817 -S'\\By\\b' -p2818 -ag3 -a(lp2819 -(S'xy' -p2820 -S' 0: y' -p2821 -tp2822 -aaa(lp2823 -S'\\by\\B' -p2824 -ag3 -a(lp2825 -(S'yz' -p2826 -S' 0: y' -p2827 -tp2828 -aaa(lp2829 -S'\\By\\B' -p2830 -ag3 -a(lp2831 -(S'xyz' -p2832 -S' 0: y' -p2833 -tp2834 -aaa(lp2835 +p2605 +tp2606 +aaa(lp2607 S'\\w' -p2836 +p2608 ag3 -a(lp2837 +a(lp2609 (g41 S' 0: a' -p2838 -tp2839 -aaa(lp2840 +p2610 +tp2611 +aaa(lp2612 S'\\W' -p2841 +p2613 ag3 -a(lp2842 +a(lp2614 (S'-' -p2843 +p2615 S' 0: -' -p2844 -tp2845 +p2616 +tp2617 a(S'*** Failers' -p2846 +p2618 S' 0: *' -p2847 -tp2848 -a(g2843 +p2619 +tp2620 +a(g2615 S' 0: -' -p2849 -tp2850 +p2621 +tp2622 a(g41 S'No match' -p2851 -tp2852 -aaa(lp2853 +p2623 +tp2624 +aaa(lp2625 S'a\\sb' -p2854 +p2626 ag3 -a(lp2855 +a(lp2627 (S'a b' -p2856 +p2628 S' 0: a b' -p2857 -tp2858 -aaa(lp2859 +p2629 +tp2630 +aaa(lp2631 S'a\\Sb' -p2860 +p2632 ag3 -a(lp2861 +a(lp2633 (S'a-b' -p2862 +p2634 S' 0: a-b' -p2863 -tp2864 +p2635 +tp2636 a(S'*** Failers' -p2865 +p2637 S'No match' -p2866 -tp2867 +p2638 +tp2639 a(S'a-b' -p2868 +p2640 S' 0: a-b' -p2869 -tp2870 +p2641 +tp2642 a(S'a b' -p2871 +p2643 S'No match' -p2872 -tp2873 -aaa(lp2874 +p2644 +tp2645 +aaa(lp2646 S'\\d' -p2875 +p2647 ag3 -a(lp2876 -(g1177 +a(lp2648 +(g1066 S' 0: 1' -p2877 -tp2878 -aaa(lp2879 +p2649 +tp2650 +aaa(lp2651 S'\\D' -p2880 +p2652 ag3 -a(lp2881 -(g2843 +a(lp2653 +(g2615 S' 0: -' -p2882 -tp2883 +p2654 +tp2655 a(S'*** Failers' -p2884 +p2656 S' 0: *' -p2885 -tp2886 -a(g2843 +p2657 +tp2658 +a(g2615 S' 0: -' -p2887 -tp2888 -a(g1177 +p2659 +tp2660 +a(g1066 S'No match' -p2889 -tp2890 -aaa(lp2891 +p2661 +tp2662 +aaa(lp2663 S'[\\w]' -p2892 +p2664 ag3 -a(lp2893 +a(lp2665 (g41 S' 0: a' -p2894 -tp2895 -aaa(lp2896 +p2666 +tp2667 +aaa(lp2668 S'[\\W]' -p2897 +p2669 ag3 -a(lp2898 -(g2843 +a(lp2670 +(g2615 S' 0: -' -p2899 -tp2900 +p2671 +tp2672 a(S'*** Failers' -p2901 +p2673 S' 0: *' -p2902 -tp2903 -a(g2843 +p2674 +tp2675 +a(g2615 S' 0: -' -p2904 -tp2905 +p2676 +tp2677 a(g41 S'No match' -p2906 -tp2907 -aaa(lp2908 +p2678 +tp2679 +aaa(lp2680 S'a[\\s]b' -p2909 +p2681 ag3 -a(lp2910 +a(lp2682 (S'a b' -p2911 +p2683 S' 0: a b' -p2912 -tp2913 -aaa(lp2914 +p2684 +tp2685 +aaa(lp2686 S'a[\\S]b' -p2915 +p2687 ag3 -a(lp2916 +a(lp2688 (S'a-b' -p2917 +p2689 S' 0: a-b' -p2918 -tp2919 +p2690 +tp2691 a(S'*** Failers' -p2920 +p2692 S'No match' -p2921 -tp2922 +p2693 +tp2694 a(S'a-b' -p2923 +p2695 S' 0: a-b' -p2924 -tp2925 +p2696 +tp2697 a(S'a b' -p2926 +p2698 S'No match' -p2927 -tp2928 -aaa(lp2929 +p2699 +tp2700 +aaa(lp2701 S'[\\d]' -p2930 +p2702 ag3 -a(lp2931 -(g1177 +a(lp2703 +(g1066 S' 0: 1' -p2932 -tp2933 -aaa(lp2934 +p2704 +tp2705 +aaa(lp2706 S'[\\D]' -p2935 +p2707 ag3 -a(lp2936 -(g2843 +a(lp2708 +(g2615 S' 0: -' -p2937 -tp2938 +p2709 +tp2710 a(S'*** Failers' -p2939 +p2711 S' 0: *' -p2940 -tp2941 -a(g2843 +p2712 +tp2713 +a(g2615 S' 0: -' -p2942 -tp2943 -a(g1177 +p2714 +tp2715 +a(g1066 S'No match' -p2944 -tp2945 -aaa(lp2946 +p2716 +tp2717 +aaa(lp2718 S'ab|cd' -p2947 +p2719 ag3 -a(lp2948 +a(lp2720 (S'abc' -p2949 +p2721 S' 0: ab' -p2950 -tp2951 +p2722 +tp2723 a(S'abcd' -p2952 +p2724 S' 0: ab' -p2953 -tp2954 -aaa(lp2955 +p2725 +tp2726 +aaa(lp2727 S'()ef' -p2956 +p2728 ag3 -a(lp2957 +a(lp2729 (S'def' -p2958 +p2730 S' 0: ef' -p2959 -tp2960 -aaa(lp2961 +p2731 +tp2732 +aaa(lp2733 S'$b' -p2962 +p2734 ag3 -a(lp2963 -aa(lp2964 +a(lp2735 +aa(lp2736 S'a\\(b' -p2965 +p2737 ag3 -a(lp2966 +a(lp2738 (S'a(b' -p2967 +p2739 S' 0: a(b' -p2968 -tp2969 -aaa(lp2970 +p2740 +tp2741 +aaa(lp2742 S'a\\(*b' -p2971 +p2743 ag3 -a(lp2972 +a(lp2744 (S'ab' -p2973 +p2745 S' 0: ab' -p2974 -tp2975 +p2746 +tp2747 a(S'a((b' -p2976 +p2748 S' 0: a((b' -p2977 -tp2978 -aaa(lp2979 +p2749 +tp2750 +aaa(lp2751 S'a\\\\b' -p2980 +p2752 ag3 -a(lp2981 -(S'a\x08' -p2982 -S'No match' -p2983 -tp2984 -aaa(lp2985 +a(lp2753 +aa(lp2754 S'((a))' -p2986 +p2755 ag3 -a(lp2987 +a(lp2756 (S'abc' -p2988 +p2757 S' 0: a' -p2989 -tp2990 -aaa(lp2991 +p2758 +tp2759 +aaa(lp2760 S'(a)b(c)' -p2992 +p2761 ag3 -a(lp2993 +a(lp2762 (S'abc' -p2994 +p2763 S' 0: abc' -p2995 -tp2996 -aaa(lp2997 +p2764 +tp2765 +aaa(lp2766 S'a+b+c' -p2998 +p2767 ag3 -a(lp2999 +a(lp2768 (S'aabbabc' -p3000 +p2769 S' 0: abc' -p3001 -tp3002 -aaa(lp3003 +p2770 +tp2771 +aaa(lp2772 S'a{1,}b{1,}c' -p3004 +p2773 ag3 -a(lp3005 +a(lp2774 (S'aabbabc' -p3006 +p2775 S' 0: abc' -p3007 -tp3008 -aaa(lp3009 +p2776 +tp2777 +aaa(lp2778 S'(a+|b)*' -p3010 +p2779 ag3 -a(lp3011 +a(lp2780 (S'ab' -p3012 +p2781 S' 0: ab' -p3013 -tp3014 -aaa(lp3015 +p2782 +tp2783 +aaa(lp2784 S'(a+|b){0,}' -p3016 +p2785 ag3 -a(lp3017 +a(lp2786 (S'ab' -p3018 +p2787 S' 0: ab' -p3019 -tp3020 -aaa(lp3021 +p2788 +tp2789 +aaa(lp2790 S'(a+|b)+' -p3022 +p2791 ag3 -a(lp3023 +a(lp2792 (S'ab' -p3024 +p2793 S' 0: ab' -p3025 -tp3026 -aaa(lp3027 +p2794 +tp2795 +aaa(lp2796 S'(a+|b){1,}' -p3028 +p2797 ag3 -a(lp3029 +a(lp2798 (S'ab' -p3030 +p2799 S' 0: ab' -p3031 -tp3032 -aaa(lp3033 +p2800 +tp2801 +aaa(lp2802 S'(a+|b)?' -p3034 +p2803 ag3 -a(lp3035 +a(lp2804 (S'ab' -p3036 +p2805 S' 0: a' -p3037 -tp3038 -aaa(lp3039 +p2806 +tp2807 +aaa(lp2808 S'(a+|b){0,1}' -p3040 +p2809 ag3 -a(lp3041 +a(lp2810 (S'ab' -p3042 +p2811 S' 0: a' -p3043 -tp3044 -aaa(lp3045 +p2812 +tp2813 +aaa(lp2814 S'[^ab]*' -p3046 +p2815 ag3 -a(lp3047 +a(lp2816 (S'cde' -p3048 +p2817 S' 0: cde' -p3049 -tp3050 -aaa(lp3051 +p2818 +tp2819 +aaa(lp2820 S'abc' -p3052 +p2821 ag3 -a(lp3053 +a(lp2822 (S'*** Failers' -p3054 +p2823 S'No match' -p3055 -tp3056 -a(g1679 +p2824 +tp2825 +a(g1562 S'No match' -p3057 -tp3058 -aaa(lp3059 +p2826 +tp2827 +aaa(lp2828 S'a*' -p3060 +p2829 ag3 -a(lp3061 -aa(lp3062 +a(lp2830 +aa(lp2831 S'([abc])*d' -p3063 +p2832 ag3 -a(lp3064 +a(lp2833 (S'abbbcd' -p3065 +p2834 S' 0: abbbcd' -p3066 -tp3067 -aaa(lp3068 +p2835 +tp2836 +aaa(lp2837 S'([abc])*bcd' -p3069 +p2838 ag3 -a(lp3070 +a(lp2839 (S'abcd' -p3071 +p2840 S' 0: abcd' -p3072 -tp3073 -aaa(lp3074 +p2841 +tp2842 +aaa(lp2843 S'a|b|c|d|e' -p3075 +p2844 ag3 -a(lp3076 +a(lp2845 (S'e' -p3077 +p2846 S' 0: e' -p3078 -tp3079 -aaa(lp3080 +p2847 +tp2848 +aaa(lp2849 S'(a|b|c|d|e)f' -p3081 +p2850 ag3 -a(lp3082 +a(lp2851 (S'ef' -p3083 +p2852 S' 0: ef' -p3084 -tp3085 -aaa(lp3086 +p2853 +tp2854 +aaa(lp2855 S'abcd*efg' -p3087 +p2856 ag3 -a(lp3088 +a(lp2857 (S'abcdefg' -p3089 +p2858 S' 0: abcdefg' -p3090 -tp3091 -aaa(lp3092 +p2859 +tp2860 +aaa(lp2861 S'ab*' -p3093 +p2862 ag3 -a(lp3094 +a(lp2863 (S'xabyabbbz' -p3095 +p2864 S' 0: ab' -p3096 -tp3097 +p2865 +tp2866 a(S'xayabbbz' -p3098 +p2867 S' 0: a' -p3099 -tp3100 -aaa(lp3101 +p2868 +tp2869 +aaa(lp2870 S'(ab|cd)e' -p3102 +p2871 ag3 -a(lp3103 +a(lp2872 (S'abcde' -p3104 +p2873 S' 0: cde' -p3105 -tp3106 -aaa(lp3107 +p2874 +tp2875 +aaa(lp2876 S'[abhgefdc]ij' -p3108 +p2877 ag3 -a(lp3109 +a(lp2878 (S'hij' -p3110 +p2879 S' 0: hij' -p3111 -tp3112 -aaa(lp3113 +p2880 +tp2881 +aaa(lp2882 S'^(ab|cd)e' -p3114 +p2883 ag3 -a(lp3115 -aa(lp3116 +a(lp2884 +aa(lp2885 S'(abc|)ef' -p3117 +p2886 ag3 -a(lp3118 +a(lp2887 (S'abcdef' -p3119 +p2888 S' 0: ef' -p3120 -tp3121 -aaa(lp3122 +p2889 +tp2890 +aaa(lp2891 S'(a|b)c*d' -p3123 +p2892 ag3 -a(lp3124 +a(lp2893 (S'abcd' -p3125 +p2894 S' 0: bcd' -p3126 -tp3127 -aaa(lp3128 +p2895 +tp2896 +aaa(lp2897 S'(ab|ab*)bc' -p3129 +p2898 ag3 -a(lp3130 +a(lp2899 (S'abc' -p3131 +p2900 S' 0: abc' -p3132 -tp3133 -aaa(lp3134 +p2901 +tp2902 +aaa(lp2903 S'a([bc]*)c*' -p3135 +p2904 ag3 -a(lp3136 +a(lp2905 (S'abc' -p3137 +p2906 S' 0: abc' -p3138 -tp3139 -aaa(lp3140 +p2907 +tp2908 +aaa(lp2909 S'a([bc]*)(c*d)' -p3141 +p2910 ag3 -a(lp3142 +a(lp2911 (S'abcd' -p3143 +p2912 S' 0: abcd' -p3144 -tp3145 -aaa(lp3146 +p2913 +tp2914 +aaa(lp2915 S'a([bc]+)(c*d)' -p3147 +p2916 ag3 -a(lp3148 +a(lp2917 (S'abcd' -p3149 +p2918 S' 0: abcd' -p3150 -tp3151 -aaa(lp3152 +p2919 +tp2920 +aaa(lp2921 S'a([bc]*)(c+d)' -p3153 +p2922 ag3 -a(lp3154 +a(lp2923 (S'abcd' -p3155 +p2924 S' 0: abcd' -p3156 -tp3157 -aaa(lp3158 +p2925 +tp2926 +aaa(lp2927 S'a[bcd]*dcdcde' -p3159 +p2928 ag3 -a(lp3160 +a(lp2929 (S'adcdcde' -p3161 +p2930 S' 0: adcdcde' -p3162 -tp3163 -aaa(lp3164 +p2931 +tp2932 +aaa(lp2933 S'a[bcd]+dcdcde' -p3165 +p2934 ag3 -a(lp3166 +a(lp2935 (S'*** Failers' -p3167 +p2936 S'No match' -p3168 -tp3169 +p2937 +tp2938 a(S'abcde' -p3170 +p2939 S'No match' -p3171 -tp3172 +p2940 +tp2941 a(S'adcdcde' -p3173 +p2942 S'No match' -p3174 -tp3175 -aaa(lp3176 +p2943 +tp2944 +aaa(lp2945 S'(ab|a)b*c' -p3177 +p2946 ag3 -a(lp3178 +a(lp2947 (S'abc' -p3179 +p2948 S' 0: abc' -p3180 -tp3181 -aaa(lp3182 +p2949 +tp2950 +aaa(lp2951 S'((a)(b)c)(d)' -p3183 +p2952 ag3 -a(lp3184 +a(lp2953 (S'abcd' -p3185 +p2954 S' 0: abcd' -p3186 -tp3187 -aaa(lp3188 +p2955 +tp2956 +aaa(lp2957 S'[a-zA-Z_][a-zA-Z0-9_]*' -p3189 +p2958 ag3 -a(lp3190 +a(lp2959 (S'alpha' -p3191 +p2960 S' 0: alpha' -p3192 -tp3193 -aaa(lp3194 +p2961 +tp2962 +aaa(lp2963 S'^a(bc+|b[eh])g|.h$' -p3195 +p2964 ag3 -a(lp3196 +a(lp2965 (S'abh' -p3197 +p2966 S' 0: bh' -p3198 -tp3199 -aaa(lp3200 +p2967 +tp2968 +aaa(lp2969 S'(bc+d$|ef*g.|h?i(j|k))' -p3201 +p2970 ag3 -a(lp3202 +a(lp2971 (S'effgz' -p3203 +p2972 S' 0: effgz' -p3204 -tp3205 +p2973 +tp2974 a(S'ij' -p3206 +p2975 S' 0: ij' -p3207 -tp3208 +p2976 +tp2977 a(S'reffgz' -p3209 +p2978 S' 0: effgz' -p3210 -tp3211 +p2979 +tp2980 a(S'*** Failers' -p3212 +p2981 S'No match' -p3213 -tp3214 +p2982 +tp2983 a(S'effg' -p3215 +p2984 S'No match' -p3216 -tp3217 +p2985 +tp2986 a(S'bcdd' -p3218 +p2987 S'No match' -p3219 -tp3220 -aaa(lp3221 +p2988 +tp2989 +aaa(lp2990 S'((((((((((a))))))))))' -p3222 +p2991 ag3 -a(lp3223 +a(lp2992 (g41 S' 0: a' -p3224 -tp3225 -aaa(lp3226 +p2993 +tp2994 +aaa(lp2995 S'(((((((((a)))))))))' -p3227 +p2996 ag3 -a(lp3228 +a(lp2997 (g41 S' 0: a' -p3229 -tp3230 -aaa(lp3231 +p2998 +tp2999 +aaa(lp3000 S'multiple words of text' -p3232 +p3001 ag3 -a(lp3233 +a(lp3002 (S'*** Failers' -p3234 +p3003 S'No match' -p3235 -tp3236 +p3004 +tp3005 a(S'aa' -p3237 +p3006 S'No match' -p3238 -tp3239 +p3007 +tp3008 a(S'uh-uh' -p3240 +p3009 S'No match' -p3241 -tp3242 -aaa(lp3243 +p3010 +tp3011 +aaa(lp3012 S'multiple words' -p3244 +p3013 ag3 -a(lp3245 +a(lp3014 (S'multiple words, yeah' -p3246 +p3015 S' 0: multiple words' -p3247 -tp3248 -aaa(lp3249 +p3016 +tp3017 +aaa(lp3018 S'(.*)c(.*)' -p3250 +p3019 ag3 -a(lp3251 +a(lp3020 (S'abcde' -p3252 +p3021 S' 0: abcde' -p3253 -tp3254 -aaa(lp3255 +p3022 +tp3023 +aaa(lp3024 S'\\((.*), (.*)\\)' -p3256 +p3025 ag3 -a(lp3257 +a(lp3026 (S'(a, b)' -p3258 +p3027 S' 0: (a, b)' -p3259 -tp3260 -aaa(lp3261 +p3028 +tp3029 +aaa(lp3030 S'[k]' -p3262 +p3031 ag3 -a(lp3263 -aa(lp3264 +a(lp3032 +aa(lp3033 S'abcd' -p3265 +p3034 ag3 -a(lp3266 +a(lp3035 (S'abcd' -p3267 +p3036 S' 0: abcd' -p3268 -tp3269 -aaa(lp3270 +p3037 +tp3038 +aaa(lp3039 S'a(bc)d' -p3271 +p3040 ag3 -a(lp3272 +a(lp3041 (S'abcd' -p3273 +p3042 S' 0: abcd' -p3274 -tp3275 -aaa(lp3276 +p3043 +tp3044 +aaa(lp3045 S'a[-]?c' -p3277 +p3046 ag3 -a(lp3278 +a(lp3047 (S'ac' -p3279 +p3048 S' 0: ac' -p3280 -tp3281 -aaa(lp3282 +p3049 +tp3050 +aaa(lp3051 S'((foo)|(bar))*' -p3283 +p3052 ag3 -a(lp3284 +a(lp3053 (S'foobar' -p3285 +p3054 S' 0: foobar' -p3286 -tp3287 -aaa(lp3288 +p3055 +tp3056 +aaa(lp3057 S'^(.+)?B' -p3289 +p3058 ag3 -a(lp3290 +a(lp3059 (S'AB' -p3291 +p3060 S' 0: AB' -p3292 -tp3293 -aaa(lp3294 +p3061 +tp3062 +aaa(lp3063 S'^([^a-z])|(\\^)$' -p3295 +p3064 ag3 -a(lp3296 +a(lp3065 (S'.' -p3297 +p3066 S' 0: .' -p3298 -tp3299 -aaa(lp3300 +p3067 +tp3068 +aaa(lp3069 S'^[<>]&' -p3301 +p3070 ag3 -a(lp3302 +a(lp3071 (S'<&OUT' -p3303 +p3072 S' 0: <&' -p3304 -tp3305 -aaa(lp3306 +p3073 +tp3074 +aaa(lp3075 S'^(){3,5}' -p3307 +p3076 ag3 -a(lp3308 +a(lp3077 (S'abc' -p3309 +p3078 S' 0: ' -p3310 -tp3311 -aaa(lp3312 +p3079 +tp3080 +aaa(lp3081 S'^(a+)*ax' -p3313 +p3082 ag3 -a(lp3314 +a(lp3083 (S'aax' -p3315 +p3084 S' 0: aax' -p3316 -tp3317 -aaa(lp3318 +p3085 +tp3086 +aaa(lp3087 S'^((a|b)+)*ax' -p3319 +p3088 ag3 -a(lp3320 +a(lp3089 (S'aax' -p3321 +p3090 S' 0: aax' -p3322 -tp3323 -aaa(lp3324 +p3091 +tp3092 +aaa(lp3093 S'^((a|bc)+)*ax' -p3325 +p3094 ag3 -a(lp3326 +a(lp3095 (S'aax' -p3327 +p3096 S' 0: aax' -p3328 -tp3329 -aaa(lp3330 +p3097 +tp3098 +aaa(lp3099 S'(a|x)*ab' -p3331 +p3100 ag3 -a(lp3332 +a(lp3101 (S'cab' -p3333 +p3102 S' 0: ab' -p3334 -tp3335 -aaa(lp3336 +p3103 +tp3104 +aaa(lp3105 S'(a)*ab' -p3337 +p3106 ag3 -a(lp3338 +a(lp3107 (S'cab' -p3339 +p3108 S' 0: ab' -p3340 -tp3341 -aaa(lp3342 +p3109 +tp3110 +aaa(lp3111 S'foo\\w*\\d{4}baz' -p3343 +p3112 ag3 -a(lp3344 +a(lp3113 (S'foobar1234baz' -p3345 +p3114 S' 0: foobar1234baz' -p3346 -tp3347 -aaa(lp3348 +p3115 +tp3116 +aaa(lp3117 S'^b' -p3349 +p3118 ag3 -a(lp3350 -aa(lp3351 +a(lp3119 +aa(lp3120 S'(\\w+:)+' -p3352 +p3121 ag3 -a(lp3353 +a(lp3122 (S'one:' -p3354 +p3123 S' 0: one:' -p3355 -tp3356 -aaa(lp3357 +p3124 +tp3125 +aaa(lp3126 S'([\\w:]+::)?(\\w+)$' -p3358 +p3127 ag3 -a(lp3359 +a(lp3128 (S'abcd' -p3360 +p3129 S' 0: abcd' -p3361 -tp3362 +p3130 +tp3131 a(S'xy:z:::abcd' -p3363 +p3132 S' 0: xy:z:::abcd' -p3364 -tp3365 -aaa(lp3366 +p3133 +tp3134 +aaa(lp3135 S'^[^bcd]*(c+)' -p3367 +p3136 ag3 -a(lp3368 +a(lp3137 (S'aexycd' -p3369 +p3138 S' 0: aexyc' -p3370 -tp3371 -aaa(lp3372 +p3139 +tp3140 +aaa(lp3141 S'(a*)b+' -p3373 +p3142 ag3 -a(lp3374 +a(lp3143 (S'caab' -p3375 +p3144 S' 0: aab' -p3376 -tp3377 -aaa(lp3378 +p3145 +tp3146 +aaa(lp3147 S'([\\w:]+::)?(\\w+)$' -p3379 +p3148 ag3 -a(lp3380 +a(lp3149 (S'abcd' -p3381 +p3150 S' 0: abcd' -p3382 -tp3383 +p3151 +tp3152 a(S'xy:z:::abcd' -p3384 +p3153 S' 0: xy:z:::abcd' -p3385 -tp3386 +p3154 +tp3155 a(S'*** Failers' -p3387 +p3156 S' 0: Failers' -p3388 -tp3389 +p3157 +tp3158 a(S'abcd:' -p3390 +p3159 S'No match' -p3391 -tp3392 +p3160 +tp3161 a(S'abcd:' -p3393 +p3162 S'No match' -p3394 -tp3395 -aaa(lp3396 +p3163 +tp3164 +aaa(lp3165 S'^[^bcd]*(c+)' -p3397 +p3166 ag3 -a(lp3398 +a(lp3167 (S'aexycd' -p3399 +p3168 S' 0: aexyc' -p3400 -tp3401 -aaa(lp3402 +p3169 +tp3170 +aaa(lp3171 S'(>a+)ab' -p3403 +p3172 ag3 -a(lp3404 -aa(lp3405 +a(lp3173 +aa(lp3174 S'([[:]+)' -p3406 +p3175 ag3 -a(lp3407 +a(lp3176 (S'a:[b]:' -p3408 +p3177 S' 0: :[' -p3409 -tp3410 -aaa(lp3411 +p3178 +tp3179 +aaa(lp3180 S'([[=]+)' -p3412 +p3181 ag3 -a(lp3413 +a(lp3182 (S'a=[b]=' -p3414 +p3183 S' 0: =[' -p3415 -tp3416 -aaa(lp3417 +p3184 +tp3185 +aaa(lp3186 S'([[.]+)' -p3418 +p3187 ag3 -a(lp3419 +a(lp3188 (S'a.[b].' -p3420 +p3189 S' 0: .[' -p3421 -tp3422 -aaa(lp3423 -S'a\\Z' -p3424 -ag3 -a(lp3425 -(S'*** Failers' -p3426 -S'No match' -p3427 -tp3428 -a(S'aaab' -p3429 -S'No match' -p3430 -tp3431 -a(S'a\nb\n' -p3432 -S'No match' -p3433 -tp3434 -aaa(lp3435 -S'b\\Z' -p3436 -ag3 -a(lp3437 -(S'a\nb\n' -p3438 -S' 0: b' -p3439 -tp3440 -aaa(lp3441 -S'b\\z' -p3442 -ag3 -a(lp3443 -aa(lp3444 -S'b\\Z' -p3445 -ag3 -a(lp3446 -(S'a\nb' -p3447 -S' 0: b' -p3448 -tp3449 -aaa(lp3450 -S'b\\z' -p3451 -ag3 -a(lp3452 -(S'a\nb' -p3453 -S' 0: b' -p3454 -tp3455 -a(S'*** Failers' -p3456 -S'No match' -p3457 -tp3458 -aaa(lp3459 +p3190 +tp3191 +aaa(lp3192 S'((Z)+|A)*' -p3460 +p3193 ag3 -a(lp3461 +a(lp3194 (S'ZABCDEFG' -p3462 +p3195 S' 0: ZA' -p3463 -tp3464 -aaa(lp3465 +p3196 +tp3197 +aaa(lp3198 S'(Z()|A)*' -p3466 +p3199 ag3 -a(lp3467 +a(lp3200 (S'ZABCDEFG' -p3468 +p3201 S' 0: ZA' -p3469 -tp3470 -aaa(lp3471 +p3202 +tp3203 +aaa(lp3204 S'(Z(())|A)*' -p3472 +p3205 ag3 -a(lp3473 +a(lp3206 (S'ZABCDEFG' -p3474 +p3207 S' 0: ZA' -p3475 -tp3476 -aaa(lp3477 +p3208 +tp3209 +aaa(lp3210 S'^[a-\\d]' -p3478 +p3211 ag3 -a(lp3479 +a(lp3212 (S'abcde' -p3480 +p3213 S' 0: a' -p3481 -tp3482 +p3214 +tp3215 a(S'-things' -p3483 +p3216 S' 0: -' -p3484 -tp3485 +p3217 +tp3218 a(S'0digit' -p3486 +p3219 S' 0: 0' -p3487 -tp3488 +p3220 +tp3221 a(S'*** Failers' -p3489 +p3222 S'No match' -p3490 -tp3491 +p3223 +tp3224 a(S'bcdef' -p3492 +p3225 S'No match' -p3493 -tp3494 -aaa(lp3495 +p3226 +tp3227 +aaa(lp3228 S'^[\\d-a]' -p3496 +p3229 ag3 -a(lp3497 +a(lp3230 (S'abcde' -p3498 +p3231 S' 0: a' -p3499 -tp3500 +p3232 +tp3233 a(S'-things' -p3501 +p3234 S' 0: -' -p3502 -tp3503 +p3235 +tp3236 a(S'0digit' -p3504 +p3237 S' 0: 0' -p3505 -tp3506 +p3238 +tp3239 a(S'*** Failers' -p3507 +p3240 S'No match' -p3508 -tp3509 +p3241 +tp3242 a(S'bcdef' -p3510 +p3243 S'No match' -p3511 -tp3512 -aaa(lp3513 -S'[[:space:]]+' -p3514 -ag3 -a(lp3515 -(S'> \t\n\x0c\r\x0b<' -p3516 -S' 0: \t\n\x0c\r\x0b' -p3517 -tp3518 -aaa(lp3519 -S'[[:blank:]]+' -p3520 -ag3 -a(lp3521 -(S'> \t\n\x0c\r\x0b<' -p3522 -S' 0: \t' -p3523 -tp3524 -aaa(lp3525 +p3244 +tp3245 +aaa(lp3246 S'[\\s]+' -p3526 +p3247 ag3 -a(lp3527 +a(lp3248 (S'> \t\n\x0c\r\x0b<' -p3528 +p3249 S' 0: \t\n\x0c\r' -p3529 -tp3530 -aaa(lp3531 +p3250 +tp3251 +aaa(lp3252 S'\\s+' -p3532 +p3253 ag3 -a(lp3533 +a(lp3254 (S'> \t\n\x0c\r\x0b<' -p3534 +p3255 S' 0: \t\n\x0c\r' -p3535 -tp3536 -aaa(lp3537 -S'\\Gabc' -p3538 -ag3 -a(lp3539 -(S'abc' -p3540 -S' 0: abc' -p3541 -tp3542 -a(S'*** Failers' -p3543 -S'No match' -p3544 -tp3545 -a(S'xyzabc' -p3546 -S'No match' -p3547 -tp3548 -aaa(lp3549 -S'[\\z\\C]' -p3550 -ag3 -a(lp3551 -(g1428 -S' 0: z' -p3552 -tp3553 -a(S'C' -p3554 -S' 0: C' -p3555 -tp3556 -aaa(lp3557 +p3256 +tp3257 +aaa(lp3258 S'\\M' -p3558 +p3259 ag3 -a(lp3559 +a(lp3260 (S'M' -p3560 +p3261 S' 0: M' -p3561 -tp3562 -aaa(lp3563 +p3262 +tp3263 +aaa(lp3264 S'(a+)*b' -p3564 +p3265 ag3 -a(lp3565 +a(lp3266 (S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -p3566 +p3267 S'No match' -p3567 -tp3568 -aaa(lp3569 +p3268 +tp3269 +aaa(lp3270 S'\xc5\xe6\xe5\xe4[\xe0-\xff\xc0-\xdf]+' -p3570 +p3271 ag3 -a(lp3571 +a(lp3272 (S'\xc5\xe6\xe5\xe4\xe0' -p3572 +p3273 S' 0: \xc5\xe6\xe5\xe4\xe0' -p3573 -tp3574 +p3274 +tp3275 a(S'\xc5\xe6\xe5\xe4\xff' -p3575 +p3276 S' 0: \xc5\xe6\xe5\xe4\xff' -p3576 -tp3577 +p3277 +tp3278 a(S'\xc5\xe6\xe5\xe4\xc0' -p3578 +p3279 S' 0: \xc5\xe6\xe5\xe4\xc0' -p3579 -tp3580 +p3280 +tp3281 a(S'\xc5\xe6\xe5\xe4\xdf' -p3581 +p3282 S' 0: \xc5\xe6\xe5\xe4\xdf' -p3582 -tp3583 -aaa(lp3584 +p3283 +tp3284 +aaa(lp3285 S'line\\nbreak' -p3585 +p3286 ag3 -a(lp3586 +a(lp3287 (S'this is a line\nbreak' -p3587 +p3288 S' 0: line\nbreak' -p3588 -tp3589 +p3289 +tp3290 a(S'line one\nthis is a line\nbreak in the second line' -p3590 +p3291 S' 0: line\nbreak' -p3591 -tp3592 -aaa(lp3593 +p3292 +tp3293 +aaa(lp3294 S'1234' -p3594 +p3295 ag3 -a(lp3595 -(S'123P' -p3596 -S'No match' -p3597 -tp3598 -aaa(lp3599 +a(lp3296 +aa(lp3297 S'1234' -p3600 +p3298 ag3 -a(lp3601 -(S'123P' -p3602 -S' 0: 4' -p3603 -tp3604 -aaa(lp3605 +a(lp3299 +aa(lp3300 S'Content-Type\\x3A[^\\r\\n]{6,}' -p3606 +p3301 ag3 -a(lp3607 +a(lp3302 (S'Content-Type:xxxxxyyy' -p3608 +p3303 S' 0: Content-Type:xxxxxyyy' -p3609 -tp3610 -aaa(lp3611 +p3304 +tp3305 +aaa(lp3306 S'Content-Type\\x3A[^\\r\\n]{6,}z' -p3612 +p3307 ag3 -a(lp3613 +a(lp3308 (S'Content-Type:xxxxxyyyz' -p3614 +p3309 S' 0: Content-Type:xxxxxyyyz' -p3615 -tp3616 -aaa(lp3617 +p3310 +tp3311 +aaa(lp3312 S'Content-Type\\x3A[^a]{6,}' -p3618 +p3313 ag3 -a(lp3619 +a(lp3314 (S'Content-Type:xxxyyy' -p3620 +p3315 S' 0: Content-Type:xxxyyy' -p3621 -tp3622 -aaa(lp3623 +p3316 +tp3317 +aaa(lp3318 S'Content-Type\\x3A[^a]{6,}z' -p3624 +p3319 ag3 -a(lp3625 +a(lp3320 (S'Content-Type:xxxyyyz' -p3626 +p3321 S' 0: Content-Type:xxxyyyz' -p3627 -tp3628 -aaa(lp3629 +p3322 +tp3323 +aaa(lp3324 S'^\\w+=.*(\\\\\\n.*)*' -p3630 +p3325 ag3 -a(lp3631 +a(lp3326 (S'abc=xyz\\\npqr' -p3632 +p3327 S' 0: abc=xyz\\\npqr' -p3633 -tp3634 -aaa(lp3635 +p3328 +tp3329 +aaa(lp3330 S'^(a()*)*' -p3636 +p3331 ag3 -a(lp3637 +a(lp3332 (S'aaaa' -p3638 +p3333 S' 0: aaaa' -p3639 -tp3640 -aaa(lp3641 +p3334 +tp3335 +aaa(lp3336 S'^(a()+)+' -p3642 +p3337 ag3 -a(lp3643 +a(lp3338 (S'aaaa' -p3644 +p3339 S' 0: aaaa' -p3645 -tp3646 -aaa(lp3647 +p3340 +tp3341 +aaa(lp3342 S'(a|)*\\d' -p3648 +p3343 ag3 -a(lp3649 +a(lp3344 (S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -p3650 +p3345 S'No match' -p3651 -tp3652 +p3346 +tp3347 a(S'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4' -p3653 +p3348 S' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4' -p3654 -tp3655 -aaa(lp3656 +p3349 +tp3350 +aaa(lp3351 S'.+foo' -p3657 +p3352 ag3 -a(lp3658 +a(lp3353 (S'afoo' -p3659 +p3354 S' 0: afoo' -p3660 -tp3661 +p3355 +tp3356 a(S'** Failers' -p3662 +p3357 S'No match' -p3663 -tp3664 +p3358 +tp3359 a(S'\r\nfoo' -p3665 +p3360 S'No match' -p3666 -tp3667 +p3361 +tp3362 a(S'\nfoo' -p3668 -S'No match' -p3669 -tp3670 -aaa(lp3671 -S'\\H\\h\\V\\v' -p3672 -ag3 -a(lp3673 -(S'X X\n' -p3674 -S' 0: X X\n' -p3675 -tp3676 -a(S'X\tX\x0b' -p3677 -S' 0: X\tX\x0b' -p3678 -tp3679 -a(S'** Failers' -p3680 -S'No match' -p3681 -tp3682 -a(S'\xa0 X\n' -p3683 -S'No match' -p3684 -tp3685 -aaa(lp3686 -S'\\H{3,4}' -p3687 -ag3 -a(lp3688 -(S'XY ABCDE' -p3689 -S' 0: ABCD' -p3690 -tp3691 -a(S'XY PQR ST' -p3692 -S' 0: PQR' -p3693 -tp3694 -aaa(lp3695 -S'.\\h{3,4}.' -p3696 -ag3 -a(lp3697 -(S'XY AB PQRS' -p3698 -S' 0: B P' -p3699 -tp3700 -aaa(lp3701 -S'\\h*X\\h?\\H+Y\\H?Z' -p3702 -ag3 -a(lp3703 -(S'>XNNNYZ' -p3704 -S' 0: XNNNYZ' -p3705 -tp3706 -a(S'> X NYQZ' -p3707 -S' 0: X NYQZ' -p3708 -tp3709 -a(S'** Failers' -p3710 +p3363 S'No match' -p3711 -tp3712 -a(S'>XYZ' -p3713 -S'No match' -p3714 -tp3715 -a(S'> X NY Z' -p3716 -S'No match' -p3717 -tp3718 -aaa(lp3719 -S'\\v*X\\v?Y\\v+Z\\V*\\x0a\\V+\\x0b\\V{2,3}\\x0c' -p3720 -ag3 -a(lp3721 -(S'>XY\nZ\nA\x0bNN\x0c' -p3722 -S' 0: XY\nZ\nA\x0bNN\x0c' -p3723 -tp3724 -a(S'>\n\rX\nY\n\x0bZZZ\nAAA\x0bNNN\x0c' -p3725 -S' 0: \n\rX\nY\n\x0bZZZ\nAAA\x0bNNN\x0c' -p3726 -tp3727 -aaa(lp3728 +p3364 +tp3365 +aaa(lp3366 S' End of testinput7 ' -p3729 +p3367 ag3 -a(lp3730 +a(lp3368 aa. \ No newline at end of file From niko at codespeak.net Fri Apr 4 13:18:59 2008 From: niko at codespeak.net (niko at codespeak.net) Date: Fri, 4 Apr 2008 13:18:59 +0200 (CEST) Subject: [pypy-svn] r53327 - in pypy/branch/fixed-list-ootype-2/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator/cli translator/cli/src translator/cli/test translator/js translator/jvm translator/jvm/src/pypy translator/jvm/test translator/oosupport Message-ID: <20080404111859.D0FF016A7EF@codespeak.net> Author: niko Date: Fri Apr 4 13:18:57 2008 New Revision: 53327 Added: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/VoidArray.java - copied unchanged from r53282, pypy/branch/fixed-list-ootype/pypy/translator/jvm/src/pypy/VoidArray.java Modified: pypy/branch/fixed-list-ootype-2/pypy/annotation/builtin.py pypy/branch/fixed-list-ootype-2/pypy/rpython/llinterp.py pypy/branch/fixed-list-ootype-2/pypy/rpython/lltypesystem/lloperation.py pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/ootype.py pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rdict.py pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rlist.py pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rstr.py pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rtuple.py pypy/branch/fixed-list-ootype-2/pypy/rpython/test/test_rlist.py pypy/branch/fixed-list-ootype-2/pypy/rpython/test/tool.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/constant.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/cts.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/entrypoint.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/gencli.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/ilgenerator.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/metavm.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/oopspec.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/opcodes.py pypy/branch/fixed-list-ootype-2/pypy/translator/cli/src/pypylib.cs pypy/branch/fixed-list-ootype-2/pypy/translator/cli/test/test_list.py pypy/branch/fixed-list-ootype-2/pypy/translator/js/asmgen.py pypy/branch/fixed-list-ootype-2/pypy/translator/js/database.py pypy/branch/fixed-list-ootype-2/pypy/translator/js/function.py pypy/branch/fixed-list-ootype-2/pypy/translator/js/jsbuiltin.py pypy/branch/fixed-list-ootype-2/pypy/translator/js/jts.py pypy/branch/fixed-list-ootype-2/pypy/translator/js/opcodes.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/builtin.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/cmpopcodes.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/constant.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/database.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/generator.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/metavm.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/methods.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/node.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/opcodes.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/prebuiltnodes.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/PyPy.java pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_class.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_list.py pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/typesystem.py pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/constant.py pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/genoo.py pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/metavm.py Log: merge the fixed-list-ootype branch onto this branch (svn merge -r 50568:HEAD https://codespeak.net/svn/pypy/branch/fixed-list-ootype/pypy pypy) Modified: pypy/branch/fixed-list-ootype-2/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/annotation/builtin.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/annotation/builtin.py Fri Apr 4 13:18:57 2008 @@ -516,6 +516,10 @@ r = SomeOOInstance(ootype.typeOf(i)) return r +def oonewarray(s_type, length): + assert s_type.is_constant() + return SomeOOInstance(s_type.const) + def null(I_OR_SM): assert I_OR_SM.is_constant() null = ootype.null(I_OR_SM.const) @@ -563,6 +567,7 @@ BUILTIN_ANALYZERS[ootype.instanceof] = instanceof BUILTIN_ANALYZERS[ootype.new] = new +BUILTIN_ANALYZERS[ootype.oonewarray] = oonewarray BUILTIN_ANALYZERS[ootype.null] = null BUILTIN_ANALYZERS[ootype.runtimenew] = runtimenew BUILTIN_ANALYZERS[ootype.classof] = classof Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/llinterp.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/llinterp.py Fri Apr 4 13:18:57 2008 @@ -1035,6 +1035,11 @@ def op_new(self, INST): assert isinstance(INST, (ootype.Instance, ootype.BuiltinType)) return ootype.new(INST) + + def op_oonewarray(self, ARRAY, length): + assert isinstance(ARRAY, ootype.Array) + assert isinstance(length, int) + return ootype.oonewarray(ARRAY, length) def op_runtimenew(self, class_): return ootype.runtimenew(class_) Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/lltypesystem/lloperation.py Fri Apr 4 13:18:57 2008 @@ -465,6 +465,7 @@ 'new': LLOp(oo=True, canraise=(Exception,)), 'runtimenew': LLOp(oo=True, canraise=(Exception,)), 'oonewcustomdict': LLOp(oo=True, canraise=(Exception,)), + 'oonewarray': LLOp(oo=True, canraise=(Exception,)), 'oosetfield': LLOp(oo=True), 'oogetfield': LLOp(oo=True, sideeffects=False), 'oosend': LLOp(oo=True, canraise=(Exception,)), Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/ootype.py Fri Apr 4 13:18:57 2008 @@ -364,7 +364,7 @@ "ll_upper": Meth([], self.SELFTYPE_T), "ll_lower": Meth([], self.SELFTYPE_T), "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count) - "ll_split_chr": Meth([self.CHAR], List(self.SELFTYPE_T)), + "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)), "ll_contains": Meth([self.CHAR], Bool), "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T), }) @@ -464,7 +464,7 @@ ITEMTYPE_T = object() def __init__(self, ITEMTYPE=None): - self._ITEMTYPE = ITEMTYPE + self.ITEM = ITEMTYPE self._null = _null_list(self) if ITEMTYPE is not None: self._init_methods() @@ -475,13 +475,9 @@ # 'ITEMTYPE_T' is used as a placeholder for indicating # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self' - # XXX clean-up later! Rename _ITEMTYPE to ITEM. For now they are - # just synonyms, please use ITEM in new code. - self.ITEM = self._ITEMTYPE - generic_types = { self.SELFTYPE_T: self, - self.ITEMTYPE_T: self._ITEMTYPE, + self.ITEMTYPE_T: self.ITEM, } # the methods are named after the ADT methods of lltypesystem's lists @@ -514,7 +510,7 @@ return True if not isinstance(other, List): return False - if self._ITEMTYPE is None or other._ITEMTYPE is None: + if self.ITEM is None or other.ITEM is None: raise TypeError("Can't compare uninitialized List type.") return BuiltinADTType.__eq__(self, other) @@ -522,28 +518,114 @@ return not (self == other) def __hash__(self): - if self._ITEMTYPE is None: + if self.ITEM is None: raise TypeError("Can't hash uninitialized List type.") return BuiltinADTType.__hash__(self) def __str__(self): return '%s(%s)' % (self.__class__.__name__, - saferecursive(str, "...")(self._ITEMTYPE)) + saferecursive(str, "...")(self.ITEM)) def _get_interp_class(self): return _list def _specialize(self, generic_types): - ITEMTYPE = self._specialize_type(self._ITEMTYPE, generic_types) + ITEMTYPE = self._specialize_type(self.ITEM, generic_types) return self.__class__(ITEMTYPE) def _defl(self): return self._null def _set_itemtype(self, ITEMTYPE): - self._ITEMTYPE = ITEMTYPE + self.ITEM = ITEMTYPE self._init_methods() + def ll_convert_from_array(self, array): + length = array.ll_length() + result = self.ll_newlist(length) + for n in range(length): + result.ll_setitem_fast(n, array.ll_getitem_fast(n)) + return result + +class Array(BuiltinADTType): + # placeholders for types + # make sure that each derived class has his own SELFTYPE_T + # placeholder, because we want backends to distinguish that. + + SELFTYPE_T = object() + ITEMTYPE_T = object() + + def __init__(self, ITEMTYPE=None): + self.ITEM = ITEMTYPE + self._null = _null_array(self) + if ITEMTYPE is not None: + self._init_methods() + + def _init_methods(self): + # This defines the abstract list interface that backends will + # have to map to their native list implementations. + # 'ITEMTYPE_T' is used as a placeholder for indicating + # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self' + + generic_types = { + self.SELFTYPE_T: self, + self.ITEMTYPE_T: self.ITEM, + } + + # the methods are named after the ADT methods of lltypesystem's lists + self._GENERIC_METHODS = frozendict({ + # "name": Meth([ARGUMENT1_TYPE, ARGUMENT2_TYPE, ...], RESULT_TYPE) + "ll_length": Meth([], Signed), + "ll_getitem_fast": Meth([Signed], self.ITEMTYPE_T), + "ll_setitem_fast": Meth([Signed, self.ITEMTYPE_T], Void), + }) + + self._setup_methods(generic_types) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, Array): + return False + if self.ITEM is None or other.ITEM is None: + raise TypeError("Can't compare uninitialized List type.") + return BuiltinADTType.__eq__(self, other) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + if self.ITEM is None: + raise TypeError("Can't hash uninitialized List type.") + return BuiltinADTType.__hash__(self) + + def __str__(self): + return '%s(%s)' % (self.__class__.__name__, + saferecursive(str, "...")(self.ITEM)) + + def _get_interp_class(self): + return _array + + def _specialize(self, generic_types): + ITEMTYPE = self._specialize_type(self.ITEM, generic_types) + return self.__class__(ITEMTYPE) + + def _defl(self): + return self._null + + def _example(self): + return oonewarray(self, 1) + + def _set_itemtype(self, ITEMTYPE): + self.ITEM = ITEMTYPE + self._init_methods() + + def ll_newlist(self, length): + from pypy.rpython.ootypesystem import rlist + return rlist.ll_newarray(self, length) + + def ll_convert_from_array(self, array): + return array class Dict(BuiltinADTType): # placeholders for types @@ -1201,8 +1283,9 @@ def ll_split_chr(self, ch): # NOT_RPYTHON - res = _list(List(self._TYPE)) - res._list = [self.make_string(s) for s in self._str.split(ch)] + l = [self.make_string(s) for s in self._str.split(ch)] + res = _array(Array(self._TYPE), len(l)) + res._array[:] = l return res def ll_contains(self, ch): @@ -1278,6 +1361,8 @@ def __init__(self, WEAK_REFERENCE): self.__dict__["_TYPE"] = WEAK_REFERENCE + + class _list(_builtin_type): def __init__(self, LIST): self._TYPE = LIST @@ -1295,7 +1380,7 @@ # NOT_RPYTHON if len(self._list) < length: diff = length - len(self._list) - self._list += [self._TYPE._ITEMTYPE._defl()] * diff + self._list += [self._TYPE.ITEM._defl()] * diff assert len(self._list) >= length def _ll_resize_le(self, length): @@ -1320,7 +1405,7 @@ def ll_setitem_fast(self, index, item): # NOT_RPYTHON - assert self._TYPE._ITEMTYPE is Void or typeOf(item) == self._TYPE._ITEMTYPE + assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM assert typeOf(index) == Signed assert index >= 0 self._list[index] = item @@ -1330,6 +1415,33 @@ def __init__(self, LIST): self.__dict__["_TYPE"] = LIST +class _array(_builtin_type): + def __init__(self, ARRAY, length): + self._TYPE = ARRAY + self._array = [ARRAY.ITEM._defl()] * length + + def ll_length(self): + # NOT_RPYTHON + return len(self._array) + + def ll_getitem_fast(self, index): + # NOT_RPYTHON + assert typeOf(index) == Signed + assert index >= 0 + return self._array[index] + + def ll_setitem_fast(self, index, item): + # NOT_RPYTHON + assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM + assert typeOf(index) == Signed + assert index >= 0 + self._array[index] = item + +class _null_array(_null_mixin(_array), _array): + + def __init__(self, ARRAY): + self.__dict__["_TYPE"] = ARRAY + class _dict(_builtin_type): def __init__(self, DICT): self._TYPE = DICT @@ -1497,10 +1609,15 @@ return TYPE._get_interp_class()(TYPE) def oonewcustomdict(DICT, ll_eq, ll_hash): + """NOT_RPYTHON""" d = new(DICT) d.ll_set_functions(ll_eq, ll_hash) return d +def oonewarray(ARRAY, length): + """NOT_RPYTHON""" + return _array(ARRAY, length) + def runtimenew(class_): assert isinstance(class_, _class) assert class_ is not nullruntimeclass @@ -1626,7 +1743,7 @@ return LIST._set_itemtype(ITEMTYPE) def hasItemType(LIST): - return LIST._ITEMTYPE is not None + return LIST.ITEM is not None def setDictTypes(DICT, KEYTYPE, VALUETYPE): return DICT._set_types(KEYTYPE, VALUETYPE) Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rbuiltin.py Fri Apr 4 13:18:57 2008 @@ -12,6 +12,13 @@ return hop.genop('new', vlist, resulttype = hop.r_result.lowleveltype) +def rtype_oonewarray(hop): + assert hop.args_s[0].is_constant() + vlist = hop.inputarg(ootype.Void, arg=0) + vlength = hop.inputarg(ootype.Signed, arg=1) + return hop.genop('oonewarray', [vlist, vlength], + resulttype = hop.r_result.lowleveltype) + def rtype_null(hop): assert hop.args_s[0].is_constant() TYPE = hop.args_s[0].const @@ -105,6 +112,7 @@ BUILTIN_TYPER = {} BUILTIN_TYPER[ootype.new] = rtype_new +BUILTIN_TYPER[ootype.oonewarray] = rtype_oonewarray BUILTIN_TYPER[ootype.null] = rtype_null BUILTIN_TYPER[ootype.classof] = rtype_classof BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rdict.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rdict.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rdict.py Fri Apr 4 13:18:57 2008 @@ -323,7 +323,7 @@ def ll_dict_kvi(d, LIST, func): length = d.ll_length() - result = ll_newlist(LIST, length) + result = LIST.ll_newlist(length) it = d.ll_get_items_iterator() i = 0 while it.ll_go_next(): @@ -332,7 +332,7 @@ elif func is dum_values: result.ll_setitem_fast(i, it.ll_current_value()) if func is dum_items: - r = ootype.new(LIST._ITEMTYPE) + r = ootype.new(LIST.ITEM) r.item0 = it.ll_current_key() # TODO: do we need casting? r.item1 = it.ll_current_value() result.ll_setitem_fast(i, r) Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rlist.py Fri Apr 4 13:18:57 2008 @@ -1,6 +1,6 @@ from pypy.tool.pairtype import pairtype from pypy.rpython.rlist import AbstractBaseListRepr, AbstractListRepr, \ - AbstractListIteratorRepr, rtype_newlist, rtype_alloc_and_set + AbstractListIteratorRepr, AbstractFixedSizeListRepr, rtype_newlist, rtype_alloc_and_set from pypy.rpython.rmodel import Repr, IntegerRepr from pypy.rpython.rmodel import inputconst, externalvsinternal from pypy.rpython.lltypesystem.lltype import Signed, Void @@ -21,15 +21,12 @@ else: self.external_item_repr, self.item_repr = \ externalvsinternal(rtyper, item_repr) - self.LIST = ootype.List() + self.LIST = self._make_empty_type() self.lowleveltype = self.LIST self.listitem = listitem self.list_cache = {} # setup() needs to be called to finish this initialization - def _externalvsinternal(self, rtyper, item_repr): - return item_repr, item_repr - def _setup_repr(self): if 'item_repr' not in self.__dict__: self.external_item_repr, self.item_repr = \ @@ -37,13 +34,9 @@ if not ootype.hasItemType(self.lowleveltype): ootype.setItemType(self.lowleveltype, self.item_repr.lowleveltype) - def null_const(self): - return self.LIST._null - - def prepare_const(self, n): - result = self.LIST.ll_newlist(n) - return result - + def _externalvsinternal(self, rtyper, item_repr): + return item_repr, item_repr + def send_message(self, hop, message, can_raise=False, v_args=None): if v_args is None: v_args = hop.inputargs(self, *hop.args_r[1:]) @@ -56,9 +49,6 @@ def get_eqfunc(self): return inputconst(Void, self.item_repr.get_ll_eq_function()) - def make_iterator_repr(self): - return ListIteratorRepr(self) - def rtype_hint(self, hop): hints = hop.args_s[-1].const if 'maxlength' in hints: @@ -71,10 +61,26 @@ class ListRepr(AbstractListRepr, BaseListRepr): + def null_const(self): + return self.LIST._null + + def prepare_const(self, n): + result = self.LIST.ll_newlist(n) + return result + + def make_iterator_repr(self): + return ListIteratorRepr(self) - pass + def _make_empty_type(self): + return ootype.List() -FixedSizeListRepr = ListRepr + def _generate_newlist(self, llops, items_v, v_sizehint): + c_list = inputconst(ootype.Void, self.lowleveltype) + v_result = llops.genop("new", [c_list], resulttype=self.lowleveltype) + c_resize = inputconst(ootype.Void, "_ll_resize") + c_length = inputconst(ootype.Signed, len(items_v)) + llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void) + return v_result class __extend__(pairtype(BaseListRepr, BaseListRepr)): @@ -87,11 +93,7 @@ def newlist(llops, r_list, items_v, v_sizehint=None): # XXX do something about v_sizehint - c_list = inputconst(ootype.Void, r_list.lowleveltype) - v_result = llops.genop("new", [c_list], resulttype=r_list.lowleveltype) - c_resize = inputconst(ootype.Void, "_ll_resize") - c_length = inputconst(ootype.Signed, len(items_v)) - llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void) + v_result = r_list._generate_newlist(llops, items_v, v_sizehint) c_setitem = inputconst(ootype.Void, "ll_setitem_fast") for i, v_item in enumerate(items_v): @@ -104,6 +106,31 @@ lst._ll_resize(length) return lst +# Fixed-size list +class FixedSizeListRepr(AbstractFixedSizeListRepr, BaseListRepr): + def compact_repr(self): + return 'FixedSizeListR %s' % (self.item_repr.compact_repr(),) + + def _make_empty_type(self): + return ootype.Array() + + def null_const(self): + return self.LIST._null + + def prepare_const(self, n): + return ll_newarray(self.LIST, n) + + def make_iterator_repr(self): + return ListIteratorRepr(self) + + def _generate_newlist(self, llops, items_v, v_sizehint): + c_array = inputconst(ootype.Void, self.lowleveltype) + c_length = inputconst(ootype.Signed, len(items_v)) + v_result = llops.genop("oonewarray", [c_array, c_length], resulttype=self.lowleveltype) + return v_result + +def ll_newarray(ARRAY, length): + return ootype.oonewarray(ARRAY, length) # ____________________________________________________________ # Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rstr.py Fri Apr 4 13:18:57 2008 @@ -170,7 +170,7 @@ return buf.ll_build() def ll_join_chars(length_dummy, lst): - if typeOf(lst)._ITEMTYPE == Char: + if typeOf(lst).ITEM == Char: buf = ootype.new(ootype.StringBuilder) else: buf = ootype.new(ootype.UnicodeBuilder) @@ -183,7 +183,7 @@ return buf.ll_build() def ll_join_strs(length_dummy, lst): - if typeOf(lst)._ITEMTYPE == ootype.String: + if typeOf(lst).ITEM == ootype.String: buf = ootype.new(ootype.StringBuilder) else: buf = ootype.new(ootype.UnicodeBuilder) @@ -209,8 +209,8 @@ def ll_stringslice_minusone(s): return s.ll_substring(0, s.ll_strlen()-1) - def ll_split_chr(LIST, s, c): - return s.ll_split_chr(c) + def ll_split_chr(RESULT, s, c): + return RESULT.ll_convert_from_array(s.ll_split_chr(c)) def ll_int(s, base): if not 2 <= base <= 36: Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/ootypesystem/rtuple.py Fri Apr 4 13:18:57 2008 @@ -36,13 +36,19 @@ def rtype_bltn_list(self, hop): from pypy.rpython.ootypesystem import rlist v_tup = hop.inputarg(self, 0) - LIST = hop.r_result.lowleveltype - c_list = inputconst(ootype.Void, LIST) - v_list = hop.genop('new', [c_list], resulttype=LIST) - c_resize = inputconst(ootype.Void, '_ll_resize') - c_setitem = inputconst(ootype.Void, 'll_setitem_fast') + RESULT = hop.r_result.lowleveltype + c_resulttype = inputconst(ootype.Void, RESULT) c_length = inputconst(ootype.Signed, len(self.items_r)) - hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void) + if isinstance(RESULT, ootype.Array): + v_list = hop.genop('oonewarray', [c_resulttype, c_length], resulttype=RESULT) + else: + assert isinstance(RESULT, ootype.List) + v_list = hop.genop('new', [c_resulttype], resulttype=RESULT) + c_resize = inputconst(ootype.Void, '_ll_resize') + hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void) + + c_setitem = inputconst(ootype.Void, 'll_setitem_fast') + for index in range(len(self.items_r)): name = self.fieldnames[index] r_item = self.items_r[index] @@ -51,6 +57,7 @@ v_item = hop.llops.convertvar(v_item, r_item, hop.r_result.item_repr) c_index = inputconst(ootype.Signed, index) hop.genop('oosend', [c_setitem, v_list, c_index, v_item], resulttype=ootype.Void) + return v_list Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/test/test_rlist.py Fri Apr 4 13:18:57 2008 @@ -498,7 +498,6 @@ assert self.class_name(res) == 'A' #''.join(res.super.typeptr.name) == 'A\00' - def test_reverse(self): def dummyfn(): l = [5, 3, 2] @@ -517,15 +516,15 @@ assert res == 235 def test_prebuilt_list(self): - klist = ['a', 'd', 'z', 'k'] + klist = [6, 7, 8, 9] def dummyfn(n): return klist[n] res = self.interpret(dummyfn, [0]) - assert res == 'a' + assert res == 6 res = self.interpret(dummyfn, [3]) - assert res == 'k' + assert res == 9 res = self.interpret(dummyfn, [-2]) - assert res == 'z' + assert res == 8 klist = ['a', 'd', 'z'] def mkdummyfn(): Modified: pypy/branch/fixed-list-ootype-2/pypy/rpython/test/tool.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/rpython/test/tool.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/rpython/test/tool.py Fri Apr 4 13:18:57 2008 @@ -107,7 +107,9 @@ return OOSupport.to_runicode(u) def ll_to_list(self, l): - return l._list[:] + if hasattr(l, '_list'): + return l._list[:] + return l._array[:] def ll_unpack_tuple(self, t, length): return tuple([getattr(t, 'item%d' % i) for i in range(length)]) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/constant.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/constant.py Fri Apr 4 13:18:57 2008 @@ -28,7 +28,7 @@ from pypy.translator.oosupport.constant import \ push_constant, WeakRefConst, StaticMethodConst, CustomDictConst, \ ListConst, ClassConst, InstanceConst, RecordConst, DictConst, \ - BaseConstantGenerator, AbstractConst + BaseConstantGenerator, AbstractConst, ArrayConst from pypy.translator.cli.ilgenerator import CLIBaseGenerator from pypy.rpython.ootypesystem import ootype from pypy.translator.cli.comparer import EqualityComparer @@ -373,9 +373,25 @@ def create_pointer(self, gen): self.db.const_count.inc('List') - self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE) + self.db.const_count.inc('List', self.value._TYPE.ITEM) self.db.const_count.inc('List', len(self.value._list)) - super(CLIListConst, self).create_pointer(gen) + super(CLIListConst, self).create_pointer(gen) + + +class CLIArrayConst(CLIBaseConstMixin, ArrayConst): + + def _do_not_initialize(self): + # Check if it is an array of all zeroes: + try: + if self.value._list == [0] * len(self.value._list): + return True + except: + pass + return super(CLIArrayConst, self)._do_not_initialize() + + def _setitem(self, SELFTYPE, gen): + gen.array_setitem(SELFTYPE) + class CLIDictConst(CLIDictMixin, DictConst): def create_pointer(self, gen): Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/cts.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/cts.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/cts.py Fri Apr 4 13:18:57 2008 @@ -95,6 +95,14 @@ arglist = ', '.join([arg.typename() for arg in self.arg_types]) return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist) +class CliArrayType(CliType): + + def __init__(self, itemtype): + self.itemtype = itemtype + + def typename(self): + return '%s[]' % self.itemtype.typename() + T = CliPrimitiveType class types: @@ -249,8 +257,13 @@ elif isinstance(t, ootype.StaticMethod): delegate = self.db.record_delegate(t) return CliClassType(None, delegate) + elif isinstance(t, ootype.Array): + item_type = self.lltype_to_cts(t.ITEM) + if item_type == types.void: # special case: Array of Void + return types.list_of_void + return CliArrayType(item_type) elif isinstance(t, ootype.List): - item_type = self.lltype_to_cts(t._ITEMTYPE) + item_type = self.lltype_to_cts(t.ITEM) if item_type == types.void: # special case: List of Void return types.list_of_void return types.list.specialize(item_type) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/entrypoint.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/entrypoint.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/entrypoint.py Fri Apr 4 13:18:57 2008 @@ -9,7 +9,7 @@ ARG0 = graph.getargs()[0].concretetype except IndexError: ARG0 = None - if isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String: + if isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String: return StandaloneEntryPoint(graph) else: return TestEntryPoint(graph) @@ -45,7 +45,7 @@ ARG0 = self.graph.getargs()[0].concretetype except IndexError: ARG0 = None - assert isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String,\ + assert isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String,\ 'Wrong entry point signature: List(String) expected' ilasm.begin_function('main', [('string[]', 'argv')], 'void', True, 'static') Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/gencli.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/gencli.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/gencli.py Fri Apr 4 13:18:57 2008 @@ -31,6 +31,7 @@ RecordConst = constant.CLIRecordConst ClassConst = constant.CLIClassConst ListConst = constant.CLIListConst + ArrayConst = constant.CLIArrayConst StaticMethodConst = constant.CLIStaticMethodConst CustomDictConst = constant.CLICustomDictConst DictConst = constant.CLIDictConst Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/ilgenerator.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/ilgenerator.py Fri Apr 4 13:18:57 2008 @@ -417,3 +417,31 @@ def dup(self, TYPE): self.ilasm.opcode('dup') + + def oonewarray(self, TYPE, length): + if TYPE.ITEM is ootype.Void: + self.new(TYPE) + self.ilasm.opcode('dup') + self.load(length) + self.ilasm.call_method('void [pypylib]pypy.runtime.ListOfVoid::_ll_resize(int32)', virtual=False) + else: + clitype = self.cts.lltype_to_cts(TYPE) + self.load(length) + self.ilasm.opcode('newarr', clitype.itemtype.typename()) + + def _array_suffix(self, ARRAY, erase_unsigned=False): + from pypy.translator.cli.metavm import OOTYPE_TO_MNEMONIC + suffix = OOTYPE_TO_MNEMONIC.get(ARRAY.ITEM, 'ref') + if erase_unsigned: + suffix = suffix.replace('u', 'i') + return suffix + + def array_setitem(self, ARRAY): + suffix = self._array_suffix(ARRAY, erase_unsigned=True) + self.ilasm.opcode('stelem.%s' % suffix) + + def array_getitem(self, ARRAY): + self.ilasm.opcode('ldelem.%s' % self._array_suffix(ARRAY)) + + def array_length(self, ARRAY): + self.ilasm.opcode('ldlen') Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/metavm.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/metavm.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/metavm.py Fri Apr 4 13:18:57 2008 @@ -68,6 +68,17 @@ arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) generator.call_signature(signature) + elif isinstance(this.concretetype, ootype.Array) and this.concretetype.ITEM is not ootype.Void: + v_array = args[0] + ARRAY = v_array.concretetype + if method_name == 'll_setitem_fast': + generator.array_setitem(ARRAY) + elif method_name == 'll_getitem_fast': + generator.array_getitem(ARRAY) + elif method_name == 'll_length': + generator.array_length(ARRAY) + else: + assert False else: generator.call_method(this.concretetype, method_name) @@ -251,10 +262,14 @@ OOTYPE_TO_MNEMONIC = { + ootype.Bool: 'i1', + ootype.Char: 'i2', + ootype.UniChar: 'i2', ootype.Signed: 'i4', ootype.SignedLongLong: 'i8', ootype.Unsigned: 'u4', ootype.UnsignedLongLong: 'u8', + ootype.Float: 'r8', } class _CastPrimitive(MicroInstruction): Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/oopspec.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/oopspec.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/oopspec.py Fri Apr 4 13:18:57 2008 @@ -31,9 +31,9 @@ def get_method(TYPE, name): try: - # special case: when having List of Void, look at the concrete - # methods, not the generic ones - if isinstance(TYPE, ootype.List) and TYPE._ITEMTYPE is ootype.Void: + # special case: when having List of Void, or an Array, look at + # the concrete methods, not the generic ones + if isinstance(TYPE, ootype.Array) or (isinstance(TYPE, ootype.List) and TYPE.ITEM is ootype.Void): return TYPE._METHODS[name] else: return TYPE._GENERIC_METHODS[name] Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/opcodes.py Fri Apr 4 13:18:57 2008 @@ -4,7 +4,7 @@ TypeOf, CastPrimitive, EventHandler, GetStaticField, SetStaticField,\ FieldInfoForConst from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ - New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode + New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode, OONewArray from pypy.translator.cli.cts import WEAKREF from pypy.rpython.ootypesystem import ootype @@ -58,6 +58,7 @@ '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], + 'oonewarray': [OONewArray, StoreResult], 'hint': [PushArg(0), StoreResult], 'direct_call': [Call], Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/src/pypylib.cs Fri Apr 4 13:18:57 2008 @@ -35,10 +35,28 @@ public static string ToPython(object x) { if (x == null) return "None"; + else if (x is Array) + return ArrayToPython((Array)x); else return x.ToString(); } + private static string ArrayToPython(Array array) + { + string res = "["; + foreach(object item in array) { + if (item != null && item.GetType() == typeof(string)) { + object tmp = (object)item; + res += ToPython((string)tmp) + ","; + } + else + res += ToPython(item) + ","; + + } + res += "]"; + return res; + } + public static string InstanceToPython(object obj) { return string.Format("InstanceWrapper('{0}')", obj.GetType().FullName); @@ -373,11 +391,9 @@ return s.Substring(start, count); } - public static List ll_split_chr(string s, char ch) + public static string[] ll_split_chr(string s, char ch) { - List res = new List(); - res.AddRange(s.Split(ch)); - return res; + return s.Split(ch); } public static bool ll_contains(string s, char ch) @@ -417,7 +433,7 @@ res += pypy.test.Result.ToPython((string)tmp) + ","; } else - res += item.ToString() + ","; // XXX: doesn't work for chars + res += pypy.test.Result.ToPython(item) + ","; } res += "]"; return res; Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/cli/test/test_list.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/cli/test/test_list.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/cli/test/test_list.py Fri Apr 4 13:18:57 2008 @@ -1,6 +1,7 @@ import py from pypy.translator.cli.test.runtest import CliTest from pypy.rpython.test.test_rlist import BaseTestRlist +from pypy.rlib.rarithmetic import r_uint class TestCliList(CliTest, BaseTestRlist): def test_recursive(self): @@ -8,3 +9,19 @@ def test_getitem_exc(self): py.test.skip('fixme!') + + def test_list_unsigned(self): + def fn(x): + lst = [r_uint(0), r_uint(1)] + lst[0] = r_uint(x) + return lst[0] + res = self.interpret(fn, [42]) + assert res == 42 + + def test_list_bool(self): + def fn(x): + lst = [True, False] + lst[0] = x + return lst[0] + res = self.interpret(fn, [False]) + assert res == False Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/js/asmgen.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/js/asmgen.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/js/asmgen.py Fri Apr 4 13:18:57 2008 @@ -219,6 +219,9 @@ def runtimenew(self): self.right_hand.append("new %s()" % self.right_hand.pop()) + def oonewarray(self, obj, length): + self.right_hand.append("new %s(%s)" % (obj, length)) + def load_self(self): self.right_hand.append("this") Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/js/database.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/js/database.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/js/database.py Fri Apr 4 13:18:57 2008 @@ -227,6 +227,8 @@ return InstanceConst(db, const, static_type) elif isinstance(const, ootype._list): return ListConst(db, const) + elif isinstance(const, ootype._array): + return ListConst(db, const) elif isinstance(const, ootype._record): return RecordConst(db, const) elif isinstance(const, ootype._string): @@ -355,6 +357,13 @@ class ListConst(AbstractConst): + def _get_list(self): + if isinstance(self.const, ootype._list): + return self.const._list + else: + return self.const._array + + def get_name(self): return "const_list" @@ -368,7 +377,7 @@ if not self.const: return - for i in self.const._list: + for i in self._get_list(): name = self.db.record_const(i, None, 'const') if name is not None: self.depends.add(name) @@ -381,9 +390,10 @@ if not self.const: return - for i in xrange(len(self.const._list)): + l = self._get_list() + for i in xrange(len(l)): ilasm.load_str("%s.%s"%(const_var.name, name)) - el = self.const._list[i] + el = l[i] self.db.load_const(typeOf(el), el, ilasm) self.db.load_const(typeOf(i), i, ilasm) ilasm.list_setitem() Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/js/function.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/js/function.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/js/function.py Fri Apr 4 13:18:57 2008 @@ -73,6 +73,9 @@ def new(self, obj): self.ilasm.new(self.cts.obj_name(obj)) + def oonewarray(self, obj, length): + self.ilasm.oonewarray(self.cts.obj_name(obj), length) + def set_field(self, obj, name): self.ilasm.set_field(obj, name) #self.ilasm.set_field(self.field_name(obj,name)) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/js/jsbuiltin.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/js/jsbuiltin.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/js/jsbuiltin.py Fri Apr 4 13:18:57 2008 @@ -59,6 +59,11 @@ '_ll_resize_le' : list_resize, 'll_length' : _GetPredefinedField('length'), }, + ootype.Array: { + 'll_setitem_fast' : ListSetitem, + 'll_getitem_fast' : ListGetitem, + 'll_length' : _GetPredefinedField('length'), + }, ootype.Dict: { 'll_get' : ListGetitem, 'll_set' : ListSetitem, Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/js/jts.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/js/jts.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/js/jts.py Fri Apr 4 13:18:57 2008 @@ -43,6 +43,8 @@ return self.escape_name(t._name) elif isinstance(t, ootype.List): return "Array" + elif isinstance(t, ootype.Array): + return "Array" elif isinstance(t, lltype.Primitive): return "var" elif isinstance(t, ootype.Record): @@ -135,7 +137,7 @@ ## elif isinstance(t, ootype.StaticMethod): ## return 'void' # TODO: is it correct to ignore StaticMethod? ## elif isinstance(t, ootype.List): -## item_type = self.lltype_to_cts(t._ITEMTYPE) +## item_type = self.lltype_to_cts(t.ITEM) ## return self.__class(PYPY_LIST % item_type, include_class) ## elif isinstance(t, ootype.Dict): ## key_type = self.lltype_to_cts(t._KEYTYPE) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/js/opcodes.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/js/opcodes.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/js/opcodes.py Fri Apr 4 13:18:57 2008 @@ -2,7 +2,8 @@ """ from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult,\ - InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive + InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive,\ + OONewArray from pypy.translator.oosupport.metavm import _GetFieldDispatcher, _SetFieldDispatcher, \ _CallDispatcher, _MethodDispatcher, SetField @@ -119,6 +120,7 @@ 'indirect_call' : [IndirectCall], 'same_as' : CopyName, 'new' : [New], + 'oonewarray' : [OONewArray], 'runtimenew' : [RuntimeNew], 'instanceof' : [IsInstance], #'subclassof' : [IsSubclassOf], Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/builtin.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/builtin.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/builtin.py Fri Apr 4 13:18:57 2008 @@ -1,5 +1,4 @@ -from pypy.translator.jvm import typesystem as jvmtype -from pypy.translator.jvm import generator as jvmgen +import pypy.translator.jvm.typesystem as jvm from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.typesystem import \ jInt, jVoid, jStringBuilder, jString, jPyPy, jChar, jArrayList, jObject, \ @@ -9,7 +8,7 @@ # ______________________________________________________________________ # Mapping of built-in OOTypes to JVM types -class JvmBuiltInType(jvmtype.JvmClassType): +class JvmBuiltInType(jvm.JvmClassType): """ Represents built-in types to JVM. May optionally be associated @@ -18,7 +17,7 @@ """ def __init__(self, db, classty, OOTYPE): - jvmtype.JvmClassType.__init__(self, classty.name) + jvm.JvmClassType.__init__(self, classty.name) self.db = db self.OOTYPE = OOTYPE self.gen = Generifier(OOTYPE) @@ -30,14 +29,14 @@ return hash(self.name) def lookup_field(self, fieldnm): - """ Given a field name, returns a jvmgen.Field object """ + """ Given a field name, returns a jvm.Field object """ _, FIELDTY = self.OOTYPE._lookup_field(fieldnm) jfieldty = self.db.lltype_to_cts(FIELDTY) - return jvmgen.Field( + return jvm.Field( self.descriptor.class_name(), fieldnm, jfieldty, False) def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + """ Given the method name, returns a jvm.Method object """ # Look for a shortcut method in our table of remappings: try: @@ -56,14 +55,14 @@ if self.OOTYPE.__class__ in bridged_objects: # Bridged objects are ones where we have written a java class # that has methods with the correct names and types already - return jvmgen.Method.v(self, methodnm, jargtypes, jrettype) + return jvm.Method.v(self, methodnm, jargtypes, jrettype) else: # By default, we assume it is a static method on the PyPy # object, that takes an instance of this object as the first # argument. The other arguments we just convert to java versions, # except for generics. jargtypes = [self] + jargtypes - return jvmgen.Method.s(jPyPy, methodnm, jargtypes, jrettype) + return jvm.Method.s(jPyPy, methodnm, jargtypes, jrettype) # When we lookup a method on a BuiltInClassNode, we first check the # 'built_in_methods' and 'bridged_objects' tables. This allows us to @@ -80,73 +79,73 @@ # .__class__ is required (ootype.StringBuilder.__class__, "ll_allocate"): - jvmgen.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid), + jvm.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid), (ootype.StringBuilder.__class__, "ll_build"): - jvmgen.Method.v(jStringBuilder, "toString", (), jString), + jvm.Method.v(jStringBuilder, "toString", (), jString), (ootype.String.__class__, "ll_streq"): - jvmgen.Method.v(jString, "equals", (jObject,), jBool), + jvm.Method.v(jString, "equals", (jObject,), jBool), (ootype.String.__class__, "ll_strlen"): - jvmgen.Method.v(jString, "length", (), jInt), + jvm.Method.v(jString, "length", (), jInt), (ootype.String.__class__, "ll_stritem_nonneg"): - jvmgen.Method.v(jString, "charAt", (jInt,), jChar), + jvm.Method.v(jString, "charAt", (jInt,), jChar), (ootype.String.__class__, "ll_startswith"): - jvmgen.Method.v(jString, "startsWith", (jString,), jBool), + jvm.Method.v(jString, "startsWith", (jString,), jBool), (ootype.String.__class__, "ll_endswith"): - jvmgen.Method.v(jString, "endsWith", (jString,), jBool), + jvm.Method.v(jString, "endsWith", (jString,), jBool), (ootype.String.__class__, "ll_strcmp"): - jvmgen.Method.v(jString, "compareTo", (jString,), jInt), + jvm.Method.v(jString, "compareTo", (jString,), jInt), (ootype.String.__class__, "ll_upper"): - jvmgen.Method.v(jString, "toUpperCase", (), jString), + jvm.Method.v(jString, "toUpperCase", (), jString), (ootype.String.__class__, "ll_lower"): - jvmgen.Method.v(jString, "toLowerCase", (), jString), + jvm.Method.v(jString, "toLowerCase", (), jString), (ootype.String.__class__, "ll_replace_chr_chr"): - jvmgen.Method.v(jString, "replace", (jChar, jChar), jString), + jvm.Method.v(jString, "replace", (jChar, jChar), jString), (ootype.Dict, "ll_set"): - jvmgen.Method.v(jHashMap, "put", (jObject, jObject), jObject), + jvm.Method.v(jHashMap, "put", (jObject, jObject), jObject), (ootype.Dict, "ll_get"): - jvmgen.Method.v(jHashMap, "get", (jObject,), jObject), + jvm.Method.v(jHashMap, "get", (jObject,), jObject), (ootype.Dict, "ll_contains"): - jvmgen.Method.v(jHashMap, "containsKey", (jObject,), jBool), + jvm.Method.v(jHashMap, "containsKey", (jObject,), jBool), (ootype.Dict, "ll_length"): - jvmgen.Method.v(jHashMap, "size", (), jInt), + jvm.Method.v(jHashMap, "size", (), jInt), (ootype.Dict, "ll_clear"): - jvmgen.Method.v(jHashMap, "clear", (), jVoid), + jvm.Method.v(jHashMap, "clear", (), jVoid), (ootype.CustomDict, "ll_set"): - jvmgen.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject), + jvm.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject), (ootype.CustomDict, "ll_get"): - jvmgen.Method.v(jPyPyCustomDict, "get", (jObject,), jObject), + jvm.Method.v(jPyPyCustomDict, "get", (jObject,), jObject), (ootype.CustomDict, "ll_contains"): - jvmgen.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool), + jvm.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool), (ootype.CustomDict, "ll_length"): - jvmgen.Method.v(jPyPyCustomDict, "size", (), jInt), + jvm.Method.v(jPyPyCustomDict, "size", (), jInt), (ootype.CustomDict, "ll_clear"): - jvmgen.Method.v(jPyPyCustomDict, "clear", (), jVoid), + jvm.Method.v(jPyPyCustomDict, "clear", (), jVoid), (ootype.List, "ll_length"): - jvmgen.Method.v(jArrayList, "size", (), jInt), + jvm.Method.v(jArrayList, "size", (), jInt), (ootype.List, "ll_getitem_fast"): - jvmgen.Method.v(jArrayList, "get", (jInt,), jObject), + jvm.Method.v(jArrayList, "get", (jInt,), jObject), } Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/cmpopcodes.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/cmpopcodes.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/cmpopcodes.py Fri Apr 4 13:18:57 2008 @@ -1,9 +1,11 @@ -from pypy.translator.jvm.generator import \ +from pypy.translator.jvm.typesystem import \ IFLT, IFLE, IFEQ, IFNE, IFGT, IFGE, \ IFNONNULL, IF_ACMPEQ, GOTO, ICONST, \ DCONST_0, DCMPG, LCONST_0, LCMP, \ IF_ICMPLT, IF_ICMPLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPGT, IF_ICMPGE, \ - PYPYUINTCMP, PYPYULONGCMP, \ + PYPYUINTCMP, PYPYULONGCMP + +from pypy.translator.jvm.generator import \ Label ##### Branch directly as the result of a comparison Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/constant.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/constant.py Fri Apr 4 13:18:57 2008 @@ -1,15 +1,14 @@ from pypy.rpython.ootypesystem import ootype from pypy.objspace.flow import model as flowmodel -from pypy.translator.jvm.generator import \ - Field, Method, CUSTOMDICTMAKE +import pypy.translator.jvm.typesystem as jvm +from pypy.translator.jvm.typesystem import \ + jVoid, Method, Field from pypy.translator.oosupport.constant import \ BaseConstantGenerator, RecordConst, InstanceConst, ClassConst, \ StaticMethodConst, CustomDictConst, WeakRefConst, push_constant, \ MAX_CONST_PER_STEP -from pypy.translator.jvm.typesystem import \ - jObject, jVoid, jPyPyWeakRef, JvmClassType -jPyPyConstantInit = JvmClassType('pypy.ConstantInit') +jPyPyConstantInit = jvm.JvmClassType('pypy.ConstantInit') jPyPyConstantInitMethod = Method.s(jPyPyConstantInit, 'init', [], jVoid) # ___________________________________________________________________________ @@ -51,7 +50,7 @@ # This prevents any one class from getting too big. if (self.num_constants % MAX_CONST_PER_STEP) == 0: cc_num = len(self.ccs) - self.ccs.append(JvmClassType('pypy.Constant_%d' % cc_num)) + self.ccs.append(jvm.JvmClassType('pypy.Constant_%d' % cc_num)) self.num_constants += 1 const.fieldobj = Field(self.ccs[-1].name, const.name, jfieldty, True) @@ -99,7 +98,7 @@ except KeyError: constants_by_cls[const.fieldobj.class_name] = [const] for cc in self.ccs: - ilasm.begin_class(cc, jObject) + ilasm.begin_class(cc, jvm.jObject) for const in constants_by_cls[cc.name]: ilasm.add_field(const.fieldobj) ilasm.end_class() @@ -122,8 +121,9 @@ self._push_constant_during_init(gen, const) def _declare_step(self, gen, stepnum): - self.step_classes.append(JvmClassType('pypy.ConstantInit_%d' % stepnum)) - gen.begin_class(self.step_classes[-1], jObject) + self.step_classes.append(jvm.JvmClassType( + 'pypy.ConstantInit_%d' % stepnum)) + gen.begin_class(self.step_classes[-1], jvm.jObject) gen.begin_function('constant_init', [], [], jVoid, True) def _close_step(self, gen, stepnum): @@ -132,7 +132,7 @@ gen.end_class() # end pypy.ConstantInit_NNN def _end_gen_constants(self, gen, numsteps): - gen.begin_class(jPyPyConstantInit, jObject) + gen.begin_class(jPyPyConstantInit, jvm.jObject) gen.begin_j_function(jPyPyConstantInit, jPyPyConstantInitMethod) for cls in self.step_classes: m = Method.s(cls, "constant_init", [], jVoid) @@ -156,7 +156,7 @@ if self.delegate_impl: gen.new_with_jtype(self.delegate_impl) else: - gen.push_null(jObject) + gen.push_null(jvm.jObject) def initialize_data(self, constgen, gen): return @@ -180,7 +180,7 @@ def create_pointer(self, gen): gen.new_with_jtype(self.eq_jcls) gen.new_with_jtype(self.hash_jcls) - gen.emit(CUSTOMDICTMAKE) + gen.emit(jvm.CUSTOMDICTMAKE) class JVMWeakRefConst(WeakRefConst): @@ -188,7 +188,7 @@ PRIORITY = 200 def jtype(self): - return jPyPyWeakRef + return jvm.jPyPyWeakRef def create_pointer(self, gen): if not self.value: Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/database.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/database.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/database.py Fri Apr 4 13:18:57 2008 @@ -7,21 +7,15 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.ootypesystem import ootype, rclass from pypy.rpython.ootypesystem.module import ll_os -from pypy.translator.jvm import typesystem as jvmtype from pypy.translator.jvm import node, methods from pypy.translator.jvm.option import getoption -import pypy.translator.jvm.generator as jvmgen -from pypy.translator.jvm.generator import Method, Property, Field -import pypy.translator.jvm.constant as jvmconst -from pypy.translator.jvm.typesystem import \ - jStringBuilder, jInt, jVoid, jString, jChar, jObject, \ - jThrowable, JvmNativeClass, jPyPy, JvmClassType from pypy.translator.jvm.builtin import JvmBuiltInType - from pypy.translator.oosupport.database import Database as OODatabase from pypy.rpython.ootypesystem.bltregistry import ExternalType from pypy.annotation.signature import annotation from pypy.annotation.model import annotation_to_lltype +import pypy.translator.jvm.constant as jvmconst +import pypy.translator.jvm.typesystem as jvm # ______________________________________________________________________ # Database object @@ -34,7 +28,7 @@ self._jasmin_files = [] # list of strings --- .j files we made self._classes = {} # Maps ootype class objects to node.Class objects, # and JvmType objects as well - self._functions = {} # graph -> jvmgen.Method + self._functions = {} # graph -> jvm.Method # (jargtypes, jrettype) -> node.StaticMethodInterface self._delegates = {} @@ -44,7 +38,7 @@ self._function_names = {} # graph --> function_name - self._constants = {} # flowmodel.Variable --> jvmgen.Const + self._constants = {} # flowmodel.Variable --> jvm.Const # Special fields for the Object class, see _translate_Object self._object_interf = None @@ -65,11 +59,11 @@ # # These are public attributes that are referenced from # elsewhere in the code using - # jvmgen.Generator.push_interlink() and .push_pypy(). - self.jPyPyMain = JvmClassType(self._pkg('Main')) - self.pypy_field = jvmgen.Field.s(self.jPyPyMain, 'pypy', jPyPy) - self.interlink_field = jvmgen.Field.s(self.jPyPyMain, 'ilink', - jvmtype.jPyPyInterlink) + # jvm.Generator.push_interlink() and .push_pypy(). + self.jPyPyMain = jvm.JvmClassType(self._pkg('Main')) + self.pypy_field = jvm.Field.s(self.jPyPyMain, 'pypy', jvm.jPyPy) + self.interlink_field = jvm.Field.s(self.jPyPyMain, 'ilink', + jvm.jPyPyInterlink) # _________________________________________________________________ # Java String vs Byte Array @@ -93,7 +87,7 @@ def class_name(self, TYPE): jtype = self.lltype_to_cts(TYPE) - assert isinstance(jtype, jvmtype.JvmClassType) + assert isinstance(jtype, jvm.JvmClassType) return jtype.name def add_jasmin_file(self, jfile): @@ -120,14 +114,14 @@ like. The 'methods' argument should be a dictionary whose keys are - method names and whose entries are jvmgen.Method objects which + method names and whose entries are jvm.Method objects which the corresponding method should invoke. """ nm = self._pkg(self._uniq('InterlinkImplementation')) - cls = node.Class(nm, supercls=jObject) + cls = node.Class(nm, supercls=jvm.jObject) for method_name, helper in methods.items(): cls.add_method(node.InterlinkFunction(cls, method_name, helper)) - cls.add_interface(jvmtype.jPyPyInterlink) + cls.add_interface(jvm.jPyPyInterlink) self.jInterlinkImplementation = cls self.pending_node(cls) @@ -169,7 +163,7 @@ # Create the class object first clsnm = self._pkg(self._uniq('Record')) - clsobj = node.Class(clsnm, jObject) + clsobj = node.Class(clsnm, jvm.jObject) self._classes[OOTYPE] = clsobj # Add fields: @@ -205,8 +199,8 @@ def gen_name(): return self._pkg(self._uniq(OBJ._name)) internm, implnm, exc_implnm = gen_name(), gen_name(), gen_name() self._object_interf = node.Interface(internm) - self._object_impl = node.Class(implnm, supercls=jObject) - self._object_exc_impl = node.Class(exc_implnm, supercls=jThrowable) + self._object_impl = node.Class(implnm, supercls=jvm.jObject) + self._object_exc_impl = node.Class(exc_implnm, supercls=jvm.jThrowable) self._object_impl.add_interface(self._object_interf) self._object_exc_impl.add_interface(self._object_interf) @@ -220,12 +214,12 @@ methodnm = "_jvm_"+fieldnm def getter_method_obj(node): - return Method.v(node, methodnm+"_g", [], fieldty) + return jvm.Method.v(node, methodnm+"_g", [], fieldty) def putter_method_obj(node): - return Method.v(node, methodnm+"_p", [fieldty], jVoid) + return jvm.Method.v(node, methodnm+"_p", [fieldty], jvm.jVoid) # Add get/put methods to the interface: - prop = Property( + prop = jvm.Property( fieldnm, getter_method_obj(self._object_interf), putter_method_obj(self._object_interf), @@ -235,7 +229,7 @@ # Generate implementations: def generate_impl(clsobj): clsnm = clsobj.name - fieldobj = Field(clsnm, fieldnm, fieldty, False, FIELDOOTY) + fieldobj = jvm.Field(clsnm, fieldnm, fieldty, False, FIELDOOTY) clsobj.add_field(fieldobj, fielddef) clsobj.add_method(node.GetterFunction( self, clsobj, getter_method_obj(clsobj), fieldobj)) @@ -296,7 +290,7 @@ arglist = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] returntype = self.lltype_to_cts(METH.RESULT) - clsobj.add_abstract_method(jvmgen.Method.v( + clsobj.add_abstract_method(jvm.Method.v( clsobj, mname, arglist, returntype)) else: # if the first argument's type is not a supertype of @@ -323,7 +317,7 @@ if FIELDOOTY is ootype.Void: continue fieldty = self.lltype_to_cts(FIELDOOTY) clsobj.add_field( - jvmgen.Field(clsobj.name, fieldnm, fieldty, False, FIELDOOTY), + jvm.Field(clsobj.name, fieldnm, fieldty, False, FIELDOOTY), fielddef) def pending_class(self, OOTYPE): @@ -334,7 +328,7 @@ This is invoked when a standalone function is to be compiled. It creates a class named after the function with a single method, invoke(). This class is added to the worklist. - Returns a jvmgen.Method object that allows this function to be + Returns a jvm.Method object that allows this function to be invoked. """ if graph in self._functions: @@ -366,7 +360,7 @@ """ Like record_delegate, but the signature is in terms of java types. jargs is a list of JvmTypes, one for each argument, - and jret is a JvmType. Note that jargs does NOT include an + and jret is a Jvm. Note that jargs does NOT include an entry for the this pointer of the resulting object. """ key = (jargs, jret) @@ -424,17 +418,17 @@ # any type. _toString_methods = { - ootype.Signed:jvmgen.INTTOSTRINGI, - ootype.Unsigned:jvmgen.PYPYSERIALIZEUINT, - ootype.SignedLongLong:jvmgen.LONGTOSTRINGL, - ootype.UnsignedLongLong: jvmgen.PYPYSERIALIZEULONG, - ootype.Float:jvmgen.DOUBLETOSTRINGD, - ootype.Bool:jvmgen.PYPYSERIALIZEBOOLEAN, - ootype.Void:jvmgen.PYPYSERIALIZEVOID, - ootype.Char:jvmgen.PYPYESCAPEDCHAR, - ootype.UniChar:jvmgen.PYPYESCAPEDUNICHAR, - ootype.String:jvmgen.PYPYESCAPEDSTRING, - ootype.Unicode:jvmgen.PYPYESCAPEDUNICODE, + ootype.Signed:jvm.INTTOSTRINGI, + ootype.Unsigned:jvm.PYPYSERIALIZEUINT, + ootype.SignedLongLong:jvm.LONGTOSTRINGL, + ootype.UnsignedLongLong: jvm.PYPYSERIALIZEULONG, + ootype.Float:jvm.DOUBLETOSTRINGD, + ootype.Bool:jvm.PYPYSERIALIZEBOOLEAN, + ootype.Void:jvm.PYPYSERIALIZEVOID, + ootype.Char:jvm.PYPYESCAPEDCHAR, + ootype.UniChar:jvm.PYPYESCAPEDUNICHAR, + ootype.String:jvm.PYPYESCAPEDSTRING, + ootype.Unicode:jvm.PYPYESCAPEDUNICODE, } def toString_method_for_ootype(self, OOTYPE): @@ -451,7 +445,7 @@ to print the value of 'var'. """ - return self._toString_methods.get(OOTYPE, jvmgen.PYPYSERIALIZEOBJECT) + return self._toString_methods.get(OOTYPE, jvm.PYPYSERIALIZEOBJECT) # _________________________________________________________________ # Type translation functions @@ -471,46 +465,51 @@ # Dictionary for scalar types; in this case, if we see the key, we # will return the value ootype_to_scalar = { - ootype.Void: jvmtype.jVoid, - ootype.Signed: jvmtype.jInt, - ootype.Unsigned: jvmtype.jInt, - ootype.SignedLongLong: jvmtype.jLong, - ootype.UnsignedLongLong: jvmtype.jLong, - ootype.Bool: jvmtype.jBool, - ootype.Float: jvmtype.jDouble, - ootype.Char: jvmtype.jChar, # byte would be sufficient, but harder - ootype.UniChar: jvmtype.jChar, - ootype.Class: jvmtype.jClass, - ootype.ROOT: jvmtype.jObject, # treat like a scalar + ootype.Void: jvm.jVoid, + ootype.Signed: jvm.jInt, + ootype.Unsigned: jvm.jInt, + ootype.SignedLongLong: jvm.jLong, + ootype.UnsignedLongLong: jvm.jLong, + ootype.Bool: jvm.jBool, + ootype.Float: jvm.jDouble, + ootype.Char: jvm.jChar, # byte would be sufficient, but harder + ootype.UniChar: jvm.jChar, + ootype.Class: jvm.jClass, + ootype.ROOT: jvm.jObject, # treat like a scalar } # Dictionary for non-scalar types; in this case, if we see the key, we # will return a JvmBuiltInType based on the value ootype_to_builtin = { - ootype.String: jvmtype.jString, - ootype.Unicode: jvmtype.jString, - ootype.StringBuilder: jvmtype.jStringBuilder, - ootype.UnicodeBuilder: jvmtype.jStringBuilder, - ootype.List: jvmtype.jArrayList, - ootype.Dict: jvmtype.jHashMap, - ootype.DictItemsIterator:jvmtype.jPyPyDictItemsIterator, - ootype.CustomDict: jvmtype.jPyPyCustomDict, - ootype.WeakReference: jvmtype.jPyPyWeakRef, - ll_os.STAT_RESULT: jvmtype.jPyPyStatResult, + ootype.String: jvm.jString, + ootype.Unicode: jvm.jString, + ootype.StringBuilder: jvm.jStringBuilder, + ootype.UnicodeBuilder: jvm.jStringBuilder, + ootype.List: jvm.jArrayList, + ootype.Dict: jvm.jHashMap, + ootype.DictItemsIterator:jvm.jPyPyDictItemsIterator, + ootype.CustomDict: jvm.jPyPyCustomDict, + ootype.WeakReference: jvm.jPyPyWeakRef, + ll_os.STAT_RESULT: jvm.jPyPyStatResult, # These are some configured records that are generated by Java # code. #ootype.Record({"item0": ootype.Signed, "item1": ootype.Signed}): - #jvmtype.jPyPyRecordSignedSigned, + #jvm.jPyPyRecordSignedSigned, #ootype.Record({"item0": ootype.Float, "item1": ootype.Signed}): - #jvmtype.jPyPyRecordFloatSigned, + #jvm.jPyPyRecordFloatSigned, #ootype.Record({"item0": ootype.Float, "item1": ootype.Float}): - #jvmtype.jPyPyRecordFloatFloat, + #jvm.jPyPyRecordFloatFloat, #ootype.Record({"item0": ootype.String, "item1": ootype.String}): - #jvmtype.jPyPyRecordStringString, + #jvm.jPyPyRecordStringString, } def lltype_to_cts(self, OOT): + import sys + res = self._lltype_to_cts(OOT) + return res + + def _lltype_to_cts(self, OOT): """ Returns an instance of JvmType corresponding to the given OOType """ @@ -519,9 +518,11 @@ return self.ootype_to_scalar[OOT] if (isinstance(OOT, lltype.Ptr) and isinstance(OOT.TO, lltype.OpaqueType)): - return jObject + return jvm.jObject if OOT in self.ootype_to_builtin: return JvmBuiltInType(self, self.ootype_to_builtin[OOT], OOT) + if isinstance(OOT, ootype.Array): + return self._array_type(OOT.ITEM) if OOT.__class__ in self.ootype_to_builtin: return JvmBuiltInType( self, self.ootype_to_builtin[OOT.__class__], OOT) @@ -538,10 +539,26 @@ # handle externals if isinstance(OOT, ExternalType): - return JvmNativeClass(self, OOT) + return jvm.JvmNativeClass(self, OOT) assert False, "Untranslatable type %s!" % OOT + ooitemtype_to_array = { + ootype.Signed : jvm.jIntArray, + ootype.Unsigned : jvm.jIntArray, + ootype.Char : jvm.jCharArray, + ootype.Bool : jvm.jBoolArray, + ootype.UniChar : jvm.jCharArray, + ootype.String : jvm.jStringArray, + ootype.Float : jvm.jDoubleArray, + ootype.Void : jvm.jVoidArray, + } + + def _array_type(self, ITEM): + if ITEM in self.ooitemtype_to_array: + return self.ooitemtype_to_array[ITEM] + return jvm.jObjectArray + def annotation_to_cts(self, _tp): s_tp = annotation(_tp) TP = annotation_to_lltype(s_tp) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/generator.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/generator.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/generator.py Fri Apr 4 13:18:57 2008 @@ -12,231 +12,11 @@ from pypy.rlib.objectmodel import CDefinedIntSymbolic from pypy.rlib.rarithmetic import isnan, isinf from pypy.translator.oosupport.constant import push_constant -import pypy.translator.jvm.typesystem as jvmtype -from pypy.translator.jvm.typesystem import \ - JvmType, jString, jInt, jLong, jDouble, jBool, jString, \ - jPyPy, jVoid, jMath, desc_for_method, jPrintStream, jClass, jChar, \ - jObject, jByteArray, jPyPyExcWrap, jIntegerClass, jLongClass, \ - jDoubleClass, jCharClass, jStringBuilder, JvmScalarType, jArrayList, \ - jObjectArray, jPyPyInterlink, jPyPyCustomDict, jPyPyEquals, \ - jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os, jPyPyInterlink - - -# ___________________________________________________________________________ -# JVM Opcodes: -# -# Map from symbolic name to an instance of the Opcode class - -class Opcode(object): - def __init__(self, jvmstr): - """ - flags is a set of flags (see above) that describe opcode #UPDATE - jvmstr is the name for jasmin printouts - """ - self.jvmstr = jvmstr - self.flags = None #Should flags be added to args? - - def __repr__(self): - return "" % (self.jvmstr, self.flags) - - def specialize(self, args): - """ Process the argument list according to the various flags. - Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing - the new opcode, and ARGS is a list of arguments or empty tuple. - Most of these do not do anything. """ - return (self.jvmstr, args) - -class IntConstOpcode(Opcode): - """ The ICONST opcode specializes itself for small integer opcodes. """ - def specialize(self, args): - assert len(args) == 1 - if args[0] == -1: - return self.jvmstr + "_m1", () - elif args[0] >= 0 and args[0] <= 5: - return self.jvmstr + "_" + str(args[0]), () - # Non obvious: convert ICONST to LDC if the constant is out of - # range - return "ldc", args - -class VarOpcode(Opcode): - """ An Opcode which takes a variable index as an argument; specialized - to small integer indices. """ - def specialize(self, args): - assert len(args) == 1 - if args[0] >= 0 and args[0] <= 3: - return self.jvmstr + "_" + str(args[0]), () - return Opcode.specialize(self, args) - -class IntClassNameOpcode(Opcode): - """ An opcode which takes an internal class name as its argument; - the actual argument will be a JvmType instance. """ - def specialize(self, args): - args = [args[0].descriptor.int_class_name()] - return self.jvmstr, args - -class OpcodeFamily(object): - """ - Many opcodes in JVM have variants that depend on the type of the - operands; for example, one must choose the correct ALOAD, ILOAD, - or DLOAD depending on whether one is loading a reference, integer, - or double variable respectively. Each instance of this class - defines one 'family' of opcodes, such as the LOAD family shown - above, and produces Opcode objects specific to a particular type. - """ - def __init__(self, opcclass, suffix): - """ - opcclass is the opcode subclass to use (see above) when - instantiating a particular opcode - - jvmstr is the name for jasmin printouts - """ - self.opcode_class = opcclass - self.suffix = suffix - self.cache = {} - - def _o(self, prefix): - try: - return self.cache[prefix] - except KeyError: - self.cache[prefix] = obj = self.opcode_class( - prefix+self.suffix) - return obj - - def for_type(self, argtype): - """ Returns a customized opcode of this family appropriate to - 'argtype', a JvmType object. """ - - desc = argtype.descriptor - - # These are always true: - if desc[0] == 'L': return self._o("a") # Objects - if desc[0] == '[': return self._o("a") # Arrays - if desc == 'I': return self._o("i") # Integers - if desc == 'J': return self._o("l") # Integers - if desc == 'D': return self._o("d") # Doubles - if desc == 'V': return self._o("") # Void [used by RETURN] - - # Chars/Bytes/Booleans are normally represented as ints - # in the JVM, but some opcodes are different. They use a - # different OpcodeFamily (see ArrayOpcodeFamily for ex) - if desc == 'C': return self._o("i") # Characters - if desc == 'B': return self._o("i") # Bytes - if desc == 'Z': return self._o("i") # Boolean +import pypy.translator.jvm.typesystem as jvm - assert False, "Unknown argtype=%s" % repr(argtype) - raise NotImplementedError - -class ArrayOpcodeFamily(OpcodeFamily): - """ Opcode family specialized for array access instr """ - def for_type(self, argtype): - desc = argtype.descriptor - if desc == 'J': return self._o("l") # Integers - if desc == 'D': return self._o("d") # Doubles - if desc == 'C': return self._o("c") # Characters - if desc == 'B': return self._o("b") # Bytes - if desc == 'Z': return self._o("b") # Boolean (access as bytes) - return OpcodeFamily.for_type(self, argtype) - -# Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx -# variants compare a single integer arg against 0, and the IF_ICMPxx -# variants compare 2 integer arguments against each other. -for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'): - ifop = "if%s" % cmpop - if_icmpop = "if_icmp%s" % cmpop - globals()[ifop.upper()] = Opcode(ifop) - globals()[if_icmpop.upper()] = Opcode(if_icmpop) - -# Compare references, either against NULL or against each other -IFNULL = Opcode('ifnull') -IFNONNULL = Opcode('ifnonnull') -IF_ACMPEQ = Opcode('if_acmpeq') -IF_ACMPNE = Opcode('if_acmpne') - -# Method invocation -INVOKESTATIC = Opcode('invokestatic') -INVOKEVIRTUAL = Opcode('invokevirtual') -INVOKESPECIAL = Opcode('invokespecial') -INVOKEINTERFACE = Opcode('invokeinterface') - -# Other opcodes -LDC = Opcode('ldc') # single-word types -LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs -GOTO = Opcode('goto') -ICONST = IntConstOpcode('iconst') -ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly -ACONST_NULL=Opcode('aconst_null') -DCONST_0 = Opcode('dconst_0') -DCONST_1 = Opcode('dconst_1') -LCONST_0 = Opcode('lconst_0') -LCONST_1 = Opcode('lconst_1') -GETFIELD = Opcode('getfield') -PUTFIELD = Opcode('putfield') -GETSTATIC = Opcode('getstatic') -PUTSTATIC = Opcode('putstatic') -CHECKCAST = IntClassNameOpcode('checkcast') -INEG = Opcode('ineg') -IXOR = Opcode('ixor') -IADD = Opcode('iadd') -ISUB = Opcode('isub') -IMUL = Opcode('imul') -IDIV = Opcode('idiv') -IREM = Opcode('irem') -IAND = Opcode('iand') -IOR = Opcode('ior') -ISHL = Opcode('ishl') -ISHR = Opcode('ishr') -IUSHR = Opcode('iushr') -LCMP = Opcode('lcmp') -DCMPG = Opcode('dcmpg') -DCMPL = Opcode('dcmpl') -NOP = Opcode('nop') -I2D = Opcode('i2d') -I2L = Opcode('i2l') -D2I= Opcode('d2i') -#D2L= Opcode('d2l') #PAUL -L2I = Opcode('l2i') -L2D = Opcode('l2d') -ATHROW = Opcode('athrow') -DNEG = Opcode('dneg') -DADD = Opcode('dadd') -DSUB = Opcode('dsub') -DMUL = Opcode('dmul') -DDIV = Opcode('ddiv') -DREM = Opcode('drem') -LNEG = Opcode('lneg') -LADD = Opcode('ladd') -LSUB = Opcode('lsub') -LMUL = Opcode('lmul') -LDIV = Opcode('ldiv') -LREM = Opcode('lrem') -LAND = Opcode('land') -LOR = Opcode('lor') -LXOR = Opcode('lxor') -LSHL = Opcode('lshl') -LSHR = Opcode('lshr') -LUSHR = Opcode('lushr') -NEW = IntClassNameOpcode('new') -DUP = Opcode('dup') -DUP2 = Opcode('dup2') -DUP_X1 = Opcode('dup_x1') -POP = Opcode('pop') -POP2 = Opcode('pop2') -SWAP = Opcode('swap') -INSTANCEOF= IntClassNameOpcode('instanceof') -# Loading/storing local variables -LOAD = OpcodeFamily(VarOpcode, "load") -STORE = OpcodeFamily(VarOpcode, "store") -RETURN = OpcodeFamily(Opcode, "return") - -# Loading/storing from arrays -# *NOTE*: This family is characterized by the type of the ELEMENT, -# not the type of the ARRAY. -# -# Also: here I break from convention by naming the objects ARRLOAD -# rather than ALOAD, even though the suffix is 'aload'. This is to -# avoid confusion with the ALOAD opcode. -ARRLOAD = ArrayOpcodeFamily(Opcode, "aload") -ARRSTORE = ArrayOpcodeFamily(Opcode, "astore") +# Load a few commonly used names, but prefer to use 'jvm.Name' +from pypy.translator.jvm.typesystem import \ + jPyPy, jString, jInt, jVoid # ___________________________________________________________________________ # Labels @@ -257,244 +37,6 @@ return self.label # ___________________________________________________________________________ -# Methods -# -# "Method" objects describe all the information needed to invoke a -# method. We create one for each node.Function object, as well as for -# various helper methods (defined below). To invoke a method, you -# push its arguments and then use generator.emit(methobj) where -# methobj is its Method instance. - -class Method(object): - - # Create a constructor: - def c(classty, argtypes): - return Method(classty.name, "", argtypes, jVoid, - opcode=INVOKESPECIAL) - c = staticmethod(c) - - # Create a virtual or interface method: - def v(classty, methnm, argtypes, rettype): - """ - Shorthand to create a virtual method. - 'class' - JvmType object for the class - 'methnm' - name of the method (Python string) - 'argtypes' - list of JvmType objects, one for each argument but - not the this ptr - 'rettype' - JvmType for return type - """ - assert argtypes is not None - assert rettype is not None - classnm = classty.name - if isinstance(classty, jvmtype.JvmInterfaceType): - opc = INVOKEINTERFACE - else: - assert isinstance(classty, jvmtype.JvmClassType) - opc = INVOKEVIRTUAL - return Method(classnm, methnm, argtypes, rettype, opcode=opc) - v = staticmethod(v) - - # Create a static method: - def s(classty, methnm, argtypes, rettype): - """ - Shorthand to create a static method. - 'class' - JvmType object for the class - 'methnm' - name of the method (Python string) - 'argtypes' - list of JvmType objects, one for each argument but - not the this ptr - 'rettype' - JvmType for return type - """ - assert isinstance(classty, JvmType) - classnm = classty.name - return Method(classnm, methnm, argtypes, rettype) - s = staticmethod(s) - - def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC): - self.opcode = opcode - self.class_name = classnm # String, ie. "java.lang.Math" - self.method_name = methnm # String "abs" - self.argument_types = argtypes # List of jvmtypes - self.return_type = rettype # jvmtype - - # Compute the method descriptior, which is a string like "()I": - argtypesdesc = [a.descriptor for a in argtypes] - rettypedesc = rettype.descriptor - self.descriptor = desc_for_method(argtypesdesc, rettypedesc) - def invoke(self, gen): - gen._instr(self.opcode, self) - def is_static(self): - return self.opcode == INVOKESTATIC - def jasmin_syntax(self): - res = "%s/%s%s" % (self.class_name.replace('.','/'), - self.method_name, - self.descriptor) - # A weird, inexplicable quirk of Jasmin syntax is that it requires - # the number of arguments after an invokeinterface call: - if self.opcode == INVOKEINTERFACE: - res += " %d" % (len(self.argument_types)+1,) - return res - -OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt) -OBJTOSTRING = Method.v(jObject, 'toString', (), jString) -OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool) -SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid) -INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString) -LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString) -DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString) -CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString) -MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt) -IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt) -MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong) -LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong) -MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble) -INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt) -LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong) -IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt) -LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong) -ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt) -LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong) -IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt) -LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong) -MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble) -IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt) -LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong) -IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt) -LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong) -IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt) -LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong) -ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt) -LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong) -MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble) -PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid) -CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass) -CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool) -STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append', - (jString,), jStringBuilder) -PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt) -PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt) -PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt) -PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt) -PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt) -PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong) -PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble) -PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt) -PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL -PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong) -PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt) -PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt) -PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong) -PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong) -PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool) -PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble) -PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar) -PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble) -PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid) -PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid) -PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString) -PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString) -PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString) -PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString) -PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString) -PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString) -PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString) -PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString) -PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString) -PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) -PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) -PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList) -PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble) -OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) -CLASSGETNAME = Method.v(jClass, 'getName', (), jString) -CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make', - (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict) -PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef) -PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject) - -# ___________________________________________________________________________ -# Fields -# -# Field objects encode information about fields. - -class Field(object): - - @staticmethod - def i(classty, fieldnm, fieldty, OOTYPE=None): - """ - Shorthand to create an instance field. - 'class' - JvmType object for the class containing the field - 'fieldnm' - name of the field (Python string) - 'fieldty' - JvmType object for the type of the field - 'OOTYPE' - optional OOTYPE object for the type of the field - """ - return Field(classty.name, fieldnm, fieldty, False, OOTYPE) - - @staticmethod - def s(classty, fieldnm, fieldty, OOTYPE=None): - """ - Shorthand to create a static field. - 'class' - JvmType object for the class containing the field - 'fieldnm' - name of the field (Python string) - 'fieldty' - JvmType object for the type of the field - 'OOTYPE' - optional OOTYPE object for the type of the field - """ - return Field(classty.name, fieldnm, fieldty, True, OOTYPE) - - def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None): - # All fields are public - self.class_name = classnm # String, ie. "java.lang.Math" - self.field_name = fieldnm # String "someField" - self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None - self.jtype = jtype # JvmType - self.is_static = static # True or False - def load(self, gen): - if self.is_static: - gen._instr(GETSTATIC, self) - else: - gen._instr(GETFIELD, self) - def store(self, gen): - if self.is_static: - gen._instr(PUTSTATIC, self) - else: - gen._instr(PUTFIELD, self) - def jasmin_syntax(self): - return "%s/%s %s" % ( - self.class_name.replace('.','/'), - self.field_name, - self.jtype.descriptor) - -class Property(object): - """ - An object which acts like a Field, but when a value is loaded or - stored it actually invokes accessor methods. - """ - def __init__(self, field_name, get_method, put_method, OOTYPE=None): - self.get_method = get_method - self.put_method = put_method - self.field_name = field_name - self.OOTYPE = OOTYPE - - # Synthesize the Field attributes from the get_method/put_method: - self.class_name = get_method.class_name - assert put_method.class_name == self.class_name - self.jtype = get_method.return_type - self.is_static = get_method.is_static - def load(self, gen): - self.get_method.invoke(gen) - def store(self, gen): - self.put_method.invoke(gen) - # jasmin_syntax is not needed, since this object itself never appears - # as an argument an Opcode - -SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream) -SYSTEMERR = Field.s(jSystem, 'err', jPrintStream) -DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble) -DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble) -DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble) - -PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink) -PYPYOS = Field.i(jPyPy, 'os', jll_os) - -# ___________________________________________________________________________ # Generator State class ClassState(object): @@ -625,8 +167,7 @@ """ self.begin_function("", [], [self.current_type()], jVoid) self.load_jvm_var(self.current_type(), 0) - jmethod = Method(self.curclass.superclass_type.name, "", - (), jVoid, opcode=INVOKESPECIAL) + jmethod = jvm.Method.c(self.curclass.superclass_type, ()) jmethod.invoke(self) def end_constructor(self): @@ -700,14 +241,14 @@ def return_val(self, jtype): """ Returns a value from top of stack of the JvmType 'jtype' """ - self._instr(RETURN.for_type(jtype)) + self._instr(jvm.RETURN.for_type(jtype)) 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) + self.emit(jvm.OBJECTGETCLASS) + self.emit(jvm.CLASSGETNAME) def load_string(self, str): """ Pushes a Java version of a Python string onto the stack. @@ -724,7 +265,7 @@ '"') # Use LDC to load the Java version: # XXX --- support byte arrays here? Would be trickier! - self._instr(LDC, res) + self._instr(jvm.LDC, res) def load_jvm_var(self, jvartype, varidx): """ Loads from jvm slot #varidx, which is expected to hold a value of @@ -732,20 +273,20 @@ assert varidx < self.curfunc.next_offset if jvartype is jVoid: return - opc = LOAD.for_type(jvartype) + opc = jvm.LOAD.for_type(jvartype) self._instr(opc, varidx) def store_jvm_var(self, vartype, varidx): """ Loads from jvm slot #varidx, which is expected to hold a value of type vartype """ - self._instr(STORE.for_type(vartype), varidx) + self._instr(jvm.STORE.for_type(vartype), varidx) def load_from_array(self, elemtype): """ Loads something from an array; the result will be of type 'elemtype' (and hence the array is of type 'array_of(elemtype)'), where 'elemtype' is a JvmType. Assumes that the array ref and index are already pushed onto stack (in that order). """ - self._instr(ARRLOAD.for_type(elemtype)) + self._instr(jvm.ARRLOAD.for_type(elemtype)) def store_to_array(self, elemtype): """ Stores something into an array; the result will be of type @@ -753,7 +294,7 @@ 'array_of(elemtype)'), where 'elemtype' is a JvmType. Assumes that the array ref, index, and value are already pushed onto stack (in that order).""" - self._instr(ARRLOAD.for_type(elemtype)) + self._instr(jvm.ARRLOAD.for_type(elemtype)) def unique_label(self, desc, mark=False): """ Returns an opaque, unique label object that can be passed an @@ -773,7 +314,7 @@ def load_this_ptr(self): """ Convenience method. Be sure you only call it from a virtual method, not static methods. """ - self.load_jvm_var(jObject, 0) + self.load_jvm_var(jvm.jObject, 0) def load_function_argument(self, index): """ Convenience method. Loads function argument #index; note that @@ -786,9 +327,9 @@ self.prepare_generic_argument_with_jtype(jty) def prepare_generic_argument_with_jtype(self, jty): - if jty is jvmtype.jVoid: - self.emit(ACONST_NULL) - elif isinstance(jty, JvmScalarType): + if jty is jVoid: + self.emit(jvm.ACONST_NULL) + elif isinstance(jty, jvm.JvmScalarType): self.box_value(jty) def prepare_generic_result(self, ITEMTYPE): @@ -796,9 +337,9 @@ self.prepare_generic_result_with_jtype(jresty) def prepare_generic_result_with_jtype(self, jresty): - if jresty is jvmtype.jVoid: - self.emit(POP) - elif isinstance(jresty, JvmScalarType): + if jresty is jVoid: + self.emit(jvm.POP) + elif isinstance(jresty, jvm.JvmScalarType): # Perform any un-boxing required: self.downcast_jtype(jresty.box_type) self.unbox_value(jresty) @@ -810,20 +351,21 @@ """ Assuming that an value of type jscalartype is on the stack, boxes it into an Object. """ jclasstype = jscalartype.box_type - jmethod = Method.s(jclasstype, 'valueOf', (jscalartype,), jclasstype) + jmethod = jvm.Method.s( + jclasstype, 'valueOf', (jscalartype,), jclasstype) self.emit(jmethod) def unbox_value(self, jscalartype): """ Assuming that a boxed value of type jscalartype is on the stack, unboxes it. """ jclasstype = jscalartype.box_type - jmethod = Method.v( + jmethod = jvm.Method.v( jclasstype, jscalartype.unbox_method, (), jscalartype) self.emit(jmethod) def swap(self): """ Swaps the two words highest on the stack. """ - self.emit(SWAP) + self.emit(jvm.SWAP) # __________________________________________________________________ # Exception Handling @@ -869,14 +411,14 @@ _equals = { ootype.Void: (None,None), - ootype.SignedLongLong: (LCMP,IFEQ), - ootype.UnsignedLongLong: (LCMP,IFEQ), - ootype.Float: (DCMPG,IFEQ), - ootype.Signed: (None,IF_ICMPNE), - ootype.Unsigned: (None,IF_ICMPNE), - ootype.Bool: (None,IF_ICMPNE), - ootype.Char: (None,IF_ICMPNE), - ootype.UniChar: (None,IF_ICMPNE), + ootype.SignedLongLong: (jvm.LCMP, jvm.IFEQ), + ootype.UnsignedLongLong: (jvm.LCMP, jvm.IFEQ), + ootype.Float: (jvm.DCMPG, jvm.IFEQ), + ootype.Signed: (None,jvm.IF_ICMPNE), + ootype.Unsigned: (None,jvm.IF_ICMPNE), + ootype.Bool: (None,jvm.IF_ICMPNE), + ootype.Char: (None,jvm.IF_ICMPNE), + ootype.UniChar: (None,jvm.IF_ICMPNE), } def compare_values(self, OOTYPE, unequal_lbl): """ Assumes that two instances of OOTYPE are pushed on the stack; @@ -886,14 +428,14 @@ if i1: self.emit(i1) if i2: self.emit(i2, unequal_lbl) return - self.emit(OBJEQUALS) - self.emit(IFEQ, unequal_lbl) + self.emit(jvm.OBJEQUALS) + self.emit(jvm.IFEQ, unequal_lbl) _hash = { - ootype.Void: ICONST_0, - ootype.SignedLongLong: L2I, - ootype.UnsignedLongLong: L2I, - ootype.Float: D2I, + ootype.Void: jvm.ICONST_0, + ootype.SignedLongLong: jvm.L2I, + ootype.UnsignedLongLong: jvm.L2I, + ootype.Float: jvm.D2I, ootype.Signed: None, ootype.Unsigned: None, ootype.Bool: None, @@ -907,7 +449,7 @@ i1 = self._hash[OOTYPE] if i1: self.emit(i1) return - self.emit(OBJHASHCODE) + self.emit(jvm.OBJHASHCODE) # __________________________________________________________________ # Generator methods and others that are invoked by MicroInstructions @@ -919,16 +461,19 @@ it is the name of a method to invoke, or an Opcode/Method object (defined above).""" + if instr is None: + return + if isinstance(instr, str): return getattr(self, instr)(*args) - if isinstance(instr, Opcode): + if isinstance(instr, jvm.Opcode): return self._instr(instr, *args) - if isinstance(instr, Method): + if isinstance(instr, jvm.BaseMethod): return instr.invoke(self) - if isinstance(instr, Field) or isinstance(instr, Property): + if isinstance(instr, jvm.Field) or isinstance(instr, jvm.Property): return instr.load(self) raise Exception("Unknown object in call to emit(): "+repr(instr)) @@ -936,6 +481,7 @@ def _var_data(self, v): # Determine java type: jty = self.db.lltype_to_cts(v.concretetype) + import sys # Determine index in stack frame slots: # note that arguments and locals can be treated the same here return jty, self.curfunc.var_offset(v, jty) @@ -989,11 +535,11 @@ self.downcast_jtype(jtype) def downcast_jtype(self, jtype): - self._instr(CHECKCAST, jtype) + self._instr(jvm.CHECKCAST, jtype) def instanceof(self, TYPE): jtype = self.db.lltype_to_cts(TYPE) - self._instr(INSTANCEOF, jtype) + self._instr(jvm.INSTANCEOF, jtype) # included for compatibility with oosupport, but instanceof_jtype # follows our naming convention better @@ -1001,22 +547,22 @@ return self.instanceof_jtype(jtype) def instanceof_jtype(self, jtype): - self._instr(INSTANCEOF, jtype) + self._instr(jvm.INSTANCEOF, jtype) def branch_unconditionally(self, target_label): self.goto(target_label) def branch_conditionally(self, cond, target_label): if cond: - self._instr(IFNE, target_label) + self._instr(jvm.IFNE, target_label) else: - self._instr(IFEQ, target_label) + self._instr(jvm.IFEQ, target_label) def branch_if_equal(self, target_label): - self._instr(IF_ICMPEQ, target_label) + self._instr(jvm.IF_ICMPEQ, target_label) def branch_if_not_equal(self, target_label): - self._instr(IF_ICMPNE, target_label) + self._instr(jvm.IF_ICMPNE, target_label) def call_graph(self, graph): mthd = self.db.pending_function(graph) @@ -1028,7 +574,7 @@ mthd.invoke(self) # Check if we have to convert the result type at all: - gener = jvmtype.Generifier(OOCLASS) + gener = jvm.Generifier(OOCLASS) RETTYPE = gener.full_types(method_name)[1] jrettype = self.db.lltype_to_cts(RETTYPE) if jrettype != mthd.return_type: @@ -1043,7 +589,7 @@ # If necessary, load the ll_os object pointer instead: if module == 'll_os': - PYPYOS.load(self) + jvm.PYPYOS.load(self) def call_primitive(self, op, module, name): callee = op.args[0].value @@ -1052,7 +598,7 @@ # Determine what class the primitive is implemented in: if module == 'll_os': - jcls = jll_os + jcls = jvm.jll_os else: jcls = jPyPy @@ -1062,9 +608,9 @@ # the method cannot directly refer to the Java type in # .java source, as its name is not yet known. if jrettype.is_generated(): - mthd = Method.v(jcls, name, jargtypes, jObject) + mthd = jvm.Method.v(jcls, name, jargtypes, jvm.jObject) else: - mthd = Method.v(jcls, name, jargtypes, jrettype) + mthd = jvm.Method.v(jcls, name, jargtypes, jrettype) # Invoke the method self.emit(mthd) @@ -1081,13 +627,13 @@ cts_type = self.db.lltype_to_cts(OOTYPE) # treat all objects the same: - if isinstance(cts_type, jvmtype.JvmClassType): - cts_type = jObject + if isinstance(cts_type, jvm.JvmClassType): + cts_type = jvm.jObject - mthd = Method.v(jPyPy, 'oostring', [cts_type, jInt], jString) + mthd = jvm.Method.v(jPyPy, 'oostring', [cts_type, jInt], jString) self.emit(mthd) if self.db.using_byte_array: - self.emit(PYPYSTRING2BYTES) + self.emit(jvm.PYPYSTRING2BYTES) def prepare_call_oounicode(self, OOTYPE): # Load the PyPy object pointer onto the stack: @@ -1095,10 +641,10 @@ def call_oounicode(self, OOTYPE): cts_type = self.db.lltype_to_cts(OOTYPE) - mthd = Method.v(jPyPy, 'oounicode', [cts_type], jString) + mthd = jvm.Method.v(jPyPy, 'oounicode', [cts_type], jString) self.emit(mthd) if self.db.using_byte_array: - self.emit(PYPYSTRING2BYTES) + self.emit(jvm.PYPYSTRING2BYTES) def new(self, TYPE): jtype = self.db.lltype_to_cts(TYPE) @@ -1106,38 +652,43 @@ def new_with_jtype(self, jtype, ctor=None): if ctor is None: - ctor = Method.c(jtype, ()) - self.emit(NEW, jtype) - self.emit(DUP) + ctor = jvm.Method.c(jtype, ()) + self.emit(jvm.NEW, jtype) + self.emit(jvm.DUP) self.emit(ctor) + def oonewarray(self, TYPE, length): + jtype = self.db.lltype_to_cts(TYPE) + self.load(length) + jtype.make(self) + def instantiate(self): - self.emit(PYPYRUNTIMENEW) + self.emit(jvm.PYPYRUNTIMENEW) def getclassobject(self, OOINSTANCE): - jvmtype = self.db.lltype_to_cts(OOINSTANCE) - self.load_string(jvmtype.name) - CLASSFORNAME.invoke(self) + jtype = self.db.lltype_to_cts(OOINSTANCE) + self.load_string(jtype.name) + jvm.CLASSFORNAME.invoke(self) def dup(self, OOTYPE): - jvmtype = self.db.lltype_to_cts(OOTYPE) - self.dup_jtype(jvmtype) + jtype = self.db.lltype_to_cts(OOTYPE) + self.dup_jtype(jtype) - def dup_jtype(self, jvmtype): - if jvmtype.descriptor.type_width() == 1: - self.emit(DUP) + def dup_jtype(self, jtype): + if jtype.descriptor.type_width() == 1: + self.emit(jvm.DUP) else: - self.emit(DUP2) + self.emit(jvm.DUP2) def pop(self, OOTYPE): - jvmtype = self.db.lltype_to_cts(OOTYPE) - if jvmtype.descriptor.type_width() == 1: - self.emit(POP) + jtype = self.db.lltype_to_cts(OOTYPE) + if jtype.descriptor.type_width() == 1: + self.emit(jvm.POP) else: - self.emit(POP2) + self.emit(jvm.POP2) def push_null(self, OOTYPE): - self.emit(ACONST_NULL) + self.emit(jvm.ACONST_NULL) # we can't assume MALLOC_ZERO_FILLED, because for scalar type the # default item for ArrayList is null, not e.g. Integer(0) or @@ -1150,16 +701,16 @@ if TYPE is ootype.Void: return elif isinstance(value, CDefinedIntSymbolic): - self.emit(ICONST, self.DEFINED_INT_SYMBOLICS[value.expr]) + self.emit(jvm.ICONST, self.DEFINED_INT_SYMBOLICS[value.expr]) elif TYPE in (ootype.Bool, ootype.Signed): - self.emit(ICONST, int(value)) + self.emit(jvm.ICONST, int(value)) elif TYPE is ootype.Unsigned: # Converts the unsigned int into its corresponding signed value: if value > 0x7FFFFFFF: value = -((int(value) ^ 0xFFFFFFFF)+1) - self.emit(ICONST, value) + self.emit(jvm.ICONST, value) elif TYPE is ootype.Char or TYPE is ootype.UniChar: - self.emit(ICONST, ord(value)) + self.emit(jvm.ICONST, ord(value)) elif TYPE is ootype.SignedLongLong: self._push_long_constant(long(value)) elif TYPE is ootype.UnsignedLongLong: @@ -1171,7 +722,7 @@ self._push_double_constant(float(value)) elif TYPE in (ootype.String, ootype.Unicode): if value == ootype.null(TYPE): - self.emit(ACONST_NULL) + self.emit(jvm.ACONST_NULL) else: self.load_string(value._str) else: @@ -1179,25 +730,25 @@ def _push_long_constant(self, value): if value == 0: - self.emit(LCONST_0) + self.emit(jvm.LCONST_0) elif value == 1: - self.emit(LCONST_1) + self.emit(jvm.LCONST_1) else: - self.emit(LDC2, value) + self.emit(jvm.LDC2, value) def _push_double_constant(self, value): if isnan(value): - DOUBLENAN.load(self) + jvm.DOUBLENAN.load(self) elif isinf(value): - if value > 0: DOUBLEPOSINF.load(self) - else: DOUBLENEGINF.load(self) + if value > 0: jvm.DOUBLEPOSINF.load(self) + else: jvm.DOUBLENEGINF.load(self) elif value == 0.0: - self.emit(DCONST_0) + self.emit(jvm.DCONST_0) elif value == 1.0: - self.emit(DCONST_1) + self.emit(jvm.DCONST_1) else: # Big hack to avoid exponential notation: - self.emit(LDC2, "%22.22f" % value) + self.emit(jvm.LDC2, "%22.22f" % value) def create_weakref(self, OOTYPE): """ @@ -1207,7 +758,7 @@ The result will be that at the top of the stack is a weak reference. """ self.prepare_generic_argument(OOTYPE) - self.emit(PYPYWEAKREFCREATE) + self.emit(jvm.PYPYWEAKREFCREATE) def deref_weakref(self, OOTYPE): """ @@ -1215,7 +766,7 @@ that this weak ref is a pointer to. OOTYPE is the kind of object you had a weak reference to. """ - self.emit(PYPYWEAKREFGET) + self.emit(jvm.PYPYWEAKREFGET) self.prepare_generic_result(OOTYPE) # __________________________________________________________________ @@ -1223,30 +774,30 @@ def throw(self): """ Throw the object from top of the stack as an exception """ - self._instr(ATHROW) + self._instr(jvm.ATHROW) def iabs(self): - MATHIABS.invoke(self) + jvm.MATHIABS.invoke(self) def dbl_abs(self): - MATHDABS.invoke(self) + jvm.MATHDABS.invoke(self) def bitwise_negate(self): """ Invert all the bits in the "int" on the top of the stack """ - self._instr(ICONST, -1) - self._instr(IXOR) + self._instr(jvm.ICONST, -1) + self._instr(jvm.IXOR) def goto(self, label): """ Jumps unconditionally """ - self._instr(GOTO, label) + self._instr(jvm.GOTO, label) def goto_if_true(self, label): """ Jumps if the top of stack is true """ - self._instr(IFNE, label) + self._instr(jvm.IFNE, label) def goto_if_false(self, label): """ Jumps if the top of stack is false """ - self._instr(IFEQ, label) + self._instr(jvm.IFEQ, label) class JasminGenerator(JVMGenerator): Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/metavm.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/metavm.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/metavm.py Fri Apr 4 13:18:57 2008 @@ -1,8 +1,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.metavm import MicroInstruction from pypy.translator.jvm.typesystem import JvmScalarType, JvmClassType -import pypy.translator.jvm.generator as jvmgen -import pypy.translator.jvm.typesystem as jvmtype +import pypy.translator.jvm.typesystem as jvm from pypy.translator.jvm.builtin import JvmBuiltInType from pypy.translator.jvm import cmpopcodes @@ -86,13 +85,13 @@ def render(self, generator, op): self._load_func(generator, *op.args[1:4]) self._load_func(generator, *op.args[4:7]) - generator.emit(jvmgen.CUSTOMDICTMAKE) + generator.emit(jvm.CUSTOMDICTMAKE) NewCustomDict = _NewCustomDict() CASTS = { # FROM TO - (ootype.Signed, ootype.UnsignedLongLong): jvmgen.I2L, - (ootype.SignedLongLong, ootype.Signed): jvmgen.L2I, + (ootype.Signed, ootype.UnsignedLongLong): jvm.I2L, + (ootype.SignedLongLong, ootype.Signed): jvm.L2I, (ootype.UnsignedLongLong, ootype.SignedLongLong): None, } @@ -118,9 +117,9 @@ truelbl = generator.unique_label('load_comparision_result_true') endlbl = generator.unique_label('load_comparision_result_end') cmpopcodes.branch_if(generator, op.opname, truelbl) - generator.emit(jvmgen.ICONST, 0) + generator.emit(jvm.ICONST, 0) generator.goto(endlbl) generator.mark(truelbl) - generator.emit(jvmgen.ICONST, 1) + generator.emit(jvm.ICONST, 1) generator.mark(endlbl) PushComparisonResult = _PushComparisonResult() Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/methods.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/methods.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/methods.py Fri Apr 4 13:18:57 2008 @@ -7,8 +7,7 @@ """ -import pypy.translator.jvm.generator as jvmgen -import pypy.translator.jvm.typesystem as jvmtype +import pypy.translator.jvm.typesystem as jvm from pypy.rpython.ootypesystem import ootype, rclass class BaseDumpMethod(object): @@ -19,7 +18,7 @@ self.clsobj = clsobj self.name = "toString" self.jargtypes = [clsobj] - self.jrettype = jvmtype.jString + self.jrettype = jvm.jString def _print_field_value(self, fieldnm, FIELDOOTY): self.gen.load_this_ptr() @@ -27,21 +26,21 @@ fieldobj.load(self.gen) dumpmethod = self.db.toString_method_for_ootype(FIELDOOTY) self.gen.emit(dumpmethod) - self.gen.emit(jvmgen.STRINGBUILDERAPPEND) + self.gen.emit(jvm.STRINGBUILDERAPPEND) def _print(self, str): self.gen.load_string(str) - self.gen.emit(jvmgen.STRINGBUILDERAPPEND) + self.gen.emit(jvm.STRINGBUILDERAPPEND) def render(self, gen): self.gen = gen gen.begin_function( self.name, (), self.jargtypes, self.jrettype, static=False) - gen.new_with_jtype(jvmtype.jStringBuilder) + gen.new_with_jtype(jvm.jStringBuilder) self._render_guts(gen) - gen.emit(jvmgen.OBJTOSTRING) - gen.emit(jvmgen.RETURN.for_type(jvmtype.jString)) + gen.emit(jvm.OBJTOSTRING) + gen.emit(jvm.RETURN.for_type(jvm.jString)) gen.end_function() self.gen = None @@ -117,8 +116,8 @@ self.OOCLASS = OOCLASS self.clsobj = clsobj self.name = "equals" - self.jargtypes = [clsobj, jvmtype.jObject] - self.jrettype = jvmtype.jBool + self.jargtypes = [clsobj, jvm.jObject] + self.jrettype = jvm.jBool def render(self, gen): self.gen = gen @@ -156,10 +155,10 @@ # Return true or false as appropriate gen.push_primitive_constant(ootype.Bool, True) - gen.return_val(jvmtype.jBool) + gen.return_val(jvm.jBool) gen.mark(unequal_lbl) gen.push_primitive_constant(ootype.Bool, False) - gen.return_val(jvmtype.jBool) + gen.return_val(jvm.jBool) gen.end_function() @@ -171,7 +170,7 @@ self.clsobj = clsobj self.name = "hashCode" self.jargtypes = [clsobj] - self.jrettype = jvmtype.jInt + self.jrettype = jvm.jInt def render(self, gen): self.gen = gen @@ -194,10 +193,10 @@ gen.hash_value(FIELDOOTY) # XOR that with the main hash - gen.emit(jvmgen.IXOR) + gen.emit(jvm.IXOR) # Return the final hash - gen.return_val(jvmtype.jInt) + gen.return_val(jvm.jInt) gen.end_function() Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/node.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/node.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/node.py Fri Apr 4 13:18:57 2008 @@ -39,8 +39,7 @@ from pypy.translator.jvm.cmpopcodes import \ can_branch_directly, branch_if -import py -import pypy.translator.jvm.generator as jvmgen +import pypy.translator.jvm.typesystem as jvm import pypy.translator.jvm.typesystem as jvmtype from pypy.translator.jvm.log import log @@ -86,14 +85,14 @@ # XXX --- perhaps this table would be better placed in typesystem.py # so as to constrain the knowledge of lltype and ootype _type_conversion_methods = { - ootype.Signed:jvmgen.PYPYSTRTOINT, - ootype.Unsigned:jvmgen.PYPYSTRTOUINT, - lltype.SignedLongLong:jvmgen.PYPYSTRTOLONG, - lltype.UnsignedLongLong:jvmgen.PYPYSTRTOULONG, - ootype.Bool:jvmgen.PYPYSTRTOBOOL, - ootype.Float:jvmgen.PYPYSTRTODOUBLE, - ootype.Char:jvmgen.PYPYSTRTOCHAR, - ootype.UniChar:jvmgen.PYPYSTRTOCHAR, + ootype.Signed:jvm.PYPYSTRTOINT, + ootype.Unsigned:jvm.PYPYSTRTOUINT, + lltype.SignedLongLong:jvm.PYPYSTRTOLONG, + lltype.UnsignedLongLong:jvm.PYPYSTRTOULONG, + ootype.Bool:jvm.PYPYSTRTOBOOL, + ootype.Float:jvm.PYPYSTRTODOUBLE, + ootype.Char:jvm.PYPYSTRTOCHAR, + ootype.UniChar:jvm.PYPYSTRTOCHAR, ootype.String:None } @@ -109,14 +108,13 @@ # # 2. Run the initialization method for the constant class. # - gen.begin_function( - '', (), [], jVoid, static=True) - gen.emit(jvmgen.NEW, jPyPy) - gen.emit(jvmgen.DUP) + gen.begin_function('', (), [], jVoid, static=True) + gen.emit(jvm.NEW, jPyPy) + gen.emit(jvm.DUP) gen.new_with_jtype(gen.db.jInterlinkImplementation) - gen.emit(jvmgen.DUP) + gen.emit(jvm.DUP) gen.db.interlink_field.store(gen) - gen.emit(jvmgen.Method.c(jPyPy, [jPyPyInterlink])) + gen.emit(jvm.Method.c(jPyPy, [jPyPyInterlink])) gen.db.pypy_field.store(gen) gen.db.constant_generator.runtime_init(gen) gen.return_val(jVoid) @@ -143,7 +141,7 @@ conv = self._type_conversion_methods[arg.concretetype] if conv: gen.push_pypy() gen.load_jvm_var(jStringArray, 0) - gen.emit(jvmgen.ICONST, i) + gen.emit(jvm.ICONST, i) gen.load_from_array(jString) if conv: gen.emit(conv) else: @@ -151,9 +149,9 @@ # python method expects arg0 = self.graph.getargs()[0] assert isinstance(arg0.concretetype, ootype.List), str(arg0.concretetype) - assert arg0.concretetype._ITEMTYPE is ootype.String + assert arg0.concretetype.ITEM is ootype.String gen.load_jvm_var(jStringArray, 0) - gen.emit(jvmgen.PYPYARRAYTOLIST) + gen.emit(jvm.PYPYARRAYTOLIST) # Generate a call to this method gen.emit(self.db.pending_function(self.graph)) @@ -171,13 +169,13 @@ gen.add_comment('Invoking dump method for result of type ' +str(RESOOTYPE)) gen.emit(dumpmethod) # generate the string - gen.emit(jvmgen.PYPYDUMP) # dump to stdout + gen.emit(jvm.PYPYDUMP) # dump to stdout gen.goto(done_printing) gen.end_try() jexc = self.db.exception_root_object() gen.begin_catch(jexc) - gen.emit(jvmgen.PYPYDUMPEXCWRAPPER) # dumps to stdout + gen.emit(jvm.PYPYDUMPEXCWRAPPER) # dumps to stdout gen.end_catch() gen.mark(done_printing) @@ -198,12 +196,12 @@ name = None def render(self, gen): - """ Uses the gen argument, a jvmgen.Generator, to create the + """ Uses the gen argument, a jvm.Generator, to create the appropriate JVM assembly for this method. """ raise NotImplementedError def method(self): - """ Returns a jvmgen.Method object that would allow this + """ Returns a jvm.Method object that would allow this function to be invoked. """ raise NotImplementedError @@ -272,12 +270,12 @@ return self.generator.unique_label(prefix) def method(self): - """ Returns a jvmgen.Method that can invoke this function """ + """ Returns a jvm.Method that can invoke this function """ if not self.is_method: - ctor = jvmgen.Method.s + ctor = jvm.Method.s startidx = 0 else: - ctor = jvmgen.Method.v + ctor = jvm.Method.v startidx = 1 return ctor(self.classty, self.name, self.jargtypes[startidx:], self.jrettype) @@ -359,11 +357,11 @@ # exception to be caught by the normal handlers. self.ilasm.begin_catch(jexcty) self.ilasm.push_interlink() - interlink_method = jvmgen.Method.v( + interlink_method = jvm.Method.v( jPyPyInterlink, "throw"+pyexccls.__name__, [], jVoid) self.ilasm.emit(interlink_method) - self.ilasm.emit(jvmgen.ACONST_NULL) - self.ilasm.emit(jvmgen.ATHROW) + self.ilasm.emit(jvm.ACONST_NULL) # "inform" the verifier... + self.ilasm.emit(jvm.ATHROW) # ...that we throw here self.ilasm.end_try() def begin_catch(self, llexitcase): @@ -386,7 +384,7 @@ else: # the exception value is on the stack, store it in the proper place if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.emit(jvmgen.DUP) + self.ilasm.emit(jvm.DUP) self.ilasm.store(link.last_exc_value) fld = self.db.lltype_to_cts(rclass.OBJECT).lookup_field('meta') self.ilasm.emit(fld) @@ -517,9 +515,9 @@ def _trace(self, str, writeline=False): if writeline: str += '\n' - jvmgen.SYSTEMERR.load(self.generator) + jvm.SYSTEMERR.load(self.generator) self.generator.load_string(str) - jvmgen.PRINTSTREAMPRINTSTR.invoke(self.generator) + jvm.PRINTSTREAMPRINTSTR.invoke(self.generator) def _is_printable(self, res): @@ -554,10 +552,10 @@ res.concretetype) self._trace(" "+prompt+": ") - self.generator.emit(jvmgen.SYSTEMERR) + self.generator.emit(jvm.SYSTEMERR) self.generator.load(res) self.generator.emit(jmethod) - self.generator.emit(jvmgen.PRINTSTREAMPRINTSTR) + self.generator.emit(jvm.PRINTSTREAMPRINTSTR) self._trace("\n") def _trace_enabled(self): @@ -596,7 +594,7 @@ self.java_return_type = jrettype self.dump_method = ConstantStringDumpMethod( self, "StaticMethodInterface") - self.invoke_method_obj = jvmgen.Method.v( + self.invoke_method_obj = jvm.Method.v( self, 'invoke', self.java_argument_types[1:], self.java_return_type) @@ -604,7 +602,7 @@ raise KeyError(fieldnm) # no fields def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + """ Given the method name, returns a jvm.Method object """ assert isinstance(self.java_return_type, JvmType) if methodnm == 'invoke': return self.invoke_method_obj @@ -698,9 +696,9 @@ if bound_to_jty: self.bound_to_jty = bound_to_jty - self.bound_to_fld = jvmgen.Field( + self.bound_to_fld = jvm.Field( self.name, 'bound_to', bound_to_jty, False) - self.bind_method = jvmgen.Method.s( + self.bind_method = jvm.Method.s( self, 'bind', (self.bound_to_jty,), self) else: self.bound_to_jty = None @@ -731,7 +729,7 @@ gen.begin_function( 'bind', [], (self.bound_to_jty,), self, static=True) gen.new_with_jtype(self) - gen.emit(jvmgen.DUP) + gen.emit(jvm.DUP) gen.load_jvm_var(self.bound_to_jty, 0) self.bound_to_fld.store(gen) gen.return_val(self) @@ -810,10 +808,10 @@ """ JvmGeneratedClassType.__init__(self, name) self.rendered = False # has rendering occurred? - self.fields = {} # maps field name to jvmgen.Field object + self.fields = {} # maps field name to jvm.Field object self.interfaces = [] # list of JvmTypes self.methods = {} # maps method name to a Function object* - self.abstract_methods = {} # maps method name to jvmgen.Method object + self.abstract_methods = {} # maps method name to jvm.Method object self.set_super_class(supercls) # * --- actually maps to an object that defines the @@ -833,9 +831,9 @@ self.throwable = True def add_field(self, fieldobj, fielddef): - """ Creates a new field accessed via the jvmgen.Field + """ Creates a new field accessed via the jvm.Field descriptor 'fieldobj'. Must be called before render().""" - assert not self.rendered and isinstance(fieldobj, jvmgen.Field) + assert not self.rendered and isinstance(fieldobj, jvm.Field) self.fields[fieldobj.field_name] = (fieldobj, fielddef) def add_interface(self, inter): @@ -848,7 +846,7 @@ return self.super_class.lookup_field(fieldnm) def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + """ Given the method name, returns a jvm.Method object """ if methodnm in self.methods: return self.methods[methodnm].method() if methodnm in self.abstract_methods: @@ -864,7 +862,7 @@ def add_abstract_method(self, jmethod): """ Adds an abstract method to our list of methods; jmethod should - be a jvmgen.Method object """ + be a jvm.Method object """ assert jmethod.method_name not in self.methods self.abstract_methods[jmethod.method_name] = jmethod @@ -912,7 +910,7 @@ """ interlink: the JvmType of the Interlink implementation name: the name of the method - helper: a jvmgen.Method object for the helper func we should invoke + helper: a jvm.Method object for the helper func we should invoke """ self.interlink = interlink self.name = name @@ -926,7 +924,7 @@ else: self.return_type = self.helper.return_type - self.method_obj = jvmgen.Method.v(interlink, + self.method_obj = jvm.Method.v(interlink, self.name, self.helper.argument_types, self.return_type) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/opcodes.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/opcodes.py Fri Apr 4 13:18:57 2008 @@ -6,7 +6,7 @@ """ from pypy.translator.oosupport.metavm import \ - PushArg, PushAllArgs, StoreResult, InstructionList, New, DoNothing, Call,\ + PushArg, PushAllArgs, StoreResult, InstructionList, New, OONewArray, DoNothing, Call,\ SetField, GetField, DownCast, RuntimeNew, OOString, OOUnicode, \ CastTo, PushPrimitive from pypy.translator.jvm.metavm import \ @@ -15,19 +15,18 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.cmpopcodes import cmp_opname -import pypy.translator.jvm.generator as jvmgen -import pypy.translator.jvm.typesystem as jvmtype +import pypy.translator.jvm.typesystem as jvm def _proc(val): if isinstance(val, list): # Lists of instructions we leave alone: return InstructionList(val) - elif isinstance(val, jvmgen.Method) and not val.is_static(): + elif isinstance(val, jvm.Method) and not val.is_static(): # For virtual methods, we first push an instance of the relevant # class, then the arguments, and then invoke the method. Note # that we only allow virtual methods of certain pre-designated # classes to be in the table. - if val.class_name == jvmtype.jPyPy.name: + if val.class_name == jvm.jPyPy.name: return InstructionList( (PushPyPy, PushAllArgs, val, StoreResult)) else: @@ -71,6 +70,7 @@ opcodes = _proc_dict({ # __________ object oriented operations __________ 'new': [New, StoreResult], + 'oonewarray': [OONewArray, StoreResult], 'runtimenew': [RuntimeNew, StoreResult], 'oosetfield': [SetField], 'oogetfield': [GetField, StoreResult], @@ -78,19 +78,19 @@ 'ooupcast': DoNothing, 'oodowncast': [DownCast, StoreResult], 'instanceof': [CastTo, StoreResult], - 'subclassof': [PushAllArgs, jvmgen.SWAP, jvmgen.CLASSISASSIGNABLEFROM, StoreResult], - 'ooidentityhash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], - 'oohash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], + 'subclassof': [PushAllArgs, jvm.SWAP, jvm.CLASSISASSIGNABLEFROM, StoreResult], + 'ooidentityhash': [PushAllArgs, jvm.OBJHASHCODE, StoreResult], + 'oohash': [PushAllArgs, jvm.OBJHASHCODE, StoreResult], 'oostring': [OOString, StoreResult], 'oounicode': [OOUnicode, StoreResult], - 'ooparse_float': jvmgen.PYPYOOPARSEFLOAT, + 'ooparse_float': jvm.PYPYOOPARSEFLOAT, 'oonewcustomdict': [NewCustomDict, StoreResult], 'same_as': DoNothing, 'hint': [PushArg(0), StoreResult], 'direct_call': [Call, StoreResult], 'indirect_call': [PushAllArgs, IndirectCall, StoreResult], - 'gc__collect': jvmgen.SYSTEMGC, + 'gc__collect': jvm.SYSTEMGC, 'gc_set_max_heap_size': Ignore, 'resume_point': Ignore, @@ -100,100 +100,100 @@ 'bool_not': 'logical_not', - 'int_neg': jvmgen.INEG, - 'int_neg_ovf': jvmgen.INEGOVF, + 'int_neg': jvm.INEG, + 'int_neg_ovf': jvm.INEGOVF, 'int_abs': 'iabs', - 'int_abs_ovf': jvmgen.IABSOVF, + 'int_abs_ovf': jvm.IABSOVF, 'int_invert': 'bitwise_negate', - 'int_add': jvmgen.IADD, - 'int_sub': jvmgen.ISUB, - 'int_mul': jvmgen.IMUL, - 'int_floordiv': jvmgen.IDIV, - 'int_floordiv_zer': _check_zer(jvmgen.IDIV), - 'int_mod': jvmgen.IREM, - 'int_and': jvmgen.IAND, - 'int_or': jvmgen.IOR, - 'int_lshift': jvmgen.ISHL, - 'int_rshift': jvmgen.ISHR, - 'int_xor': jvmgen.IXOR, - 'int_add_ovf': jvmgen.IADDOVF, - 'int_add_nonneg_ovf': jvmgen.IADDOVF, - 'int_sub_ovf': jvmgen.ISUBOVF, - 'int_mul_ovf': jvmgen.IMULOVF, - 'int_floordiv_ovf': jvmgen.IDIV, # these can't overflow! - 'int_mod_zer': _check_zer(jvmgen.IREM), - 'int_mod_ovf': jvmgen.IREMOVF, - 'int_and_ovf': jvmgen.IAND, - 'int_or_ovf': jvmgen.IOR, - - 'int_lshift_ovf': jvmgen.ISHLOVF, - 'int_lshift_ovf_val': jvmgen.ISHLOVF, # VAL... what is val used for?? - - 'int_rshift_ovf': jvmgen.ISHR, # these can't overflow! - 'int_xor_ovf': jvmgen.IXOR, - 'int_floordiv_ovf_zer': _check_zer(jvmgen.IDIV), - 'int_mod_ovf_zer': _check_zer(jvmgen.IREMOVF), + 'int_add': jvm.IADD, + 'int_sub': jvm.ISUB, + 'int_mul': jvm.IMUL, + 'int_floordiv': jvm.IDIV, + 'int_floordiv_zer': _check_zer(jvm.IDIV), + 'int_mod': jvm.IREM, + 'int_and': jvm.IAND, + 'int_or': jvm.IOR, + 'int_lshift': jvm.ISHL, + 'int_rshift': jvm.ISHR, + 'int_xor': jvm.IXOR, + 'int_add_ovf': jvm.IADDOVF, + 'int_add_nonneg_ovf': jvm.IADDOVF, + 'int_sub_ovf': jvm.ISUBOVF, + 'int_mul_ovf': jvm.IMULOVF, + 'int_floordiv_ovf': jvm.IDIV, # these can't overflow! + 'int_mod_zer': _check_zer(jvm.IREM), + 'int_mod_ovf': jvm.IREMOVF, + 'int_and_ovf': jvm.IAND, + 'int_or_ovf': jvm.IOR, + + 'int_lshift_ovf': jvm.ISHLOVF, + 'int_lshift_ovf_val': jvm.ISHLOVF, # VAL... what is val used for?? + + 'int_rshift_ovf': jvm.ISHR, # these can't overflow! + 'int_xor_ovf': jvm.IXOR, + 'int_floordiv_ovf_zer': _check_zer(jvm.IDIV), + 'int_mod_ovf_zer': _check_zer(jvm.IREMOVF), 'uint_invert': 'bitwise_negate', - 'uint_add': jvmgen.IADD, - 'uint_sub': jvmgen.ISUB, - 'uint_mul': jvmgen.PYPYUINTMUL, - 'uint_div': jvmgen.PYPYUINTDIV, + 'uint_add': jvm.IADD, + 'uint_sub': jvm.ISUB, + 'uint_mul': jvm.PYPYUINTMUL, + 'uint_div': jvm.PYPYUINTDIV, 'uint_truediv': None, # TODO - 'uint_floordiv': jvmgen.PYPYUINTDIV, - 'uint_mod': jvmgen.PYPYUINTMOD, - 'uint_and': jvmgen.IAND, - 'uint_or': jvmgen.IOR, - 'uint_lshift': jvmgen.ISHL, - 'uint_rshift': jvmgen.IUSHR, - 'uint_xor': jvmgen.IXOR, + 'uint_floordiv': jvm.PYPYUINTDIV, + 'uint_mod': jvm.PYPYUINTMOD, + 'uint_and': jvm.IAND, + 'uint_or': jvm.IOR, + 'uint_lshift': jvm.ISHL, + 'uint_rshift': jvm.IUSHR, + 'uint_xor': jvm.IXOR, - 'float_neg': jvmgen.DNEG, + 'float_neg': jvm.DNEG, 'float_abs': 'dbl_abs', - 'float_add': jvmgen.DADD, - 'float_sub': jvmgen.DSUB, - 'float_mul': jvmgen.DMUL, - 'float_truediv': jvmgen.DDIV, - - 'llong_neg': jvmgen.LNEG, - 'llong_neg_ovf': jvmgen.LNEGOVF, - 'llong_abs': jvmgen.MATHLABS, - 'llong_abs_ovf': jvmgen.LABSOVF, - 'llong_invert': jvmgen.PYPYLONGBITWISENEGATE, - - 'llong_add': jvmgen.LADD, - 'llong_sub': jvmgen.LSUB, - 'llong_mul': jvmgen.LMUL, - 'llong_div': jvmgen.LDIV, + 'float_add': jvm.DADD, + 'float_sub': jvm.DSUB, + 'float_mul': jvm.DMUL, + 'float_truediv': jvm.DDIV, + + 'llong_neg': jvm.LNEG, + 'llong_neg_ovf': jvm.LNEGOVF, + 'llong_abs': jvm.MATHLABS, + 'llong_abs_ovf': jvm.LABSOVF, + 'llong_invert': jvm.PYPYLONGBITWISENEGATE, + + 'llong_add': jvm.LADD, + 'llong_sub': jvm.LSUB, + 'llong_mul': jvm.LMUL, + 'llong_div': jvm.LDIV, 'llong_truediv': None, # TODO - 'llong_floordiv': jvmgen.LDIV, - 'llong_floordiv_zer': _check_zer(jvmgen.LDIV), - 'llong_mod': jvmgen.LREM, - 'llong_mod_zer': _check_zer(jvmgen.LREM), - 'llong_and': jvmgen.LAND, - 'llong_or': jvmgen.LOR, - 'llong_lshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult], # XXX - do we care about shifts of >(1<<32) bits?? - 'llong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHR, StoreResult], - 'llong_xor': jvmgen.LXOR, - 'llong_floordiv_ovf': jvmgen.LDIV, # these can't overflow! - 'llong_mod_ovf': jvmgen.LREMOVF, - 'llong_lshift_ovf': jvmgen.LSHLOVF, - - 'ullong_invert': jvmgen.PYPYLONGBITWISENEGATE, - - 'ullong_add': jvmgen.LADD, - 'ullong_sub': jvmgen.LSUB, - 'ullong_mul': jvmgen.LMUL, - 'ullong_div': jvmgen.LDIV, # valid? + 'llong_floordiv': jvm.LDIV, + 'llong_floordiv_zer': _check_zer(jvm.LDIV), + 'llong_mod': jvm.LREM, + 'llong_mod_zer': _check_zer(jvm.LREM), + 'llong_and': jvm.LAND, + 'llong_or': jvm.LOR, + 'llong_lshift': [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult], + 'llong_rshift': [PushAllArgs, jvm.L2I, jvm.LSHR, StoreResult], + 'llong_xor': jvm.LXOR, + 'llong_floordiv_ovf': jvm.LDIV, # these can't overflow! + 'llong_mod_ovf': jvm.LREMOVF, + 'llong_lshift_ovf': jvm.LSHLOVF, + + 'ullong_invert': jvm.PYPYLONGBITWISENEGATE, + + 'ullong_add': jvm.LADD, + 'ullong_sub': jvm.LSUB, + 'ullong_mul': jvm.LMUL, + 'ullong_div': jvm.LDIV, # valid? 'ullong_truediv': None, # TODO - 'ullong_floordiv': jvmgen.LDIV, # valid? - 'ullong_mod': jvmgen.PYPYULONGMOD, - 'ullong_lshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult], - 'ullong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LUSHR, StoreResult], - 'ullong_mod_zer': jvmgen.PYPYULONGMOD, + 'ullong_floordiv': jvm.LDIV, # valid? + 'ullong_mod': jvm.PYPYULONGMOD, + 'ullong_lshift': [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult], + 'ullong_rshift': [PushAllArgs, jvm.L2I, jvm.LUSHR, StoreResult], + 'ullong_mod_zer': jvm.PYPYULONGMOD, # when casting from bool we want that every truth value is casted # to 1: we can't simply DoNothing, because the CLI stack could @@ -201,21 +201,21 @@ # trick. #THIS COMMENT NEEDS TO BE VALIDATED AND UPDATED 'cast_bool_to_int': DoNothing, 'cast_bool_to_uint': DoNothing, - 'cast_bool_to_float': jvmgen.PYPYBOOLTODOUBLE, #PAUL, inefficient + 'cast_bool_to_float': jvm.PYPYBOOLTODOUBLE, #PAUL, inefficient 'cast_char_to_int': DoNothing, 'cast_unichar_to_int': DoNothing, 'cast_int_to_char': DoNothing, 'cast_int_to_unichar': DoNothing, 'cast_int_to_uint': DoNothing, - 'cast_int_to_float': jvmgen.I2D, - 'cast_int_to_longlong': jvmgen.I2L, + 'cast_int_to_float': jvm.I2D, + 'cast_int_to_longlong': jvm.I2L, 'cast_uint_to_int': DoNothing, - 'cast_uint_to_float': jvmgen.PYPYUINTTODOUBLE, - 'cast_float_to_int': jvmgen.D2I, - 'cast_float_to_longlong': jvmgen.PYPYDOUBLETOLONG, #PAUL - 'cast_float_to_uint': jvmgen.PYPYDOUBLETOUINT, - 'truncate_longlong_to_int': jvmgen.L2I, - 'cast_longlong_to_float': jvmgen.L2D, + 'cast_uint_to_float': jvm.PYPYUINTTODOUBLE, + 'cast_float_to_int': jvm.D2I, + 'cast_float_to_longlong': jvm.PYPYDOUBLETOLONG, #PAUL + 'cast_float_to_uint': jvm.PYPYDOUBLETOUINT, + 'truncate_longlong_to_int': jvm.L2I, + 'cast_longlong_to_float': jvm.L2D, 'cast_primitive': [PushAllArgs, CastPrimitive, StoreResult], 'is_early_constant': [PushPrimitive(ootype.Bool, False), StoreResult] Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/prebuiltnodes.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/prebuiltnodes.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/prebuiltnodes.py Fri Apr 4 13:18:57 2008 @@ -57,7 +57,7 @@ def create_interlink_node(db): """ Translates the create_interlink_impl() function and returns - a jvmgen.Method object that allows it to be called. """ + a jvm.Method object that allows it to be called. """ translator = db.genoo.translator for func, type_list in HELPERS.items(): Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/PyPy.java ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/PyPy.java (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/PyPy.java Fri Apr 4 13:18:57 2008 @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Map; import java.text.DecimalFormat; +import java.lang.reflect.Array; /** * Class with a number of utility routines. One instance of this is @@ -407,7 +408,16 @@ sb.append("]"); return sb.toString(); } - else if (o instanceof String) { + if (o.getClass().isArray()) { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < Array.getLength(o); i++) { + sb.append(serializeObject(Array.get(o, i))).append(","); + } + sb.append("]"); + return sb.toString(); + } + if (o instanceof String) { return escaped_string((String)o); } return o.toString(); @@ -731,7 +741,7 @@ return str.substring(start, end); } - public static ArrayList ll_split_chr(String str, char c) { + public static Object[] ll_split_chr(String str, char c) { ArrayList list = new ArrayList(); int lastidx = 0, idx = 0; while ((idx = str.indexOf(c, lastidx)) != -1) @@ -741,7 +751,7 @@ lastidx = idx+1; } list.add(str.substring(lastidx)); - return list; + return list.toArray(new String[list.size()]); } public static String ll_substring(String str, int start, int cnt) { Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_class.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_class.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_class.py Fri Apr 4 13:18:57 2008 @@ -24,7 +24,8 @@ assert self.interpret(fn, [2]) == 42 - + def test_specialize_methods(self): + py.test.skip('ABSTRACT METHOD FIX: RE-TEST AFTER MERGE') class TestJvmSpecialCase(JvmTest, BaseTestSpecialcase): pass Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_list.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_list.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/test/test_list.py Fri Apr 4 13:18:57 2008 @@ -15,4 +15,17 @@ return lst[0] res = self.interpret(fn, []) assert res == 0 + + def test_bool_fixed_list(self): + """ Tests that we handle boolean fixed lists, which do not require + boxing or unboxing """ + def fn(i): + lst = [False, True] + if lst[i]: + return 22 + else: + return 44 + for i in range(0,2): + res = self.interpret(fn, [i]) + assert res == fn(i) Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/typesystem.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/typesystem.py Fri Apr 4 13:18:57 2008 @@ -1,33 +1,28 @@ """ -Definition and some basic translations between PyPy ootypesystem and -JVM type system. - -Here are some tentative non-obvious decisions: - -Signed scalar types mostly map as is. - -Unsigned scalar types are a problem; the basic idea is to store them -as signed values, but execute special code when working with them. Another -option would be to use classes, or to use the "next larger" type and remember to use appropriate modulos. The jury is out on -this. Another idea would be to add a variant type system that does -not have unsigned values, and write the required helper and conversion -methods in RPython --- then it could be used for multiple backends. - -Python strings are mapped to byte arrays, not Java Strings, since -Python strings are really sets of bytes, not unicode code points. -Jury is out on this as well; this is not the approach taken by cli, -for example. - -Python Unicode strings, on the other hand, map directly to Java Strings. - -WeakRefs are mapped to a thin wrapper class, PyPyWeakRef, to allow for -mutation of the object being referenced (the ll_set method). - -Collections can hopefully map to Java collections instances. Note -that JVM does not have an idea of generic typing at its lowest level -(well, they do have signature attributes, but those don't really count -for much). +Defines the basic structures which are used to represent JVM abstraction, +such as Java types, fields, methods and opcodes. +The structures in this file generally two different, but related, +roles. First, they describe a JVM abstraction. For example, jObject +describes some of the properties of the built-in class +java.lang.Object. Second, they can represent the concrete realization +of an OOTYPE construct. For example, JvmType instances are used to +represent the translated class which will be generated for some OOTYPE +class. + +This file itself is intended to be imported from a wide variety of +locations, and thus generally restricts itself to classes and global +variables that describe intrinsic parts of the JVM. For example, +there are objects representing different opcodes, type definitions for +built-in types like java.lang.Object and java.lang.System, and +method/field declarations for well-known methods and fields on those +types. + +Other files extend this set with objects that represent the JVM +realization of some OOTYPE construct. For example, the module +builtin.py describes the JVM types that are used to define the +built-in OOTYPE types, such as lists or dictionaries. The module +node.py contains code for representing user-defined classes. """ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype @@ -69,8 +64,11 @@ def int_class_name(self): """ Converts a descriptor like Ljava/lang/Object; to internal class name java/lang/Object """ - assert self[0] == 'L' and self[-1] == ';' - return self[1:-1] + if self[0] == 'L' and self[-1] == ';': + return self[1:-1] + else: + assert self.startswith('[') + return self def type_width(self): """ Returns number of JVM words this type takes up. JVM words are a theoretically abstract quantity that basically @@ -102,6 +100,13 @@ # ______________________________________________________________________ # Basic JVM Types +# +# As described above, some of these define well-known types in the JVM +# or standard Java library. In addition, there are subtypes of +# JvmType which represent the translated version of some RPython +# class, such as a list, dictionary, or user-defined class. Those +# subtypes are generally defined in other modules, as they have +# dependencies that would cause circular imports. class JvmType(object): """ @@ -116,15 +121,23 @@ # (None for scalars and arrays) def lookup_field(self, fieldnm): - """ If the class has a field named 'fieldnm', returns a - jvmgen.Field or jvmgen.Property object that represents it and can - be used with the interpreter to load/store it. If no such field - exists, or this is not a class, then raises KeyError. """ + """ Returns a Field or Property object that represents the + field named 'fieldnm', or raises KeyError if no such field + exists. 'fieldnm' generally represents an OOTYPE field, and + thus this method is generally not implemenented by the JvmType + classes that just represent native Java classes, even if they + have fields. Instead, such fields are described as global + Field constants, either in this file or elsewhere. """ raise NotImplementedException + def lookup_method(self, methodnm): - """ Returns a jvm.generator.Method object representing the method - with the given name, or raises KeyError if that field does not - exist on this type. """ + """ Returns a BaseMethod object that represents the method + named 'methodnm', or raises KeyError if no such field exists. + 'methodnm' represents an OOTYPE method, and thus this method + is generally not implemenented by the JvmType classes that + just represent native Java classes, even if they have methods. + Instead, such methods are described as global Method constants + in this file, either in this file or elsewhere. """ raise NotImplementedException def is_generated(self): @@ -226,22 +239,6 @@ jByte = JvmScalarType('B', jByteClass, 'byteValue') jChar = JvmScalarType('C', jCharClass, 'charValue') -class JvmArrayType(JvmType): - """ - Subclass used for all array instances. - """ - def __init__(self, elemtype): - JvmType.__init__(self, desc_for_array_of(elemtype.descriptor)) - self.element_type = elemtype - def lookup_field(self, fieldnm): - raise KeyError(fieldnm) # TODO adjust interface to permit opcode here - def lookup_method(self, methodnm): - raise KeyError(methodnm) # Arrays have no methods - -jByteArray = JvmArrayType(jByte) -jObjectArray = JvmArrayType(jObject) -jStringArray = JvmArrayType(jString) - class Generifier(object): """ @@ -263,7 +260,7 @@ if hasattr(self.OOTYPE, 'SELFTYPE_T'): self.generics[self.OOTYPE.SELFTYPE_T] = (self.OOTYPE,self.OOTYPE) - for pname,pval in (('ITEMTYPE_T', '_ITEMTYPE'), + for pname,pval in (('ITEMTYPE_T', 'ITEM'), ('KEYTYPE_T', '_KEYTYPE'), ('VALUETYPE_T', '_VALUETYPE')): if hasattr(self.OOTYPE, pname): @@ -301,7 +298,7 @@ # Java Callback Interfaces # # A list of interfaces which static functions that we generate will -# automatically implement if application. See the pypy/Callback.java, +# automatically implement if applicable. See the pypy/Callback.java, # node.py/StaticMethodInterface for more information. jCallbackInterfaces = [] # collects all of the defined JvmCallbackInterfaces @@ -351,10 +348,630 @@ return self.methods[methname] def _add_methods(self): - from pypy.translator.jvm.generator import Method for methname, methspec in self.OOTYPE._class_._methods.items(): argtypes = [self.db.annotation_to_cts(arg._type) for arg in methspec.args] restype = self.db.annotation_to_cts(methspec.retval._type) self.methods[methname] = Method.v(self, methname, argtypes, restype) + +# ______________________________________________________________________ +# The bridge between RPython array and JVM arrays. The main differences +# are that (a) RPython has arrays of void type, and (b) RPython arrays +# have methods, whereas Java methods don't. We inline those methods +# into the appropriate bytecode. + +class _JvmVoidArray(JvmClassType): + """ + A special case for void arrays. These are represented by an instance + of the VoidArray class, which implements the required methods. + """ + + method_types = { + 'll_length': ([], jInt), + 'll_getitem_fast': ([jInt], jVoid), + 'll_setitem_fast': ([jInt], jVoid), + } + + def __init__(self): + JvmClassType.__init__(self, 'pypy.VoidArray') + + def make(self, gen): + # Construct a new VoidArray object, assuming the length has + # been pushed onto the stack already. + gen.emit(PYPYVOIDARRAYMAKE) + + def lookup_field(self, fieldnm): + raise KeyError(fieldnm) # no fields + + def lookup_method(self, methodnm): + jargtypes, jrettype = self.method_types[methodnm] + return Method.v(self, methodnm, jargtypes, jrettype) + +class JvmArrayType(JvmType): + """ + Subclass used for all array instances. + """ + def __init__(self, elemtype): + JvmType.__init__(self, desc_for_array_of(elemtype.descriptor)) + self.element_type = elemtype + def make(self, gen): + # Issues the opcode to build a new array of the appropriate type. + # Assumes the length has been pushed onto the stack already. + gen.emit(NEWARRAY.for_type(self)) + def lookup_field(self, fieldnm): + raise KeyError(fieldnm) + def lookup_method(self, methodnm): + # Arrays don't have methods in Java, but they do in the ootype system + if methodnm == "ll_length": + return OpcodeMethod([], jInt, ARRAYLENGTH) + elif methodnm == "ll_getitem_fast": + return OpcodeMethod([jInt], self.element_type, + ARRLOAD.for_type(self.element_type)) + elif methodnm == "ll_setitem_fast": + return OpcodeMethod([jInt, self.element_type], jVoid, + ARRSTORE.for_type(self.element_type)) + else: + raise KeyError(methodnm) + +jBoolArray = JvmArrayType(jBool) +jByteArray = JvmArrayType(jByte) +jObjectArray = JvmArrayType(jObject) +jStringArray = JvmArrayType(jString) +jDoubleArray = JvmArrayType(jDouble) +jCharArray = JvmArrayType(jChar) +jIntArray = JvmArrayType(jInt) +jVoidArray = _JvmVoidArray() + +# ______________________________________________________________________ +# Opcodes +# +# Objects describing the various opcodes which we use. In some cases, +# there are also opcode families, which consist of a set of related +# opcodes that are specialized by the types they operate on (i.e., +# IADD, DADD, etc). + +class Opcode(object): + def __init__(self, jvmstr): + """ + flags is a set of flags (see above) that describe opcode #UPDATE + jvmstr is the name for jasmin printouts + """ + self.jvmstr = jvmstr + self.flags = None #Should flags be added to args? + + def __repr__(self): + return "" % (self.jvmstr, self.flags) + + def specialize(self, args): + """ Process the argument list according to the various flags. + Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing + the new opcode, and ARGS is a list of arguments or empty tuple. + Most of these do not do anything. """ + return (self.jvmstr, args) + +class IntConstOpcode(Opcode): + """ The ICONST opcode specializes itself for small integer opcodes. """ + def specialize(self, args): + assert len(args) == 1 + if args[0] == -1: + return self.jvmstr + "_m1", () + elif args[0] >= 0 and args[0] <= 5: + return self.jvmstr + "_" + str(args[0]), () + # Non obvious: convert ICONST to LDC if the constant is out of + # range + return "ldc", args + +class VarOpcode(Opcode): + """ An Opcode which takes a variable index as an argument; specialized + to small integer indices. """ + def specialize(self, args): + assert len(args) == 1 + if args[0] >= 0 and args[0] <= 3: + return self.jvmstr + "_" + str(args[0]), () + return Opcode.specialize(self, args) + +class IntClassNameOpcode(Opcode): + """ An opcode which takes an internal class name as its argument; + the actual argument will be a JvmType instance. """ + def specialize(self, args): + args = [args[0].descriptor.int_class_name()] + return self.jvmstr, args + +class OpcodeFamily(object): + """ + Many opcodes in JVM have variants that depend on the type of the + operands; for example, one must choose the correct ALOAD, ILOAD, + or DLOAD depending on whether one is loading a reference, integer, + or double variable respectively. Each instance of this class + defines one 'family' of opcodes, such as the LOAD family shown + above, and produces Opcode objects specific to a particular type. + """ + def __init__(self, opcclass, suffix): + """ + opcclass is the opcode subclass to use (see above) when + instantiating a particular opcode + + jvmstr is the name for jasmin printouts + """ + self.opcode_class = opcclass + self.suffix = suffix + self.cache = {} + + def _o(self, prefix): + try: + return self.cache[prefix] + except KeyError: + self.cache[prefix] = obj = self.opcode_class( + prefix+self.suffix) + return obj + + def for_type(self, argtype): + """ Returns a customized opcode of this family appropriate to + 'argtype', a JvmType object. """ + + desc = argtype.descriptor + + # These are always true: + if desc[0] == 'L': return self._o("a") # Objects + if desc[0] == '[': return self._o("a") # Arrays + if desc == 'I': return self._o("i") # Integers + if desc == 'J': return self._o("l") # Integers + if desc == 'D': return self._o("d") # Doubles + if desc == 'V': return self._o("") # Void [used by RETURN] + + # Chars/Bytes/Booleans are normally represented as ints + # in the JVM, but some opcodes are different. They use a + # different OpcodeFamily (see ArrayOpcodeFamily for ex) + if desc == 'C': return self._o("i") # Characters + if desc == 'B': return self._o("i") # Bytes + if desc == 'Z': return self._o("i") # Boolean + + assert False, "Unknown argtype=%s" % repr(argtype) + raise NotImplementedError + +class ArrayOpcodeFamily(OpcodeFamily): + """ Opcode family specialized for array access instr """ + def for_type(self, argtype): + desc = argtype.descriptor + if desc == 'J': return self._o("l") # Integers + if desc == 'D': return self._o("d") # Doubles + if desc == 'C': return self._o("c") # Characters + if desc == 'B': return self._o("b") # Bytes + if desc == 'Z': return self._o("b") # Boolean (access as bytes) + return OpcodeFamily.for_type(self, argtype) + +class NewArrayOpcodeFamily(object): + def __init__(self): + self.cache = {} + + def for_type(self, arraytype): + try: + return self.cache[arraytype] + except KeyError: + pass + desc = arraytype.descriptor + if desc == '[I': + s = "newarray int" + elif desc == '[D': + s = "newarray double" + elif desc == '[C': + s = "newarray char" + elif desc == '[B': + s = "newarray byte" + elif desc == '[Z': + s = "newarray boolean" + else: + s = "anewarray " + arraytype.element_type.descriptor.int_class_name() + self.cache[arraytype] = obj = Opcode(s) + return obj + +NEWARRAY = NewArrayOpcodeFamily() +ARRAYLENGTH = Opcode("arraylength") + +# Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx +# variants compare a single integer arg against 0, and the IF_ICMPxx +# variants compare 2 integer arguments against each other. +for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'): + ifop = "if%s" % cmpop + if_icmpop = "if_icmp%s" % cmpop + globals()[ifop.upper()] = Opcode(ifop) + globals()[if_icmpop.upper()] = Opcode(if_icmpop) + +# Compare references, either against NULL or against each other +IFNULL = Opcode('ifnull') +IFNONNULL = Opcode('ifnonnull') +IF_ACMPEQ = Opcode('if_acmpeq') +IF_ACMPNE = Opcode('if_acmpne') + +# Method invocation +INVOKESTATIC = Opcode('invokestatic') +INVOKEVIRTUAL = Opcode('invokevirtual') +INVOKESPECIAL = Opcode('invokespecial') +INVOKEINTERFACE = Opcode('invokeinterface') + +# Other opcodes +LDC = Opcode('ldc') # single-word types +LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs +GOTO = Opcode('goto') +ICONST = IntConstOpcode('iconst') +ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly +ACONST_NULL=Opcode('aconst_null') +DCONST_0 = Opcode('dconst_0') +DCONST_1 = Opcode('dconst_1') +LCONST_0 = Opcode('lconst_0') +LCONST_1 = Opcode('lconst_1') +GETFIELD = Opcode('getfield') +PUTFIELD = Opcode('putfield') +GETSTATIC = Opcode('getstatic') +PUTSTATIC = Opcode('putstatic') +CHECKCAST = IntClassNameOpcode('checkcast') +INEG = Opcode('ineg') +IXOR = Opcode('ixor') +IADD = Opcode('iadd') +ISUB = Opcode('isub') +IMUL = Opcode('imul') +IDIV = Opcode('idiv') +IREM = Opcode('irem') +IAND = Opcode('iand') +IOR = Opcode('ior') +ISHL = Opcode('ishl') +ISHR = Opcode('ishr') +IUSHR = Opcode('iushr') +LCMP = Opcode('lcmp') +DCMPG = Opcode('dcmpg') +DCMPL = Opcode('dcmpl') +NOP = Opcode('nop') +I2D = Opcode('i2d') +I2L = Opcode('i2l') +D2I= Opcode('d2i') +#D2L= Opcode('d2l') #PAUL +L2I = Opcode('l2i') +L2D = Opcode('l2d') +ATHROW = Opcode('athrow') +DNEG = Opcode('dneg') +DADD = Opcode('dadd') +DSUB = Opcode('dsub') +DMUL = Opcode('dmul') +DDIV = Opcode('ddiv') +DREM = Opcode('drem') +LNEG = Opcode('lneg') +LADD = Opcode('ladd') +LSUB = Opcode('lsub') +LMUL = Opcode('lmul') +LDIV = Opcode('ldiv') +LREM = Opcode('lrem') +LAND = Opcode('land') +LOR = Opcode('lor') +LXOR = Opcode('lxor') +LSHL = Opcode('lshl') +LSHR = Opcode('lshr') +LUSHR = Opcode('lushr') +NEW = IntClassNameOpcode('new') +DUP = Opcode('dup') +DUP2 = Opcode('dup2') +DUP_X1 = Opcode('dup_x1') +POP = Opcode('pop') +POP2 = Opcode('pop2') +SWAP = Opcode('swap') +INSTANCEOF= IntClassNameOpcode('instanceof') +# Loading/storing local variables +LOAD = OpcodeFamily(VarOpcode, "load") +STORE = OpcodeFamily(VarOpcode, "store") +RETURN = OpcodeFamily(Opcode, "return") + +# Loading/storing from arrays +# *NOTE*: This family is characterized by the type of the ELEMENT, +# not the type of the ARRAY. +# +# Also: here I break from convention by naming the objects ARRLOAD +# rather than ALOAD, even though the suffix is 'aload'. This is to +# avoid confusion with the ALOAD opcode. +ARRLOAD = ArrayOpcodeFamily(Opcode, "aload") +ARRSTORE = ArrayOpcodeFamily(Opcode, "astore") + +# ______________________________________________________________________ +# Methods and Fields +# +# These structures are used throughout the code to refer to JVM +# methods and fields. Similarly to JvmType instances, they are used +# both to represent random fields/methods in the JVM, and to represent +# the translation of an OOTYPE field/method. Therefore, these may not +# actually generate code corresponding to a real JVM method: for +# example, arrays use a BaseMethod subclass to generate the +# appropriate JVM opcodes that correspond to RPython arrays. +# Likewise, the Property class (see below) allows us to use a pair of +# JVM methods to represent an OOTYPE field. + +class BaseMethod(object): + def __init__(self, argtypes, rettype): + self.argument_types = argtypes # List of jvmtypes + self.return_type = rettype # jvmtype + + def is_static(self): + raise NotImplementedError + + def invoke(self, gen): + raise NotImplementedError + +class OpcodeMethod(BaseMethod): + """ + Represents a "method" that is actually implemented by a single opcode, + such as ARRAYLENGTH + """ + def __init__(self, argtypes, rettype, opcode, static=False): + """ + argtypes = an array of jvm types indicating what we expect on stack + rettype = the type we will push on the stack (if any) + opcode = the opcode to emit + static = should we be considered static? if true, then we will + not push the receiver onto the stack in metavm + """ + BaseMethod.__init__(self, argtypes, rettype) + self.opcode = opcode + self.static = static + + def is_static(self): + return self.static + + def invoke(self, gen): + gen.emit(self.opcode) + +class Method(BaseMethod): + + """ + Represents a method implemented by a genuine JVM method. Unlike + OpcodeMethod, when we emit the opcode this class is an argument to + it, and contains the extra info about the class/method being + invoked that is required. + """ + + # Create a constructor: + def c(classty, argtypes): + return Method(classty.name, "", argtypes, jVoid, + opcode=INVOKESPECIAL) + c = staticmethod(c) + + # Create a virtual or interface method: + def v(classty, methnm, argtypes, rettype): + """ + Shorthand to create a virtual method. + 'class' - JvmType object for the class + 'methnm' - name of the method (Python string) + 'argtypes' - list of JvmType objects, one for each argument but + not the this ptr + 'rettype' - JvmType for return type + """ + assert argtypes is not None + assert rettype is not None + classnm = classty.name + if isinstance(classty, JvmInterfaceType): + opc = INVOKEINTERFACE + else: + assert isinstance(classty, JvmClassType) + opc = INVOKEVIRTUAL + return Method(classnm, methnm, argtypes, rettype, opcode=opc) + v = staticmethod(v) + + # Create a static method: + def s(classty, methnm, argtypes, rettype): + """ + Shorthand to create a static method. + 'class' - JvmType object for the class + 'methnm' - name of the method (Python string) + 'argtypes' - list of JvmType objects, one for each argument but + not the this ptr + 'rettype' - JvmType for return type + """ + assert isinstance(classty, JvmType) + classnm = classty.name + return Method(classnm, methnm, argtypes, rettype) + s = staticmethod(s) + + def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC): + BaseMethod.__init__(self, argtypes, rettype) + self.opcode = opcode + self.class_name = classnm # String, ie. "java.lang.Math" + self.method_name = methnm # String "abs" + + # Compute the method descriptior, which is a string like "()I": + argtypesdesc = [a.descriptor for a in argtypes] + rettypedesc = rettype.descriptor + self.descriptor = desc_for_method(argtypesdesc, rettypedesc) + def invoke(self, gen): + gen._instr(self.opcode, self) + def is_static(self): + return self.opcode == INVOKESTATIC + def jasmin_syntax(self): + res = "%s/%s%s" % (self.class_name.replace('.','/'), + self.method_name, + self.descriptor) + # A weird, inexplicable quirk of Jasmin syntax is that it requires + # the number of arguments after an invokeinterface call: + if self.opcode == INVOKEINTERFACE: + res += " %d" % (len(self.argument_types)+1,) + return res + +class Field(object): + + """ + Represents an actual JVM field. Use the methods + fld.load(gen) / gen.emit(fld) + or + fld.store(gen) + to load the field's value onto the stack, or store into the field. + If this is not a static field, you must have pushed the object + containing the field and the field's value first. + + See also Property. + """ + + @staticmethod + def i(classty, fieldnm, fieldty, OOTYPE=None): + """ + Shorthand to create an instance field. + 'class' - JvmType object for the class containing the field + 'fieldnm' - name of the field (Python string) + 'fieldty' - JvmType object for the type of the field + 'OOTYPE' - optional OOTYPE object for the type of the field + """ + return Field(classty.name, fieldnm, fieldty, False, OOTYPE) + + @staticmethod + def s(classty, fieldnm, fieldty, OOTYPE=None): + """ + Shorthand to create a static field. + 'class' - JvmType object for the class containing the field + 'fieldnm' - name of the field (Python string) + 'fieldty' - JvmType object for the type of the field + 'OOTYPE' - optional OOTYPE object for the type of the field + """ + return Field(classty.name, fieldnm, fieldty, True, OOTYPE) + + def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None): + # All fields are public + self.class_name = classnm # String, ie. "java.lang.Math" + self.field_name = fieldnm # String "someField" + self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None + self.jtype = jtype # JvmType + self.is_static = static # True or False + def load(self, gen): + if self.is_static: + gen._instr(GETSTATIC, self) + else: + gen._instr(GETFIELD, self) + def store(self, gen): + if self.is_static: + gen._instr(PUTSTATIC, self) + else: + gen._instr(PUTFIELD, self) + def jasmin_syntax(self): + return "%s/%s %s" % ( + self.class_name.replace('.','/'), + self.field_name, + self.jtype.descriptor) + +class Property(object): + """ + An object which acts like a Field, but when a value is loaded or + stored it actually invokes accessor methods. Use like a field + (prop.load(gen), prop.store(gen), etc). + """ + def __init__(self, field_name, get_method, put_method, OOTYPE=None): + self.get_method = get_method + self.put_method = put_method + self.field_name = field_name + self.OOTYPE = OOTYPE + + # Synthesize the Field attributes from the get_method/put_method: + self.class_name = get_method.class_name + assert put_method.class_name == self.class_name + self.jtype = get_method.return_type + self.is_static = get_method.is_static + def load(self, gen): + self.get_method.invoke(gen) + def store(self, gen): + self.put_method.invoke(gen) + # jasmin_syntax is not needed, since this object itself never appears + # as an argument an Opcode + +# ___________________________________________________________________________ +# Methods +# +# "Method" objects describe all the information needed to invoke a +# method. We create one for each node.Function object, as well as for +# various helper methods (defined below). To invoke a method, you +# push its arguments and then use generator.emit(methobj) where +# methobj is its Method instance. + +OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt) +OBJTOSTRING = Method.v(jObject, 'toString', (), jString) +OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool) +SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid) +INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString) +LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString) +DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString) +CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString) +MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt) +IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt) +MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong) +LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong) +MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble) +INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt) +LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong) +IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt) +LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong) +ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt) +LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong) +IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt) +LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong) +MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble) +IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt) +LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong) +IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt) +LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong) +IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt) +LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong) +ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt) +LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong) +MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble) +PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid) +CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass) +CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool) +STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append', + (jString,), jStringBuilder) +PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt) +PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt) +PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt) +PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt) +PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt) +PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong) +PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble) +PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt) +PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL +PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong) +PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt) +PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt) +PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong) +PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong) +PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool) +PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble) +PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar) +PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble) +PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid) +PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid) +PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString) +PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString) +PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString) +PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString) +PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString) +PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString) +PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString) +PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString) +PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString) +PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) +PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) +PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList) +PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble) +OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) +CLASSGETNAME = Method.v(jClass, 'getName', (), jString) +CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make', + (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict) +PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef) +PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject) +PYPYVOIDARRAYMAKE = Method.s(jVoidArray, 'make', (jInt,), jVoidArray) + +# ___________________________________________________________________________ +# Fields +# +# Field objects encode information about fields. + +SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream) +SYSTEMERR = Field.s(jSystem, 'err', jPrintStream) +DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble) +DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble) +DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble) + +PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink) +PYPYOS = Field.i(jPyPy, 'os', jll_os) + Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/constant.py Fri Apr 4 13:18:57 2008 @@ -207,6 +207,8 @@ return genoo.ClassConst(self.db, value, uniq) elif isinstance(value, ootype._list): return genoo.ListConst(self.db, value, uniq) + elif isinstance(value, ootype._array): + return genoo.ArrayConst(self.db, value, uniq) elif isinstance(value, ootype._static_meth): return genoo.StaticMethodConst(self.db, value, uniq) elif isinstance(value, ootype._custom_dict): @@ -582,7 +584,7 @@ if not self.value: return for item in self.value._list: - self._record_const_if_complex(self.value._TYPE._ITEMTYPE, item) + self._record_const_if_complex(self.value._TYPE.ITEM, item) def create_pointer(self, gen): assert not self.is_null() @@ -607,16 +609,12 @@ can be overloaded by the backend if your conditions are wider. The default is not to initialize if the list is a list of Void. """ - return self.value._TYPE._ITEMTYPE is ootype.Void - try: - return self.value._list == [0] * len(self.value._list) - except: - return False + return self.value._TYPE.ITEM is ootype.Void def initialize_data(self, constgen, gen): assert not self.is_null() SELFTYPE = self.value._TYPE - ITEMTYPE = self.value._TYPE._ITEMTYPE + ITEM = self.value._TYPE.ITEM # check for special cases and avoid initialization if self._do_not_initialize(): @@ -627,11 +625,61 @@ constgen._consider_split_current_function(gen) gen.dup(SELFTYPE) push_constant(self.db, ootype.Signed, idx, gen) - push_constant(self.db, ITEMTYPE, item, gen) - gen.prepare_generic_argument(ITEMTYPE) + push_constant(self.db, ITEM, item, gen) + gen.prepare_generic_argument(ITEM) gen.call_method(SELFTYPE, 'll_setitem_fast') # ______________________________________________________________________ +# Array constants + +class ArrayConst(AbstractConst): + def __init__(self, db, list, count): + AbstractConst.__init__(self, db, list, count) + self.name = 'ARRAY__%d' % count + + def record_dependencies(self): + if not self.value: + return + for item in self.value._array: + self._record_const_if_complex(self.value._TYPE.ITEM, item) + + def create_pointer(self, gen): + from pypy.objspace.flow.model import Constant + assert not self.is_null() + SELFTYPE = self.value._TYPE + + # Create the array + length = Constant(len(self.value._array), ootype.Signed) + gen.oonewarray(SELFTYPE, length) + + def _do_not_initialize(self): + """ Returns True if the array should not be initialized; this + can be overloaded by the backend if your conditions are wider. + The default is not to initialize if the array is a array of + Void. """ + return self.value._TYPE.ITEM is ootype.Void + + def initialize_data(self, constgen, gen): + assert not self.is_null() + SELFTYPE = self.value._TYPE + ITEM = self.value._TYPE.ITEM + + # check for special cases and avoid initialization + if self._do_not_initialize(): + return + + # set each item in the list using the OOTYPE methods + for idx, item in enumerate(self.value._array): + constgen._consider_split_current_function(gen) + gen.dup(SELFTYPE) + push_constant(self.db, ootype.Signed, idx, gen) + push_constant(self.db, ITEM, item, gen) + self._setitem(SELFTYPE, gen) + + def _setitem(self, SELFTYPE, gen): + gen.call_method(SELFTYPE, 'll_setitem_fast') + +# ______________________________________________________________________ # Dictionary constants class DictConst(AbstractConst): Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/genoo.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/genoo.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/genoo.py Fri Apr 4 13:18:57 2008 @@ -22,6 +22,7 @@ RecordConst = ooconst.RecordConst ClassConst = ooconst.ClassConst ListConst = ooconst.ListConst + ArrayConst = ooconst.ArrayConst StaticMethodConst = ooconst.StaticMethodConst CustomDictConst = ooconst.CustomDictConst DictConst = ooconst.DictConst Modified: pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/metavm.py ============================================================================== --- pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/metavm.py (original) +++ pypy/branch/fixed-list-ootype-2/pypy/translator/oosupport/metavm.py Fri Apr 4 13:18:57 2008 @@ -214,6 +214,13 @@ Stack: ... -> newobj, ... """ raise NotImplementedError + def oonewarray(self, TYPE, length): + """ Creates a new array of the given type with the given length. + + Stack: ... -> newobj, ... """ + raise NotImplementedError + + def push_null(self, TYPE): """ Push a NULL value onto the stack (the NULL value represents a pointer to an instance of OOType TYPE, if it matters to you). """ @@ -413,6 +420,14 @@ return generator.new(op.args[0].value) + +class _OONewArray(MicroInstruction): + def render(self, generator, op): + if op.args[0].value is ootype.Void: + return + generator.oonewarray(op.args[0].value, op.args[1]) + + class BranchUnconditionally(MicroInstruction): def __init__(self, label): self.label = label @@ -497,6 +512,7 @@ generator.isinstance(class_name) New = _New() +OONewArray = _OONewArray() PushAllArgs = _PushAllArgs() StoreResult = _StoreResult() From antocuni at codespeak.net Fri Apr 4 14:52:47 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 4 Apr 2008 14:52:47 +0200 (CEST) Subject: [pypy-svn] r53329 - in pypy/branch/jit-hotpath/pypy: jit/rainbow jit/rainbow/test jit/timeshifter rpython/ootypesystem Message-ID: <20080404125247.4994816A68A@codespeak.net> Author: antocuni Date: Fri Apr 4 14:52:46 2008 New Revision: 53329 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Log: more passing tests Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Fri Apr 4 14:52:46 2008 @@ -991,22 +991,6 @@ assert res == True self.check_insns({'setfield': 2, 'getfield': 1}) - def test_deepfrozen_interior(self): - T = lltype.Struct('T', ('x', lltype.Signed)) - A = lltype.Array(T) - S = lltype.GcStruct('S', ('a', A)) - s = lltype.malloc(S, 3, zero=True) - s.a[2].x = 42 - def f(n): - s1 = hint(s, variable=True) - s1 = hint(s1, deepfreeze=True) - return s1.a[n].x - - # malloc-remove the interior ptr - res = self.interpret(f, [2], [0], backendoptimize=True) - assert res == 42 - self.check_insns({}) - def test_compile_time_const_tuple(self): d = {(4, 5): 42, (6, 7): 12} def f(a, b): @@ -2063,6 +2047,22 @@ assert res == 42 self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) + def test_deepfrozen_interior(self): + T = lltype.Struct('T', ('x', lltype.Signed)) + A = lltype.Array(T) + S = lltype.GcStruct('S', ('a', A)) + s = lltype.malloc(S, 3, zero=True) + s.a[2].x = 42 + def f(n): + s1 = hint(s, variable=True) + s1 = hint(s1, deepfreeze=True) + return s1.a[n].x + + # malloc-remove the interior ptr + res = self.interpret(f, [2], [0], backendoptimize=True) + assert res == 42 + self.check_insns({}) + class TestOOType(SimpleTests): type_system = "ootype" @@ -2201,10 +2201,7 @@ test_red_struct_array = _skip test_red_varsized_struct = _skip test_array_of_voids = _skip - test_deepfrozen_interior = _skip - test_compile_time_const_tuple = _skip - test_residual_red_call = _skip - test_residual_red_call_with_exc = _skip + test_compile_time_const_tuple = _skip # needs vdict test_simple_meth = _skip test_simple_red_meth = _skip test_simple_red_meth_vars_around = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py Fri Apr 4 14:52:46 2008 @@ -4,7 +4,7 @@ def deref(T): if isinstance(T, lltype.Ptr): return T.TO - assert isinstance(T, (ootype.Instance, ootype.BuiltinType)) + assert isinstance(T, ootype.OOType) return T def fieldType(T, name): Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Fri Apr 4 14:52:46 2008 @@ -637,12 +637,10 @@ self.canbevirtual = True else: T = None - elif isinstance(RESTYPE, ootype.Instance): + elif isinstance(RESTYPE, ootype.OOType): self._set_hints(PTRTYPE, RESTYPE) self.gcref = True # XXX: is it right? self.canbevirtual = True # XXX: is it right? - elif isinstance(RESTYPE, ootype.OOType): - assert False, 'XXX: TODO' self.RESTYPE = RESTYPE self.ptrkind = RGenOp.kindToken(PTRTYPE) self.kind = RGenOp.kindToken(RESTYPE) Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Fri Apr 4 14:52:46 2008 @@ -59,6 +59,9 @@ def _defl(self): return nullruntimeclass + + def _example(self): + return _class(ROOT) Class = Class() From niko at codespeak.net Fri Apr 4 15:10:31 2008 From: niko at codespeak.net (niko at codespeak.net) Date: Fri, 4 Apr 2008 15:10:31 +0200 (CEST) Subject: [pypy-svn] r53330 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator/cli translator/cli/src translator/cli/test translator/js translator/jvm translator/jvm/src/pypy translator/jvm/test translator/oosupport Message-ID: <20080404131031.A5A9916A7E6@codespeak.net> Author: niko Date: Fri Apr 4 15:10:29 2008 New Revision: 53330 Added: pypy/dist/pypy/translator/jvm/src/pypy/VoidArray.java - copied unchanged from r53329, pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/VoidArray.java Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py pypy/dist/pypy/rpython/ootypesystem/rdict.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/test/test_rlist.py pypy/dist/pypy/rpython/test/tool.py pypy/dist/pypy/translator/cli/constant.py pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/entrypoint.py pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/oopspec.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/test_list.py pypy/dist/pypy/translator/js/asmgen.py pypy/dist/pypy/translator/js/database.py pypy/dist/pypy/translator/js/function.py pypy/dist/pypy/translator/js/jsbuiltin.py pypy/dist/pypy/translator/js/jts.py pypy/dist/pypy/translator/js/opcodes.py pypy/dist/pypy/translator/jvm/builtin.py pypy/dist/pypy/translator/jvm/cmpopcodes.py pypy/dist/pypy/translator/jvm/constant.py pypy/dist/pypy/translator/jvm/database.py pypy/dist/pypy/translator/jvm/generator.py pypy/dist/pypy/translator/jvm/metavm.py pypy/dist/pypy/translator/jvm/methods.py pypy/dist/pypy/translator/jvm/node.py pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/jvm/prebuiltnodes.py pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java pypy/dist/pypy/translator/jvm/test/test_class.py pypy/dist/pypy/translator/jvm/test/test_list.py pypy/dist/pypy/translator/jvm/typesystem.py pypy/dist/pypy/translator/oosupport/constant.py pypy/dist/pypy/translator/oosupport/genoo.py pypy/dist/pypy/translator/oosupport/metavm.py Log: (niko, arigo and antocuni looking) merge fixed-list-ootype-2 branch to trunk, introducing a different ootype type for lists that are not resized after they are created. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Fri Apr 4 15:10:29 2008 @@ -516,6 +516,10 @@ r = SomeOOInstance(ootype.typeOf(i)) return r +def oonewarray(s_type, length): + assert s_type.is_constant() + return SomeOOInstance(s_type.const) + def null(I_OR_SM): assert I_OR_SM.is_constant() null = ootype.null(I_OR_SM.const) @@ -563,6 +567,7 @@ BUILTIN_ANALYZERS[ootype.instanceof] = instanceof BUILTIN_ANALYZERS[ootype.new] = new +BUILTIN_ANALYZERS[ootype.oonewarray] = oonewarray BUILTIN_ANALYZERS[ootype.null] = null BUILTIN_ANALYZERS[ootype.runtimenew] = runtimenew BUILTIN_ANALYZERS[ootype.classof] = classof Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Apr 4 15:10:29 2008 @@ -1035,6 +1035,11 @@ def op_new(self, INST): assert isinstance(INST, (ootype.Instance, ootype.BuiltinType)) return ootype.new(INST) + + def op_oonewarray(self, ARRAY, length): + assert isinstance(ARRAY, ootype.Array) + assert isinstance(length, int) + return ootype.oonewarray(ARRAY, length) def op_runtimenew(self, class_): return ootype.runtimenew(class_) Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Fri Apr 4 15:10:29 2008 @@ -465,6 +465,7 @@ 'new': LLOp(oo=True, canraise=(Exception,)), 'runtimenew': LLOp(oo=True, canraise=(Exception,)), 'oonewcustomdict': LLOp(oo=True, canraise=(Exception,)), + 'oonewarray': LLOp(oo=True, canraise=(Exception,)), 'oosetfield': LLOp(oo=True), 'oogetfield': LLOp(oo=True, sideeffects=False), 'oosend': LLOp(oo=True, canraise=(Exception,)), Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Fri Apr 4 15:10:29 2008 @@ -364,7 +364,7 @@ "ll_upper": Meth([], self.SELFTYPE_T), "ll_lower": Meth([], self.SELFTYPE_T), "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count) - "ll_split_chr": Meth([self.CHAR], List(self.SELFTYPE_T)), + "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)), "ll_contains": Meth([self.CHAR], Bool), "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T), }) @@ -464,7 +464,7 @@ ITEMTYPE_T = object() def __init__(self, ITEMTYPE=None): - self._ITEMTYPE = ITEMTYPE + self.ITEM = ITEMTYPE self._null = _null_list(self) if ITEMTYPE is not None: self._init_methods() @@ -475,13 +475,9 @@ # 'ITEMTYPE_T' is used as a placeholder for indicating # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self' - # XXX clean-up later! Rename _ITEMTYPE to ITEM. For now they are - # just synonyms, please use ITEM in new code. - self.ITEM = self._ITEMTYPE - generic_types = { self.SELFTYPE_T: self, - self.ITEMTYPE_T: self._ITEMTYPE, + self.ITEMTYPE_T: self.ITEM, } # the methods are named after the ADT methods of lltypesystem's lists @@ -514,7 +510,7 @@ return True if not isinstance(other, List): return False - if self._ITEMTYPE is None or other._ITEMTYPE is None: + if self.ITEM is None or other.ITEM is None: raise TypeError("Can't compare uninitialized List type.") return BuiltinADTType.__eq__(self, other) @@ -522,28 +518,114 @@ return not (self == other) def __hash__(self): - if self._ITEMTYPE is None: + if self.ITEM is None: raise TypeError("Can't hash uninitialized List type.") return BuiltinADTType.__hash__(self) def __str__(self): return '%s(%s)' % (self.__class__.__name__, - saferecursive(str, "...")(self._ITEMTYPE)) + saferecursive(str, "...")(self.ITEM)) def _get_interp_class(self): return _list def _specialize(self, generic_types): - ITEMTYPE = self._specialize_type(self._ITEMTYPE, generic_types) + ITEMTYPE = self._specialize_type(self.ITEM, generic_types) return self.__class__(ITEMTYPE) def _defl(self): return self._null def _set_itemtype(self, ITEMTYPE): - self._ITEMTYPE = ITEMTYPE + self.ITEM = ITEMTYPE self._init_methods() + def ll_convert_from_array(self, array): + length = array.ll_length() + result = self.ll_newlist(length) + for n in range(length): + result.ll_setitem_fast(n, array.ll_getitem_fast(n)) + return result + +class Array(BuiltinADTType): + # placeholders for types + # make sure that each derived class has his own SELFTYPE_T + # placeholder, because we want backends to distinguish that. + + SELFTYPE_T = object() + ITEMTYPE_T = object() + + def __init__(self, ITEMTYPE=None): + self.ITEM = ITEMTYPE + self._null = _null_array(self) + if ITEMTYPE is not None: + self._init_methods() + + def _init_methods(self): + # This defines the abstract list interface that backends will + # have to map to their native list implementations. + # 'ITEMTYPE_T' is used as a placeholder for indicating + # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self' + + generic_types = { + self.SELFTYPE_T: self, + self.ITEMTYPE_T: self.ITEM, + } + + # the methods are named after the ADT methods of lltypesystem's lists + self._GENERIC_METHODS = frozendict({ + # "name": Meth([ARGUMENT1_TYPE, ARGUMENT2_TYPE, ...], RESULT_TYPE) + "ll_length": Meth([], Signed), + "ll_getitem_fast": Meth([Signed], self.ITEMTYPE_T), + "ll_setitem_fast": Meth([Signed, self.ITEMTYPE_T], Void), + }) + + self._setup_methods(generic_types) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, Array): + return False + if self.ITEM is None or other.ITEM is None: + raise TypeError("Can't compare uninitialized List type.") + return BuiltinADTType.__eq__(self, other) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + if self.ITEM is None: + raise TypeError("Can't hash uninitialized List type.") + return BuiltinADTType.__hash__(self) + + def __str__(self): + return '%s(%s)' % (self.__class__.__name__, + saferecursive(str, "...")(self.ITEM)) + + def _get_interp_class(self): + return _array + + def _specialize(self, generic_types): + ITEMTYPE = self._specialize_type(self.ITEM, generic_types) + return self.__class__(ITEMTYPE) + + def _defl(self): + return self._null + + def _example(self): + return oonewarray(self, 1) + + def _set_itemtype(self, ITEMTYPE): + self.ITEM = ITEMTYPE + self._init_methods() + + def ll_newlist(self, length): + from pypy.rpython.ootypesystem import rlist + return rlist.ll_newarray(self, length) + + def ll_convert_from_array(self, array): + return array class Dict(BuiltinADTType): # placeholders for types @@ -1201,8 +1283,9 @@ def ll_split_chr(self, ch): # NOT_RPYTHON - res = _list(List(self._TYPE)) - res._list = [self.make_string(s) for s in self._str.split(ch)] + l = [self.make_string(s) for s in self._str.split(ch)] + res = _array(Array(self._TYPE), len(l)) + res._array[:] = l return res def ll_contains(self, ch): @@ -1278,6 +1361,8 @@ def __init__(self, WEAK_REFERENCE): self.__dict__["_TYPE"] = WEAK_REFERENCE + + class _list(_builtin_type): def __init__(self, LIST): self._TYPE = LIST @@ -1295,7 +1380,7 @@ # NOT_RPYTHON if len(self._list) < length: diff = length - len(self._list) - self._list += [self._TYPE._ITEMTYPE._defl()] * diff + self._list += [self._TYPE.ITEM._defl()] * diff assert len(self._list) >= length def _ll_resize_le(self, length): @@ -1320,7 +1405,7 @@ def ll_setitem_fast(self, index, item): # NOT_RPYTHON - assert self._TYPE._ITEMTYPE is Void or typeOf(item) == self._TYPE._ITEMTYPE + assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM assert typeOf(index) == Signed assert index >= 0 self._list[index] = item @@ -1330,6 +1415,33 @@ def __init__(self, LIST): self.__dict__["_TYPE"] = LIST +class _array(_builtin_type): + def __init__(self, ARRAY, length): + self._TYPE = ARRAY + self._array = [ARRAY.ITEM._defl()] * length + + def ll_length(self): + # NOT_RPYTHON + return len(self._array) + + def ll_getitem_fast(self, index): + # NOT_RPYTHON + assert typeOf(index) == Signed + assert index >= 0 + return self._array[index] + + def ll_setitem_fast(self, index, item): + # NOT_RPYTHON + assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM + assert typeOf(index) == Signed + assert index >= 0 + self._array[index] = item + +class _null_array(_null_mixin(_array), _array): + + def __init__(self, ARRAY): + self.__dict__["_TYPE"] = ARRAY + class _dict(_builtin_type): def __init__(self, DICT): self._TYPE = DICT @@ -1497,10 +1609,15 @@ return TYPE._get_interp_class()(TYPE) def oonewcustomdict(DICT, ll_eq, ll_hash): + """NOT_RPYTHON""" d = new(DICT) d.ll_set_functions(ll_eq, ll_hash) return d +def oonewarray(ARRAY, length): + """NOT_RPYTHON""" + return _array(ARRAY, length) + def runtimenew(class_): assert isinstance(class_, _class) assert class_ is not nullruntimeclass @@ -1626,7 +1743,7 @@ return LIST._set_itemtype(ITEMTYPE) def hasItemType(LIST): - return LIST._ITEMTYPE is not None + return LIST.ITEM is not None def setDictTypes(DICT, KEYTYPE, VALUETYPE): return DICT._set_types(KEYTYPE, VALUETYPE) Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py Fri Apr 4 15:10:29 2008 @@ -12,6 +12,13 @@ return hop.genop('new', vlist, resulttype = hop.r_result.lowleveltype) +def rtype_oonewarray(hop): + assert hop.args_s[0].is_constant() + vlist = hop.inputarg(ootype.Void, arg=0) + vlength = hop.inputarg(ootype.Signed, arg=1) + return hop.genop('oonewarray', [vlist, vlength], + resulttype = hop.r_result.lowleveltype) + def rtype_null(hop): assert hop.args_s[0].is_constant() TYPE = hop.args_s[0].const @@ -105,6 +112,7 @@ BUILTIN_TYPER = {} BUILTIN_TYPER[ootype.new] = rtype_new +BUILTIN_TYPER[ootype.oonewarray] = rtype_oonewarray BUILTIN_TYPER[ootype.null] = rtype_null BUILTIN_TYPER[ootype.classof] = rtype_classof BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof Modified: pypy/dist/pypy/rpython/ootypesystem/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rdict.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rdict.py Fri Apr 4 15:10:29 2008 @@ -323,7 +323,7 @@ def ll_dict_kvi(d, LIST, func): length = d.ll_length() - result = ll_newlist(LIST, length) + result = LIST.ll_newlist(length) it = d.ll_get_items_iterator() i = 0 while it.ll_go_next(): @@ -332,7 +332,7 @@ elif func is dum_values: result.ll_setitem_fast(i, it.ll_current_value()) if func is dum_items: - r = ootype.new(LIST._ITEMTYPE) + r = ootype.new(LIST.ITEM) r.item0 = it.ll_current_key() # TODO: do we need casting? r.item1 = it.ll_current_value() result.ll_setitem_fast(i, r) Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Fri Apr 4 15:10:29 2008 @@ -1,6 +1,6 @@ from pypy.tool.pairtype import pairtype from pypy.rpython.rlist import AbstractBaseListRepr, AbstractListRepr, \ - AbstractListIteratorRepr, rtype_newlist, rtype_alloc_and_set + AbstractListIteratorRepr, AbstractFixedSizeListRepr, rtype_newlist, rtype_alloc_and_set from pypy.rpython.rmodel import Repr, IntegerRepr from pypy.rpython.rmodel import inputconst, externalvsinternal from pypy.rpython.lltypesystem.lltype import Signed, Void @@ -21,15 +21,12 @@ else: self.external_item_repr, self.item_repr = \ externalvsinternal(rtyper, item_repr) - self.LIST = ootype.List() + self.LIST = self._make_empty_type() self.lowleveltype = self.LIST self.listitem = listitem self.list_cache = {} # setup() needs to be called to finish this initialization - def _externalvsinternal(self, rtyper, item_repr): - return item_repr, item_repr - def _setup_repr(self): if 'item_repr' not in self.__dict__: self.external_item_repr, self.item_repr = \ @@ -37,13 +34,9 @@ if not ootype.hasItemType(self.lowleveltype): ootype.setItemType(self.lowleveltype, self.item_repr.lowleveltype) - def null_const(self): - return self.LIST._null - - def prepare_const(self, n): - result = self.LIST.ll_newlist(n) - return result - + def _externalvsinternal(self, rtyper, item_repr): + return item_repr, item_repr + def send_message(self, hop, message, can_raise=False, v_args=None): if v_args is None: v_args = hop.inputargs(self, *hop.args_r[1:]) @@ -56,9 +49,6 @@ def get_eqfunc(self): return inputconst(Void, self.item_repr.get_ll_eq_function()) - def make_iterator_repr(self): - return ListIteratorRepr(self) - def rtype_hint(self, hop): hints = hop.args_s[-1].const if 'maxlength' in hints: @@ -71,10 +61,26 @@ class ListRepr(AbstractListRepr, BaseListRepr): + def null_const(self): + return self.LIST._null + + def prepare_const(self, n): + result = self.LIST.ll_newlist(n) + return result + + def make_iterator_repr(self): + return ListIteratorRepr(self) - pass + def _make_empty_type(self): + return ootype.List() -FixedSizeListRepr = ListRepr + def _generate_newlist(self, llops, items_v, v_sizehint): + c_list = inputconst(ootype.Void, self.lowleveltype) + v_result = llops.genop("new", [c_list], resulttype=self.lowleveltype) + c_resize = inputconst(ootype.Void, "_ll_resize") + c_length = inputconst(ootype.Signed, len(items_v)) + llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void) + return v_result class __extend__(pairtype(BaseListRepr, BaseListRepr)): @@ -87,11 +93,7 @@ def newlist(llops, r_list, items_v, v_sizehint=None): # XXX do something about v_sizehint - c_list = inputconst(ootype.Void, r_list.lowleveltype) - v_result = llops.genop("new", [c_list], resulttype=r_list.lowleveltype) - c_resize = inputconst(ootype.Void, "_ll_resize") - c_length = inputconst(ootype.Signed, len(items_v)) - llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void) + v_result = r_list._generate_newlist(llops, items_v, v_sizehint) c_setitem = inputconst(ootype.Void, "ll_setitem_fast") for i, v_item in enumerate(items_v): @@ -104,6 +106,31 @@ lst._ll_resize(length) return lst +# Fixed-size list +class FixedSizeListRepr(AbstractFixedSizeListRepr, BaseListRepr): + def compact_repr(self): + return 'FixedSizeListR %s' % (self.item_repr.compact_repr(),) + + def _make_empty_type(self): + return ootype.Array() + + def null_const(self): + return self.LIST._null + + def prepare_const(self, n): + return ll_newarray(self.LIST, n) + + def make_iterator_repr(self): + return ListIteratorRepr(self) + + def _generate_newlist(self, llops, items_v, v_sizehint): + c_array = inputconst(ootype.Void, self.lowleveltype) + c_length = inputconst(ootype.Signed, len(items_v)) + v_result = llops.genop("oonewarray", [c_array, c_length], resulttype=self.lowleveltype) + return v_result + +def ll_newarray(ARRAY, length): + return ootype.oonewarray(ARRAY, length) # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rstr.py Fri Apr 4 15:10:29 2008 @@ -170,7 +170,7 @@ return buf.ll_build() def ll_join_chars(length_dummy, lst): - if typeOf(lst)._ITEMTYPE == Char: + if typeOf(lst).ITEM == Char: buf = ootype.new(ootype.StringBuilder) else: buf = ootype.new(ootype.UnicodeBuilder) @@ -183,7 +183,7 @@ return buf.ll_build() def ll_join_strs(length_dummy, lst): - if typeOf(lst)._ITEMTYPE == ootype.String: + if typeOf(lst).ITEM == ootype.String: buf = ootype.new(ootype.StringBuilder) else: buf = ootype.new(ootype.UnicodeBuilder) @@ -209,8 +209,8 @@ def ll_stringslice_minusone(s): return s.ll_substring(0, s.ll_strlen()-1) - def ll_split_chr(LIST, s, c): - return s.ll_split_chr(c) + def ll_split_chr(RESULT, s, c): + return RESULT.ll_convert_from_array(s.ll_split_chr(c)) def ll_int(s, base): if not 2 <= base <= 36: Modified: pypy/dist/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rtuple.py Fri Apr 4 15:10:29 2008 @@ -36,13 +36,19 @@ def rtype_bltn_list(self, hop): from pypy.rpython.ootypesystem import rlist v_tup = hop.inputarg(self, 0) - LIST = hop.r_result.lowleveltype - c_list = inputconst(ootype.Void, LIST) - v_list = hop.genop('new', [c_list], resulttype=LIST) - c_resize = inputconst(ootype.Void, '_ll_resize') - c_setitem = inputconst(ootype.Void, 'll_setitem_fast') + RESULT = hop.r_result.lowleveltype + c_resulttype = inputconst(ootype.Void, RESULT) c_length = inputconst(ootype.Signed, len(self.items_r)) - hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void) + if isinstance(RESULT, ootype.Array): + v_list = hop.genop('oonewarray', [c_resulttype, c_length], resulttype=RESULT) + else: + assert isinstance(RESULT, ootype.List) + v_list = hop.genop('new', [c_resulttype], resulttype=RESULT) + c_resize = inputconst(ootype.Void, '_ll_resize') + hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void) + + c_setitem = inputconst(ootype.Void, 'll_setitem_fast') + for index in range(len(self.items_r)): name = self.fieldnames[index] r_item = self.items_r[index] @@ -51,6 +57,7 @@ v_item = hop.llops.convertvar(v_item, r_item, hop.r_result.item_repr) c_index = inputconst(ootype.Signed, index) hop.genop('oosend', [c_setitem, v_list, c_index, v_item], resulttype=ootype.Void) + return v_list Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Fri Apr 4 15:10:29 2008 @@ -498,7 +498,6 @@ assert self.class_name(res) == 'A' #''.join(res.super.typeptr.name) == 'A\00' - def test_reverse(self): def dummyfn(): l = [5, 3, 2] @@ -517,15 +516,15 @@ assert res == 235 def test_prebuilt_list(self): - klist = ['a', 'd', 'z', 'k'] + klist = [6, 7, 8, 9] def dummyfn(n): return klist[n] res = self.interpret(dummyfn, [0]) - assert res == 'a' + assert res == 6 res = self.interpret(dummyfn, [3]) - assert res == 'k' + assert res == 9 res = self.interpret(dummyfn, [-2]) - assert res == 'z' + assert res == 8 klist = ['a', 'd', 'z'] def mkdummyfn(): Modified: pypy/dist/pypy/rpython/test/tool.py ============================================================================== --- pypy/dist/pypy/rpython/test/tool.py (original) +++ pypy/dist/pypy/rpython/test/tool.py Fri Apr 4 15:10:29 2008 @@ -107,7 +107,9 @@ return OOSupport.to_runicode(u) def ll_to_list(self, l): - return l._list[:] + if hasattr(l, '_list'): + return l._list[:] + return l._array[:] def ll_unpack_tuple(self, t, length): return tuple([getattr(t, 'item%d' % i) for i in range(length)]) Modified: pypy/dist/pypy/translator/cli/constant.py ============================================================================== --- pypy/dist/pypy/translator/cli/constant.py (original) +++ pypy/dist/pypy/translator/cli/constant.py Fri Apr 4 15:10:29 2008 @@ -28,7 +28,7 @@ from pypy.translator.oosupport.constant import \ push_constant, WeakRefConst, StaticMethodConst, CustomDictConst, \ ListConst, ClassConst, InstanceConst, RecordConst, DictConst, \ - BaseConstantGenerator, AbstractConst + BaseConstantGenerator, AbstractConst, ArrayConst from pypy.translator.cli.ilgenerator import CLIBaseGenerator from pypy.rpython.ootypesystem import ootype from pypy.translator.cli.comparer import EqualityComparer @@ -373,9 +373,25 @@ def create_pointer(self, gen): self.db.const_count.inc('List') - self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE) + self.db.const_count.inc('List', self.value._TYPE.ITEM) self.db.const_count.inc('List', len(self.value._list)) - super(CLIListConst, self).create_pointer(gen) + super(CLIListConst, self).create_pointer(gen) + + +class CLIArrayConst(CLIBaseConstMixin, ArrayConst): + + def _do_not_initialize(self): + # Check if it is an array of all zeroes: + try: + if self.value._list == [0] * len(self.value._list): + return True + except: + pass + return super(CLIArrayConst, self)._do_not_initialize() + + def _setitem(self, SELFTYPE, gen): + gen.array_setitem(SELFTYPE) + class CLIDictConst(CLIDictMixin, DictConst): def create_pointer(self, gen): Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Fri Apr 4 15:10:29 2008 @@ -95,6 +95,14 @@ arglist = ', '.join([arg.typename() for arg in self.arg_types]) return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist) +class CliArrayType(CliType): + + def __init__(self, itemtype): + self.itemtype = itemtype + + def typename(self): + return '%s[]' % self.itemtype.typename() + T = CliPrimitiveType class types: @@ -249,8 +257,13 @@ elif isinstance(t, ootype.StaticMethod): delegate = self.db.record_delegate(t) return CliClassType(None, delegate) + elif isinstance(t, ootype.Array): + item_type = self.lltype_to_cts(t.ITEM) + if item_type == types.void: # special case: Array of Void + return types.list_of_void + return CliArrayType(item_type) elif isinstance(t, ootype.List): - item_type = self.lltype_to_cts(t._ITEMTYPE) + item_type = self.lltype_to_cts(t.ITEM) if item_type == types.void: # special case: List of Void return types.list_of_void return types.list.specialize(item_type) Modified: pypy/dist/pypy/translator/cli/entrypoint.py ============================================================================== --- pypy/dist/pypy/translator/cli/entrypoint.py (original) +++ pypy/dist/pypy/translator/cli/entrypoint.py Fri Apr 4 15:10:29 2008 @@ -9,7 +9,7 @@ ARG0 = graph.getargs()[0].concretetype except IndexError: ARG0 = None - if isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String: + if isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String: return StandaloneEntryPoint(graph) else: return TestEntryPoint(graph) @@ -45,7 +45,7 @@ ARG0 = self.graph.getargs()[0].concretetype except IndexError: ARG0 = None - assert isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String,\ + assert isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String,\ 'Wrong entry point signature: List(String) expected' ilasm.begin_function('main', [('string[]', 'argv')], 'void', True, 'static') Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Fri Apr 4 15:10:29 2008 @@ -31,6 +31,7 @@ RecordConst = constant.CLIRecordConst ClassConst = constant.CLIClassConst ListConst = constant.CLIListConst + ArrayConst = constant.CLIArrayConst StaticMethodConst = constant.CLIStaticMethodConst CustomDictConst = constant.CLICustomDictConst DictConst = constant.CLIDictConst Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Fri Apr 4 15:10:29 2008 @@ -417,3 +417,31 @@ def dup(self, TYPE): self.ilasm.opcode('dup') + + def oonewarray(self, TYPE, length): + if TYPE.ITEM is ootype.Void: + self.new(TYPE) + self.ilasm.opcode('dup') + self.load(length) + self.ilasm.call_method('void [pypylib]pypy.runtime.ListOfVoid::_ll_resize(int32)', virtual=False) + else: + clitype = self.cts.lltype_to_cts(TYPE) + self.load(length) + self.ilasm.opcode('newarr', clitype.itemtype.typename()) + + def _array_suffix(self, ARRAY, erase_unsigned=False): + from pypy.translator.cli.metavm import OOTYPE_TO_MNEMONIC + suffix = OOTYPE_TO_MNEMONIC.get(ARRAY.ITEM, 'ref') + if erase_unsigned: + suffix = suffix.replace('u', 'i') + return suffix + + def array_setitem(self, ARRAY): + suffix = self._array_suffix(ARRAY, erase_unsigned=True) + self.ilasm.opcode('stelem.%s' % suffix) + + def array_getitem(self, ARRAY): + self.ilasm.opcode('ldelem.%s' % self._array_suffix(ARRAY)) + + def array_length(self, ARRAY): + self.ilasm.opcode('ldlen') Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Fri Apr 4 15:10:29 2008 @@ -68,6 +68,17 @@ arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) generator.call_signature(signature) + elif isinstance(this.concretetype, ootype.Array) and this.concretetype.ITEM is not ootype.Void: + v_array = args[0] + ARRAY = v_array.concretetype + if method_name == 'll_setitem_fast': + generator.array_setitem(ARRAY) + elif method_name == 'll_getitem_fast': + generator.array_getitem(ARRAY) + elif method_name == 'll_length': + generator.array_length(ARRAY) + else: + assert False else: generator.call_method(this.concretetype, method_name) @@ -251,10 +262,14 @@ OOTYPE_TO_MNEMONIC = { + ootype.Bool: 'i1', + ootype.Char: 'i2', + ootype.UniChar: 'i2', ootype.Signed: 'i4', ootype.SignedLongLong: 'i8', ootype.Unsigned: 'u4', ootype.UnsignedLongLong: 'u8', + ootype.Float: 'r8', } class _CastPrimitive(MicroInstruction): Modified: pypy/dist/pypy/translator/cli/oopspec.py ============================================================================== --- pypy/dist/pypy/translator/cli/oopspec.py (original) +++ pypy/dist/pypy/translator/cli/oopspec.py Fri Apr 4 15:10:29 2008 @@ -31,9 +31,9 @@ def get_method(TYPE, name): try: - # special case: when having List of Void, look at the concrete - # methods, not the generic ones - if isinstance(TYPE, ootype.List) and TYPE._ITEMTYPE is ootype.Void: + # special case: when having List of Void, or an Array, look at + # the concrete methods, not the generic ones + if isinstance(TYPE, ootype.Array) or (isinstance(TYPE, ootype.List) and TYPE.ITEM is ootype.Void): return TYPE._METHODS[name] else: return TYPE._GENERIC_METHODS[name] Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Fri Apr 4 15:10:29 2008 @@ -4,7 +4,7 @@ TypeOf, CastPrimitive, EventHandler, GetStaticField, SetStaticField,\ FieldInfoForConst from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ - New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode + New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode, OONewArray from pypy.translator.cli.cts import WEAKREF from pypy.rpython.ootypesystem import ootype @@ -58,6 +58,7 @@ '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], + 'oonewarray': [OONewArray, StoreResult], 'hint': [PushArg(0), StoreResult], 'direct_call': [Call], 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 Fri Apr 4 15:10:29 2008 @@ -35,10 +35,28 @@ public static string ToPython(object x) { if (x == null) return "None"; + else if (x is Array) + return ArrayToPython((Array)x); else return x.ToString(); } + private static string ArrayToPython(Array array) + { + string res = "["; + foreach(object item in array) { + if (item != null && item.GetType() == typeof(string)) { + object tmp = (object)item; + res += ToPython((string)tmp) + ","; + } + else + res += ToPython(item) + ","; + + } + res += "]"; + return res; + } + public static string InstanceToPython(object obj) { return string.Format("InstanceWrapper('{0}')", obj.GetType().FullName); @@ -373,11 +391,9 @@ return s.Substring(start, count); } - public static List ll_split_chr(string s, char ch) + public static string[] ll_split_chr(string s, char ch) { - List res = new List(); - res.AddRange(s.Split(ch)); - return res; + return s.Split(ch); } public static bool ll_contains(string s, char ch) @@ -417,7 +433,7 @@ res += pypy.test.Result.ToPython((string)tmp) + ","; } else - res += item.ToString() + ","; // XXX: doesn't work for chars + res += pypy.test.Result.ToPython(item) + ","; } res += "]"; return res; Modified: pypy/dist/pypy/translator/cli/test/test_list.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_list.py (original) +++ pypy/dist/pypy/translator/cli/test/test_list.py Fri Apr 4 15:10:29 2008 @@ -1,6 +1,7 @@ import py from pypy.translator.cli.test.runtest import CliTest from pypy.rpython.test.test_rlist import BaseTestRlist +from pypy.rlib.rarithmetic import r_uint class TestCliList(CliTest, BaseTestRlist): def test_recursive(self): @@ -8,3 +9,19 @@ def test_getitem_exc(self): py.test.skip('fixme!') + + def test_list_unsigned(self): + def fn(x): + lst = [r_uint(0), r_uint(1)] + lst[0] = r_uint(x) + return lst[0] + res = self.interpret(fn, [42]) + assert res == 42 + + def test_list_bool(self): + def fn(x): + lst = [True, False] + lst[0] = x + return lst[0] + res = self.interpret(fn, [False]) + assert res == False Modified: pypy/dist/pypy/translator/js/asmgen.py ============================================================================== --- pypy/dist/pypy/translator/js/asmgen.py (original) +++ pypy/dist/pypy/translator/js/asmgen.py Fri Apr 4 15:10:29 2008 @@ -219,6 +219,9 @@ def runtimenew(self): self.right_hand.append("new %s()" % self.right_hand.pop()) + def oonewarray(self, obj, length): + self.right_hand.append("new %s(%s)" % (obj, length)) + def load_self(self): self.right_hand.append("this") Modified: pypy/dist/pypy/translator/js/database.py ============================================================================== --- pypy/dist/pypy/translator/js/database.py (original) +++ pypy/dist/pypy/translator/js/database.py Fri Apr 4 15:10:29 2008 @@ -227,6 +227,8 @@ return InstanceConst(db, const, static_type) elif isinstance(const, ootype._list): return ListConst(db, const) + elif isinstance(const, ootype._array): + return ListConst(db, const) elif isinstance(const, ootype._record): return RecordConst(db, const) elif isinstance(const, ootype._string): @@ -355,6 +357,13 @@ class ListConst(AbstractConst): + def _get_list(self): + if isinstance(self.const, ootype._list): + return self.const._list + else: + return self.const._array + + def get_name(self): return "const_list" @@ -368,7 +377,7 @@ if not self.const: return - for i in self.const._list: + for i in self._get_list(): name = self.db.record_const(i, None, 'const') if name is not None: self.depends.add(name) @@ -381,9 +390,10 @@ if not self.const: return - for i in xrange(len(self.const._list)): + l = self._get_list() + for i in xrange(len(l)): ilasm.load_str("%s.%s"%(const_var.name, name)) - el = self.const._list[i] + el = l[i] self.db.load_const(typeOf(el), el, ilasm) self.db.load_const(typeOf(i), i, ilasm) ilasm.list_setitem() Modified: pypy/dist/pypy/translator/js/function.py ============================================================================== --- pypy/dist/pypy/translator/js/function.py (original) +++ pypy/dist/pypy/translator/js/function.py Fri Apr 4 15:10:29 2008 @@ -73,6 +73,9 @@ def new(self, obj): self.ilasm.new(self.cts.obj_name(obj)) + def oonewarray(self, obj, length): + self.ilasm.oonewarray(self.cts.obj_name(obj), length) + def set_field(self, obj, name): self.ilasm.set_field(obj, name) #self.ilasm.set_field(self.field_name(obj,name)) Modified: pypy/dist/pypy/translator/js/jsbuiltin.py ============================================================================== --- pypy/dist/pypy/translator/js/jsbuiltin.py (original) +++ pypy/dist/pypy/translator/js/jsbuiltin.py Fri Apr 4 15:10:29 2008 @@ -59,6 +59,11 @@ '_ll_resize_le' : list_resize, 'll_length' : _GetPredefinedField('length'), }, + ootype.Array: { + 'll_setitem_fast' : ListSetitem, + 'll_getitem_fast' : ListGetitem, + 'll_length' : _GetPredefinedField('length'), + }, ootype.Dict: { 'll_get' : ListGetitem, 'll_set' : ListSetitem, Modified: pypy/dist/pypy/translator/js/jts.py ============================================================================== --- pypy/dist/pypy/translator/js/jts.py (original) +++ pypy/dist/pypy/translator/js/jts.py Fri Apr 4 15:10:29 2008 @@ -43,6 +43,8 @@ return self.escape_name(t._name) elif isinstance(t, ootype.List): return "Array" + elif isinstance(t, ootype.Array): + return "Array" elif isinstance(t, lltype.Primitive): return "var" elif isinstance(t, ootype.Record): @@ -135,7 +137,7 @@ ## elif isinstance(t, ootype.StaticMethod): ## return 'void' # TODO: is it correct to ignore StaticMethod? ## elif isinstance(t, ootype.List): -## item_type = self.lltype_to_cts(t._ITEMTYPE) +## item_type = self.lltype_to_cts(t.ITEM) ## return self.__class(PYPY_LIST % item_type, include_class) ## elif isinstance(t, ootype.Dict): ## key_type = self.lltype_to_cts(t._KEYTYPE) Modified: pypy/dist/pypy/translator/js/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js/opcodes.py (original) +++ pypy/dist/pypy/translator/js/opcodes.py Fri Apr 4 15:10:29 2008 @@ -2,7 +2,8 @@ """ from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult,\ - InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive + InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive,\ + OONewArray from pypy.translator.oosupport.metavm import _GetFieldDispatcher, _SetFieldDispatcher, \ _CallDispatcher, _MethodDispatcher, SetField @@ -119,6 +120,7 @@ 'indirect_call' : [IndirectCall], 'same_as' : CopyName, 'new' : [New], + 'oonewarray' : [OONewArray], 'runtimenew' : [RuntimeNew], 'instanceof' : [IsInstance], #'subclassof' : [IsSubclassOf], Modified: pypy/dist/pypy/translator/jvm/builtin.py ============================================================================== --- pypy/dist/pypy/translator/jvm/builtin.py (original) +++ pypy/dist/pypy/translator/jvm/builtin.py Fri Apr 4 15:10:29 2008 @@ -1,5 +1,4 @@ -from pypy.translator.jvm import typesystem as jvmtype -from pypy.translator.jvm import generator as jvmgen +import pypy.translator.jvm.typesystem as jvm from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.typesystem import \ jInt, jVoid, jStringBuilder, jString, jPyPy, jChar, jArrayList, jObject, \ @@ -9,7 +8,7 @@ # ______________________________________________________________________ # Mapping of built-in OOTypes to JVM types -class JvmBuiltInType(jvmtype.JvmClassType): +class JvmBuiltInType(jvm.JvmClassType): """ Represents built-in types to JVM. May optionally be associated @@ -18,7 +17,7 @@ """ def __init__(self, db, classty, OOTYPE): - jvmtype.JvmClassType.__init__(self, classty.name) + jvm.JvmClassType.__init__(self, classty.name) self.db = db self.OOTYPE = OOTYPE self.gen = Generifier(OOTYPE) @@ -30,14 +29,14 @@ return hash(self.name) def lookup_field(self, fieldnm): - """ Given a field name, returns a jvmgen.Field object """ + """ Given a field name, returns a jvm.Field object """ _, FIELDTY = self.OOTYPE._lookup_field(fieldnm) jfieldty = self.db.lltype_to_cts(FIELDTY) - return jvmgen.Field( + return jvm.Field( self.descriptor.class_name(), fieldnm, jfieldty, False) def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + """ Given the method name, returns a jvm.Method object """ # Look for a shortcut method in our table of remappings: try: @@ -56,14 +55,14 @@ if self.OOTYPE.__class__ in bridged_objects: # Bridged objects are ones where we have written a java class # that has methods with the correct names and types already - return jvmgen.Method.v(self, methodnm, jargtypes, jrettype) + return jvm.Method.v(self, methodnm, jargtypes, jrettype) else: # By default, we assume it is a static method on the PyPy # object, that takes an instance of this object as the first # argument. The other arguments we just convert to java versions, # except for generics. jargtypes = [self] + jargtypes - return jvmgen.Method.s(jPyPy, methodnm, jargtypes, jrettype) + return jvm.Method.s(jPyPy, methodnm, jargtypes, jrettype) # When we lookup a method on a BuiltInClassNode, we first check the # 'built_in_methods' and 'bridged_objects' tables. This allows us to @@ -80,73 +79,73 @@ # .__class__ is required (ootype.StringBuilder.__class__, "ll_allocate"): - jvmgen.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid), + jvm.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid), (ootype.StringBuilder.__class__, "ll_build"): - jvmgen.Method.v(jStringBuilder, "toString", (), jString), + jvm.Method.v(jStringBuilder, "toString", (), jString), (ootype.String.__class__, "ll_streq"): - jvmgen.Method.v(jString, "equals", (jObject,), jBool), + jvm.Method.v(jString, "equals", (jObject,), jBool), (ootype.String.__class__, "ll_strlen"): - jvmgen.Method.v(jString, "length", (), jInt), + jvm.Method.v(jString, "length", (), jInt), (ootype.String.__class__, "ll_stritem_nonneg"): - jvmgen.Method.v(jString, "charAt", (jInt,), jChar), + jvm.Method.v(jString, "charAt", (jInt,), jChar), (ootype.String.__class__, "ll_startswith"): - jvmgen.Method.v(jString, "startsWith", (jString,), jBool), + jvm.Method.v(jString, "startsWith", (jString,), jBool), (ootype.String.__class__, "ll_endswith"): - jvmgen.Method.v(jString, "endsWith", (jString,), jBool), + jvm.Method.v(jString, "endsWith", (jString,), jBool), (ootype.String.__class__, "ll_strcmp"): - jvmgen.Method.v(jString, "compareTo", (jString,), jInt), + jvm.Method.v(jString, "compareTo", (jString,), jInt), (ootype.String.__class__, "ll_upper"): - jvmgen.Method.v(jString, "toUpperCase", (), jString), + jvm.Method.v(jString, "toUpperCase", (), jString), (ootype.String.__class__, "ll_lower"): - jvmgen.Method.v(jString, "toLowerCase", (), jString), + jvm.Method.v(jString, "toLowerCase", (), jString), (ootype.String.__class__, "ll_replace_chr_chr"): - jvmgen.Method.v(jString, "replace", (jChar, jChar), jString), + jvm.Method.v(jString, "replace", (jChar, jChar), jString), (ootype.Dict, "ll_set"): - jvmgen.Method.v(jHashMap, "put", (jObject, jObject), jObject), + jvm.Method.v(jHashMap, "put", (jObject, jObject), jObject), (ootype.Dict, "ll_get"): - jvmgen.Method.v(jHashMap, "get", (jObject,), jObject), + jvm.Method.v(jHashMap, "get", (jObject,), jObject), (ootype.Dict, "ll_contains"): - jvmgen.Method.v(jHashMap, "containsKey", (jObject,), jBool), + jvm.Method.v(jHashMap, "containsKey", (jObject,), jBool), (ootype.Dict, "ll_length"): - jvmgen.Method.v(jHashMap, "size", (), jInt), + jvm.Method.v(jHashMap, "size", (), jInt), (ootype.Dict, "ll_clear"): - jvmgen.Method.v(jHashMap, "clear", (), jVoid), + jvm.Method.v(jHashMap, "clear", (), jVoid), (ootype.CustomDict, "ll_set"): - jvmgen.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject), + jvm.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject), (ootype.CustomDict, "ll_get"): - jvmgen.Method.v(jPyPyCustomDict, "get", (jObject,), jObject), + jvm.Method.v(jPyPyCustomDict, "get", (jObject,), jObject), (ootype.CustomDict, "ll_contains"): - jvmgen.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool), + jvm.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool), (ootype.CustomDict, "ll_length"): - jvmgen.Method.v(jPyPyCustomDict, "size", (), jInt), + jvm.Method.v(jPyPyCustomDict, "size", (), jInt), (ootype.CustomDict, "ll_clear"): - jvmgen.Method.v(jPyPyCustomDict, "clear", (), jVoid), + jvm.Method.v(jPyPyCustomDict, "clear", (), jVoid), (ootype.List, "ll_length"): - jvmgen.Method.v(jArrayList, "size", (), jInt), + jvm.Method.v(jArrayList, "size", (), jInt), (ootype.List, "ll_getitem_fast"): - jvmgen.Method.v(jArrayList, "get", (jInt,), jObject), + jvm.Method.v(jArrayList, "get", (jInt,), jObject), } Modified: pypy/dist/pypy/translator/jvm/cmpopcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/cmpopcodes.py (original) +++ pypy/dist/pypy/translator/jvm/cmpopcodes.py Fri Apr 4 15:10:29 2008 @@ -1,9 +1,11 @@ -from pypy.translator.jvm.generator import \ +from pypy.translator.jvm.typesystem import \ IFLT, IFLE, IFEQ, IFNE, IFGT, IFGE, \ IFNONNULL, IF_ACMPEQ, GOTO, ICONST, \ DCONST_0, DCMPG, LCONST_0, LCMP, \ IF_ICMPLT, IF_ICMPLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPGT, IF_ICMPGE, \ - PYPYUINTCMP, PYPYULONGCMP, \ + PYPYUINTCMP, PYPYULONGCMP + +from pypy.translator.jvm.generator import \ Label ##### Branch directly as the result of a comparison Modified: pypy/dist/pypy/translator/jvm/constant.py ============================================================================== --- pypy/dist/pypy/translator/jvm/constant.py (original) +++ pypy/dist/pypy/translator/jvm/constant.py Fri Apr 4 15:10:29 2008 @@ -1,15 +1,14 @@ from pypy.rpython.ootypesystem import ootype from pypy.objspace.flow import model as flowmodel -from pypy.translator.jvm.generator import \ - Field, Method, CUSTOMDICTMAKE +import pypy.translator.jvm.typesystem as jvm +from pypy.translator.jvm.typesystem import \ + jVoid, Method, Field from pypy.translator.oosupport.constant import \ BaseConstantGenerator, RecordConst, InstanceConst, ClassConst, \ StaticMethodConst, CustomDictConst, WeakRefConst, push_constant, \ MAX_CONST_PER_STEP -from pypy.translator.jvm.typesystem import \ - jObject, jVoid, jPyPyWeakRef, JvmClassType -jPyPyConstantInit = JvmClassType('pypy.ConstantInit') +jPyPyConstantInit = jvm.JvmClassType('pypy.ConstantInit') jPyPyConstantInitMethod = Method.s(jPyPyConstantInit, 'init', [], jVoid) # ___________________________________________________________________________ @@ -51,7 +50,7 @@ # This prevents any one class from getting too big. if (self.num_constants % MAX_CONST_PER_STEP) == 0: cc_num = len(self.ccs) - self.ccs.append(JvmClassType('pypy.Constant_%d' % cc_num)) + self.ccs.append(jvm.JvmClassType('pypy.Constant_%d' % cc_num)) self.num_constants += 1 const.fieldobj = Field(self.ccs[-1].name, const.name, jfieldty, True) @@ -99,7 +98,7 @@ except KeyError: constants_by_cls[const.fieldobj.class_name] = [const] for cc in self.ccs: - ilasm.begin_class(cc, jObject) + ilasm.begin_class(cc, jvm.jObject) for const in constants_by_cls[cc.name]: ilasm.add_field(const.fieldobj) ilasm.end_class() @@ -122,8 +121,9 @@ self._push_constant_during_init(gen, const) def _declare_step(self, gen, stepnum): - self.step_classes.append(JvmClassType('pypy.ConstantInit_%d' % stepnum)) - gen.begin_class(self.step_classes[-1], jObject) + self.step_classes.append(jvm.JvmClassType( + 'pypy.ConstantInit_%d' % stepnum)) + gen.begin_class(self.step_classes[-1], jvm.jObject) gen.begin_function('constant_init', [], [], jVoid, True) def _close_step(self, gen, stepnum): @@ -132,7 +132,7 @@ gen.end_class() # end pypy.ConstantInit_NNN def _end_gen_constants(self, gen, numsteps): - gen.begin_class(jPyPyConstantInit, jObject) + gen.begin_class(jPyPyConstantInit, jvm.jObject) gen.begin_j_function(jPyPyConstantInit, jPyPyConstantInitMethod) for cls in self.step_classes: m = Method.s(cls, "constant_init", [], jVoid) @@ -156,7 +156,7 @@ if self.delegate_impl: gen.new_with_jtype(self.delegate_impl) else: - gen.push_null(jObject) + gen.push_null(jvm.jObject) def initialize_data(self, constgen, gen): return @@ -180,7 +180,7 @@ def create_pointer(self, gen): gen.new_with_jtype(self.eq_jcls) gen.new_with_jtype(self.hash_jcls) - gen.emit(CUSTOMDICTMAKE) + gen.emit(jvm.CUSTOMDICTMAKE) class JVMWeakRefConst(WeakRefConst): @@ -188,7 +188,7 @@ PRIORITY = 200 def jtype(self): - return jPyPyWeakRef + return jvm.jPyPyWeakRef def create_pointer(self, gen): if not self.value: Modified: pypy/dist/pypy/translator/jvm/database.py ============================================================================== --- pypy/dist/pypy/translator/jvm/database.py (original) +++ pypy/dist/pypy/translator/jvm/database.py Fri Apr 4 15:10:29 2008 @@ -7,21 +7,15 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.ootypesystem import ootype, rclass from pypy.rpython.ootypesystem.module import ll_os -from pypy.translator.jvm import typesystem as jvmtype from pypy.translator.jvm import node, methods from pypy.translator.jvm.option import getoption -import pypy.translator.jvm.generator as jvmgen -from pypy.translator.jvm.generator import Method, Property, Field -import pypy.translator.jvm.constant as jvmconst -from pypy.translator.jvm.typesystem import \ - jStringBuilder, jInt, jVoid, jString, jChar, jObject, \ - jThrowable, JvmNativeClass, jPyPy, JvmClassType from pypy.translator.jvm.builtin import JvmBuiltInType - from pypy.translator.oosupport.database import Database as OODatabase from pypy.rpython.ootypesystem.bltregistry import ExternalType from pypy.annotation.signature import annotation from pypy.annotation.model import annotation_to_lltype +import pypy.translator.jvm.constant as jvmconst +import pypy.translator.jvm.typesystem as jvm # ______________________________________________________________________ # Database object @@ -34,7 +28,7 @@ self._jasmin_files = [] # list of strings --- .j files we made self._classes = {} # Maps ootype class objects to node.Class objects, # and JvmType objects as well - self._functions = {} # graph -> jvmgen.Method + self._functions = {} # graph -> jvm.Method # (jargtypes, jrettype) -> node.StaticMethodInterface self._delegates = {} @@ -44,7 +38,7 @@ self._function_names = {} # graph --> function_name - self._constants = {} # flowmodel.Variable --> jvmgen.Const + self._constants = {} # flowmodel.Variable --> jvm.Const # Special fields for the Object class, see _translate_Object self._object_interf = None @@ -65,11 +59,11 @@ # # These are public attributes that are referenced from # elsewhere in the code using - # jvmgen.Generator.push_interlink() and .push_pypy(). - self.jPyPyMain = JvmClassType(self._pkg('Main')) - self.pypy_field = jvmgen.Field.s(self.jPyPyMain, 'pypy', jPyPy) - self.interlink_field = jvmgen.Field.s(self.jPyPyMain, 'ilink', - jvmtype.jPyPyInterlink) + # jvm.Generator.push_interlink() and .push_pypy(). + self.jPyPyMain = jvm.JvmClassType(self._pkg('Main')) + self.pypy_field = jvm.Field.s(self.jPyPyMain, 'pypy', jvm.jPyPy) + self.interlink_field = jvm.Field.s(self.jPyPyMain, 'ilink', + jvm.jPyPyInterlink) # _________________________________________________________________ # Java String vs Byte Array @@ -93,7 +87,7 @@ def class_name(self, TYPE): jtype = self.lltype_to_cts(TYPE) - assert isinstance(jtype, jvmtype.JvmClassType) + assert isinstance(jtype, jvm.JvmClassType) return jtype.name def add_jasmin_file(self, jfile): @@ -120,14 +114,14 @@ like. The 'methods' argument should be a dictionary whose keys are - method names and whose entries are jvmgen.Method objects which + method names and whose entries are jvm.Method objects which the corresponding method should invoke. """ nm = self._pkg(self._uniq('InterlinkImplementation')) - cls = node.Class(nm, supercls=jObject) + cls = node.Class(nm, supercls=jvm.jObject) for method_name, helper in methods.items(): cls.add_method(node.InterlinkFunction(cls, method_name, helper)) - cls.add_interface(jvmtype.jPyPyInterlink) + cls.add_interface(jvm.jPyPyInterlink) self.jInterlinkImplementation = cls self.pending_node(cls) @@ -169,7 +163,7 @@ # Create the class object first clsnm = self._pkg(self._uniq('Record')) - clsobj = node.Class(clsnm, jObject) + clsobj = node.Class(clsnm, jvm.jObject) self._classes[OOTYPE] = clsobj # Add fields: @@ -205,8 +199,8 @@ def gen_name(): return self._pkg(self._uniq(OBJ._name)) internm, implnm, exc_implnm = gen_name(), gen_name(), gen_name() self._object_interf = node.Interface(internm) - self._object_impl = node.Class(implnm, supercls=jObject) - self._object_exc_impl = node.Class(exc_implnm, supercls=jThrowable) + self._object_impl = node.Class(implnm, supercls=jvm.jObject) + self._object_exc_impl = node.Class(exc_implnm, supercls=jvm.jThrowable) self._object_impl.add_interface(self._object_interf) self._object_exc_impl.add_interface(self._object_interf) @@ -220,12 +214,12 @@ methodnm = "_jvm_"+fieldnm def getter_method_obj(node): - return Method.v(node, methodnm+"_g", [], fieldty) + return jvm.Method.v(node, methodnm+"_g", [], fieldty) def putter_method_obj(node): - return Method.v(node, methodnm+"_p", [fieldty], jVoid) + return jvm.Method.v(node, methodnm+"_p", [fieldty], jvm.jVoid) # Add get/put methods to the interface: - prop = Property( + prop = jvm.Property( fieldnm, getter_method_obj(self._object_interf), putter_method_obj(self._object_interf), @@ -235,7 +229,7 @@ # Generate implementations: def generate_impl(clsobj): clsnm = clsobj.name - fieldobj = Field(clsnm, fieldnm, fieldty, False, FIELDOOTY) + fieldobj = jvm.Field(clsnm, fieldnm, fieldty, False, FIELDOOTY) clsobj.add_field(fieldobj, fielddef) clsobj.add_method(node.GetterFunction( self, clsobj, getter_method_obj(clsobj), fieldobj)) @@ -296,7 +290,7 @@ arglist = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] returntype = self.lltype_to_cts(METH.RESULT) - clsobj.add_abstract_method(jvmgen.Method.v( + clsobj.add_abstract_method(jvm.Method.v( clsobj, mname, arglist, returntype)) else: # if the first argument's type is not a supertype of @@ -323,7 +317,7 @@ if FIELDOOTY is ootype.Void: continue fieldty = self.lltype_to_cts(FIELDOOTY) clsobj.add_field( - jvmgen.Field(clsobj.name, fieldnm, fieldty, False, FIELDOOTY), + jvm.Field(clsobj.name, fieldnm, fieldty, False, FIELDOOTY), fielddef) def pending_class(self, OOTYPE): @@ -334,7 +328,7 @@ This is invoked when a standalone function is to be compiled. It creates a class named after the function with a single method, invoke(). This class is added to the worklist. - Returns a jvmgen.Method object that allows this function to be + Returns a jvm.Method object that allows this function to be invoked. """ if graph in self._functions: @@ -366,7 +360,7 @@ """ Like record_delegate, but the signature is in terms of java types. jargs is a list of JvmTypes, one for each argument, - and jret is a JvmType. Note that jargs does NOT include an + and jret is a Jvm. Note that jargs does NOT include an entry for the this pointer of the resulting object. """ key = (jargs, jret) @@ -424,17 +418,17 @@ # any type. _toString_methods = { - ootype.Signed:jvmgen.INTTOSTRINGI, - ootype.Unsigned:jvmgen.PYPYSERIALIZEUINT, - ootype.SignedLongLong:jvmgen.LONGTOSTRINGL, - ootype.UnsignedLongLong: jvmgen.PYPYSERIALIZEULONG, - ootype.Float:jvmgen.DOUBLETOSTRINGD, - ootype.Bool:jvmgen.PYPYSERIALIZEBOOLEAN, - ootype.Void:jvmgen.PYPYSERIALIZEVOID, - ootype.Char:jvmgen.PYPYESCAPEDCHAR, - ootype.UniChar:jvmgen.PYPYESCAPEDUNICHAR, - ootype.String:jvmgen.PYPYESCAPEDSTRING, - ootype.Unicode:jvmgen.PYPYESCAPEDUNICODE, + ootype.Signed:jvm.INTTOSTRINGI, + ootype.Unsigned:jvm.PYPYSERIALIZEUINT, + ootype.SignedLongLong:jvm.LONGTOSTRINGL, + ootype.UnsignedLongLong: jvm.PYPYSERIALIZEULONG, + ootype.Float:jvm.DOUBLETOSTRINGD, + ootype.Bool:jvm.PYPYSERIALIZEBOOLEAN, + ootype.Void:jvm.PYPYSERIALIZEVOID, + ootype.Char:jvm.PYPYESCAPEDCHAR, + ootype.UniChar:jvm.PYPYESCAPEDUNICHAR, + ootype.String:jvm.PYPYESCAPEDSTRING, + ootype.Unicode:jvm.PYPYESCAPEDUNICODE, } def toString_method_for_ootype(self, OOTYPE): @@ -451,7 +445,7 @@ to print the value of 'var'. """ - return self._toString_methods.get(OOTYPE, jvmgen.PYPYSERIALIZEOBJECT) + return self._toString_methods.get(OOTYPE, jvm.PYPYSERIALIZEOBJECT) # _________________________________________________________________ # Type translation functions @@ -471,46 +465,51 @@ # Dictionary for scalar types; in this case, if we see the key, we # will return the value ootype_to_scalar = { - ootype.Void: jvmtype.jVoid, - ootype.Signed: jvmtype.jInt, - ootype.Unsigned: jvmtype.jInt, - ootype.SignedLongLong: jvmtype.jLong, - ootype.UnsignedLongLong: jvmtype.jLong, - ootype.Bool: jvmtype.jBool, - ootype.Float: jvmtype.jDouble, - ootype.Char: jvmtype.jChar, # byte would be sufficient, but harder - ootype.UniChar: jvmtype.jChar, - ootype.Class: jvmtype.jClass, - ootype.ROOT: jvmtype.jObject, # treat like a scalar + ootype.Void: jvm.jVoid, + ootype.Signed: jvm.jInt, + ootype.Unsigned: jvm.jInt, + ootype.SignedLongLong: jvm.jLong, + ootype.UnsignedLongLong: jvm.jLong, + ootype.Bool: jvm.jBool, + ootype.Float: jvm.jDouble, + ootype.Char: jvm.jChar, # byte would be sufficient, but harder + ootype.UniChar: jvm.jChar, + ootype.Class: jvm.jClass, + ootype.ROOT: jvm.jObject, # treat like a scalar } # Dictionary for non-scalar types; in this case, if we see the key, we # will return a JvmBuiltInType based on the value ootype_to_builtin = { - ootype.String: jvmtype.jString, - ootype.Unicode: jvmtype.jString, - ootype.StringBuilder: jvmtype.jStringBuilder, - ootype.UnicodeBuilder: jvmtype.jStringBuilder, - ootype.List: jvmtype.jArrayList, - ootype.Dict: jvmtype.jHashMap, - ootype.DictItemsIterator:jvmtype.jPyPyDictItemsIterator, - ootype.CustomDict: jvmtype.jPyPyCustomDict, - ootype.WeakReference: jvmtype.jPyPyWeakRef, - ll_os.STAT_RESULT: jvmtype.jPyPyStatResult, + ootype.String: jvm.jString, + ootype.Unicode: jvm.jString, + ootype.StringBuilder: jvm.jStringBuilder, + ootype.UnicodeBuilder: jvm.jStringBuilder, + ootype.List: jvm.jArrayList, + ootype.Dict: jvm.jHashMap, + ootype.DictItemsIterator:jvm.jPyPyDictItemsIterator, + ootype.CustomDict: jvm.jPyPyCustomDict, + ootype.WeakReference: jvm.jPyPyWeakRef, + ll_os.STAT_RESULT: jvm.jPyPyStatResult, # These are some configured records that are generated by Java # code. #ootype.Record({"item0": ootype.Signed, "item1": ootype.Signed}): - #jvmtype.jPyPyRecordSignedSigned, + #jvm.jPyPyRecordSignedSigned, #ootype.Record({"item0": ootype.Float, "item1": ootype.Signed}): - #jvmtype.jPyPyRecordFloatSigned, + #jvm.jPyPyRecordFloatSigned, #ootype.Record({"item0": ootype.Float, "item1": ootype.Float}): - #jvmtype.jPyPyRecordFloatFloat, + #jvm.jPyPyRecordFloatFloat, #ootype.Record({"item0": ootype.String, "item1": ootype.String}): - #jvmtype.jPyPyRecordStringString, + #jvm.jPyPyRecordStringString, } def lltype_to_cts(self, OOT): + import sys + res = self._lltype_to_cts(OOT) + return res + + def _lltype_to_cts(self, OOT): """ Returns an instance of JvmType corresponding to the given OOType """ @@ -519,9 +518,11 @@ return self.ootype_to_scalar[OOT] if (isinstance(OOT, lltype.Ptr) and isinstance(OOT.TO, lltype.OpaqueType)): - return jObject + return jvm.jObject if OOT in self.ootype_to_builtin: return JvmBuiltInType(self, self.ootype_to_builtin[OOT], OOT) + if isinstance(OOT, ootype.Array): + return self._array_type(OOT.ITEM) if OOT.__class__ in self.ootype_to_builtin: return JvmBuiltInType( self, self.ootype_to_builtin[OOT.__class__], OOT) @@ -538,10 +539,26 @@ # handle externals if isinstance(OOT, ExternalType): - return JvmNativeClass(self, OOT) + return jvm.JvmNativeClass(self, OOT) assert False, "Untranslatable type %s!" % OOT + ooitemtype_to_array = { + ootype.Signed : jvm.jIntArray, + ootype.Unsigned : jvm.jIntArray, + ootype.Char : jvm.jCharArray, + ootype.Bool : jvm.jBoolArray, + ootype.UniChar : jvm.jCharArray, + ootype.String : jvm.jStringArray, + ootype.Float : jvm.jDoubleArray, + ootype.Void : jvm.jVoidArray, + } + + def _array_type(self, ITEM): + if ITEM in self.ooitemtype_to_array: + return self.ooitemtype_to_array[ITEM] + return jvm.jObjectArray + def annotation_to_cts(self, _tp): s_tp = annotation(_tp) TP = annotation_to_lltype(s_tp) Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Fri Apr 4 15:10:29 2008 @@ -12,231 +12,11 @@ from pypy.rlib.objectmodel import CDefinedIntSymbolic from pypy.rlib.rarithmetic import isnan, isinf from pypy.translator.oosupport.constant import push_constant -import pypy.translator.jvm.typesystem as jvmtype -from pypy.translator.jvm.typesystem import \ - JvmType, jString, jInt, jLong, jDouble, jBool, jString, \ - jPyPy, jVoid, jMath, desc_for_method, jPrintStream, jClass, jChar, \ - jObject, jByteArray, jPyPyExcWrap, jIntegerClass, jLongClass, \ - jDoubleClass, jCharClass, jStringBuilder, JvmScalarType, jArrayList, \ - jObjectArray, jPyPyInterlink, jPyPyCustomDict, jPyPyEquals, \ - jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os, jPyPyInterlink - - -# ___________________________________________________________________________ -# JVM Opcodes: -# -# Map from symbolic name to an instance of the Opcode class - -class Opcode(object): - def __init__(self, jvmstr): - """ - flags is a set of flags (see above) that describe opcode #UPDATE - jvmstr is the name for jasmin printouts - """ - self.jvmstr = jvmstr - self.flags = None #Should flags be added to args? - - def __repr__(self): - return "" % (self.jvmstr, self.flags) - - def specialize(self, args): - """ Process the argument list according to the various flags. - Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing - the new opcode, and ARGS is a list of arguments or empty tuple. - Most of these do not do anything. """ - return (self.jvmstr, args) - -class IntConstOpcode(Opcode): - """ The ICONST opcode specializes itself for small integer opcodes. """ - def specialize(self, args): - assert len(args) == 1 - if args[0] == -1: - return self.jvmstr + "_m1", () - elif args[0] >= 0 and args[0] <= 5: - return self.jvmstr + "_" + str(args[0]), () - # Non obvious: convert ICONST to LDC if the constant is out of - # range - return "ldc", args - -class VarOpcode(Opcode): - """ An Opcode which takes a variable index as an argument; specialized - to small integer indices. """ - def specialize(self, args): - assert len(args) == 1 - if args[0] >= 0 and args[0] <= 3: - return self.jvmstr + "_" + str(args[0]), () - return Opcode.specialize(self, args) - -class IntClassNameOpcode(Opcode): - """ An opcode which takes an internal class name as its argument; - the actual argument will be a JvmType instance. """ - def specialize(self, args): - args = [args[0].descriptor.int_class_name()] - return self.jvmstr, args - -class OpcodeFamily(object): - """ - Many opcodes in JVM have variants that depend on the type of the - operands; for example, one must choose the correct ALOAD, ILOAD, - or DLOAD depending on whether one is loading a reference, integer, - or double variable respectively. Each instance of this class - defines one 'family' of opcodes, such as the LOAD family shown - above, and produces Opcode objects specific to a particular type. - """ - def __init__(self, opcclass, suffix): - """ - opcclass is the opcode subclass to use (see above) when - instantiating a particular opcode - - jvmstr is the name for jasmin printouts - """ - self.opcode_class = opcclass - self.suffix = suffix - self.cache = {} - - def _o(self, prefix): - try: - return self.cache[prefix] - except KeyError: - self.cache[prefix] = obj = self.opcode_class( - prefix+self.suffix) - return obj - - def for_type(self, argtype): - """ Returns a customized opcode of this family appropriate to - 'argtype', a JvmType object. """ - - desc = argtype.descriptor - - # These are always true: - if desc[0] == 'L': return self._o("a") # Objects - if desc[0] == '[': return self._o("a") # Arrays - if desc == 'I': return self._o("i") # Integers - if desc == 'J': return self._o("l") # Integers - if desc == 'D': return self._o("d") # Doubles - if desc == 'V': return self._o("") # Void [used by RETURN] - - # Chars/Bytes/Booleans are normally represented as ints - # in the JVM, but some opcodes are different. They use a - # different OpcodeFamily (see ArrayOpcodeFamily for ex) - if desc == 'C': return self._o("i") # Characters - if desc == 'B': return self._o("i") # Bytes - if desc == 'Z': return self._o("i") # Boolean +import pypy.translator.jvm.typesystem as jvm - assert False, "Unknown argtype=%s" % repr(argtype) - raise NotImplementedError - -class ArrayOpcodeFamily(OpcodeFamily): - """ Opcode family specialized for array access instr """ - def for_type(self, argtype): - desc = argtype.descriptor - if desc == 'J': return self._o("l") # Integers - if desc == 'D': return self._o("d") # Doubles - if desc == 'C': return self._o("c") # Characters - if desc == 'B': return self._o("b") # Bytes - if desc == 'Z': return self._o("b") # Boolean (access as bytes) - return OpcodeFamily.for_type(self, argtype) - -# Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx -# variants compare a single integer arg against 0, and the IF_ICMPxx -# variants compare 2 integer arguments against each other. -for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'): - ifop = "if%s" % cmpop - if_icmpop = "if_icmp%s" % cmpop - globals()[ifop.upper()] = Opcode(ifop) - globals()[if_icmpop.upper()] = Opcode(if_icmpop) - -# Compare references, either against NULL or against each other -IFNULL = Opcode('ifnull') -IFNONNULL = Opcode('ifnonnull') -IF_ACMPEQ = Opcode('if_acmpeq') -IF_ACMPNE = Opcode('if_acmpne') - -# Method invocation -INVOKESTATIC = Opcode('invokestatic') -INVOKEVIRTUAL = Opcode('invokevirtual') -INVOKESPECIAL = Opcode('invokespecial') -INVOKEINTERFACE = Opcode('invokeinterface') - -# Other opcodes -LDC = Opcode('ldc') # single-word types -LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs -GOTO = Opcode('goto') -ICONST = IntConstOpcode('iconst') -ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly -ACONST_NULL=Opcode('aconst_null') -DCONST_0 = Opcode('dconst_0') -DCONST_1 = Opcode('dconst_1') -LCONST_0 = Opcode('lconst_0') -LCONST_1 = Opcode('lconst_1') -GETFIELD = Opcode('getfield') -PUTFIELD = Opcode('putfield') -GETSTATIC = Opcode('getstatic') -PUTSTATIC = Opcode('putstatic') -CHECKCAST = IntClassNameOpcode('checkcast') -INEG = Opcode('ineg') -IXOR = Opcode('ixor') -IADD = Opcode('iadd') -ISUB = Opcode('isub') -IMUL = Opcode('imul') -IDIV = Opcode('idiv') -IREM = Opcode('irem') -IAND = Opcode('iand') -IOR = Opcode('ior') -ISHL = Opcode('ishl') -ISHR = Opcode('ishr') -IUSHR = Opcode('iushr') -LCMP = Opcode('lcmp') -DCMPG = Opcode('dcmpg') -DCMPL = Opcode('dcmpl') -NOP = Opcode('nop') -I2D = Opcode('i2d') -I2L = Opcode('i2l') -D2I= Opcode('d2i') -#D2L= Opcode('d2l') #PAUL -L2I = Opcode('l2i') -L2D = Opcode('l2d') -ATHROW = Opcode('athrow') -DNEG = Opcode('dneg') -DADD = Opcode('dadd') -DSUB = Opcode('dsub') -DMUL = Opcode('dmul') -DDIV = Opcode('ddiv') -DREM = Opcode('drem') -LNEG = Opcode('lneg') -LADD = Opcode('ladd') -LSUB = Opcode('lsub') -LMUL = Opcode('lmul') -LDIV = Opcode('ldiv') -LREM = Opcode('lrem') -LAND = Opcode('land') -LOR = Opcode('lor') -LXOR = Opcode('lxor') -LSHL = Opcode('lshl') -LSHR = Opcode('lshr') -LUSHR = Opcode('lushr') -NEW = IntClassNameOpcode('new') -DUP = Opcode('dup') -DUP2 = Opcode('dup2') -DUP_X1 = Opcode('dup_x1') -POP = Opcode('pop') -POP2 = Opcode('pop2') -SWAP = Opcode('swap') -INSTANCEOF= IntClassNameOpcode('instanceof') -# Loading/storing local variables -LOAD = OpcodeFamily(VarOpcode, "load") -STORE = OpcodeFamily(VarOpcode, "store") -RETURN = OpcodeFamily(Opcode, "return") - -# Loading/storing from arrays -# *NOTE*: This family is characterized by the type of the ELEMENT, -# not the type of the ARRAY. -# -# Also: here I break from convention by naming the objects ARRLOAD -# rather than ALOAD, even though the suffix is 'aload'. This is to -# avoid confusion with the ALOAD opcode. -ARRLOAD = ArrayOpcodeFamily(Opcode, "aload") -ARRSTORE = ArrayOpcodeFamily(Opcode, "astore") +# Load a few commonly used names, but prefer to use 'jvm.Name' +from pypy.translator.jvm.typesystem import \ + jPyPy, jString, jInt, jVoid # ___________________________________________________________________________ # Labels @@ -257,244 +37,6 @@ return self.label # ___________________________________________________________________________ -# Methods -# -# "Method" objects describe all the information needed to invoke a -# method. We create one for each node.Function object, as well as for -# various helper methods (defined below). To invoke a method, you -# push its arguments and then use generator.emit(methobj) where -# methobj is its Method instance. - -class Method(object): - - # Create a constructor: - def c(classty, argtypes): - return Method(classty.name, "", argtypes, jVoid, - opcode=INVOKESPECIAL) - c = staticmethod(c) - - # Create a virtual or interface method: - def v(classty, methnm, argtypes, rettype): - """ - Shorthand to create a virtual method. - 'class' - JvmType object for the class - 'methnm' - name of the method (Python string) - 'argtypes' - list of JvmType objects, one for each argument but - not the this ptr - 'rettype' - JvmType for return type - """ - assert argtypes is not None - assert rettype is not None - classnm = classty.name - if isinstance(classty, jvmtype.JvmInterfaceType): - opc = INVOKEINTERFACE - else: - assert isinstance(classty, jvmtype.JvmClassType) - opc = INVOKEVIRTUAL - return Method(classnm, methnm, argtypes, rettype, opcode=opc) - v = staticmethod(v) - - # Create a static method: - def s(classty, methnm, argtypes, rettype): - """ - Shorthand to create a static method. - 'class' - JvmType object for the class - 'methnm' - name of the method (Python string) - 'argtypes' - list of JvmType objects, one for each argument but - not the this ptr - 'rettype' - JvmType for return type - """ - assert isinstance(classty, JvmType) - classnm = classty.name - return Method(classnm, methnm, argtypes, rettype) - s = staticmethod(s) - - def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC): - self.opcode = opcode - self.class_name = classnm # String, ie. "java.lang.Math" - self.method_name = methnm # String "abs" - self.argument_types = argtypes # List of jvmtypes - self.return_type = rettype # jvmtype - - # Compute the method descriptior, which is a string like "()I": - argtypesdesc = [a.descriptor for a in argtypes] - rettypedesc = rettype.descriptor - self.descriptor = desc_for_method(argtypesdesc, rettypedesc) - def invoke(self, gen): - gen._instr(self.opcode, self) - def is_static(self): - return self.opcode == INVOKESTATIC - def jasmin_syntax(self): - res = "%s/%s%s" % (self.class_name.replace('.','/'), - self.method_name, - self.descriptor) - # A weird, inexplicable quirk of Jasmin syntax is that it requires - # the number of arguments after an invokeinterface call: - if self.opcode == INVOKEINTERFACE: - res += " %d" % (len(self.argument_types)+1,) - return res - -OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt) -OBJTOSTRING = Method.v(jObject, 'toString', (), jString) -OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool) -SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid) -INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString) -LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString) -DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString) -CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString) -MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt) -IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt) -MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong) -LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong) -MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble) -INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt) -LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong) -IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt) -LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong) -ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt) -LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong) -IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt) -LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong) -MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble) -IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt) -LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong) -IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt) -LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong) -IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt) -LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong) -ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt) -LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong) -MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble) -PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid) -CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass) -CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool) -STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append', - (jString,), jStringBuilder) -PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt) -PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt) -PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt) -PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt) -PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt) -PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong) -PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble) -PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt) -PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL -PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong) -PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt) -PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt) -PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong) -PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong) -PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool) -PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble) -PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar) -PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble) -PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid) -PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid) -PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString) -PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString) -PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString) -PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString) -PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString) -PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString) -PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString) -PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString) -PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString) -PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) -PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) -PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList) -PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble) -OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) -CLASSGETNAME = Method.v(jClass, 'getName', (), jString) -CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make', - (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict) -PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef) -PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject) - -# ___________________________________________________________________________ -# Fields -# -# Field objects encode information about fields. - -class Field(object): - - @staticmethod - def i(classty, fieldnm, fieldty, OOTYPE=None): - """ - Shorthand to create an instance field. - 'class' - JvmType object for the class containing the field - 'fieldnm' - name of the field (Python string) - 'fieldty' - JvmType object for the type of the field - 'OOTYPE' - optional OOTYPE object for the type of the field - """ - return Field(classty.name, fieldnm, fieldty, False, OOTYPE) - - @staticmethod - def s(classty, fieldnm, fieldty, OOTYPE=None): - """ - Shorthand to create a static field. - 'class' - JvmType object for the class containing the field - 'fieldnm' - name of the field (Python string) - 'fieldty' - JvmType object for the type of the field - 'OOTYPE' - optional OOTYPE object for the type of the field - """ - return Field(classty.name, fieldnm, fieldty, True, OOTYPE) - - def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None): - # All fields are public - self.class_name = classnm # String, ie. "java.lang.Math" - self.field_name = fieldnm # String "someField" - self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None - self.jtype = jtype # JvmType - self.is_static = static # True or False - def load(self, gen): - if self.is_static: - gen._instr(GETSTATIC, self) - else: - gen._instr(GETFIELD, self) - def store(self, gen): - if self.is_static: - gen._instr(PUTSTATIC, self) - else: - gen._instr(PUTFIELD, self) - def jasmin_syntax(self): - return "%s/%s %s" % ( - self.class_name.replace('.','/'), - self.field_name, - self.jtype.descriptor) - -class Property(object): - """ - An object which acts like a Field, but when a value is loaded or - stored it actually invokes accessor methods. - """ - def __init__(self, field_name, get_method, put_method, OOTYPE=None): - self.get_method = get_method - self.put_method = put_method - self.field_name = field_name - self.OOTYPE = OOTYPE - - # Synthesize the Field attributes from the get_method/put_method: - self.class_name = get_method.class_name - assert put_method.class_name == self.class_name - self.jtype = get_method.return_type - self.is_static = get_method.is_static - def load(self, gen): - self.get_method.invoke(gen) - def store(self, gen): - self.put_method.invoke(gen) - # jasmin_syntax is not needed, since this object itself never appears - # as an argument an Opcode - -SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream) -SYSTEMERR = Field.s(jSystem, 'err', jPrintStream) -DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble) -DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble) -DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble) - -PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink) -PYPYOS = Field.i(jPyPy, 'os', jll_os) - -# ___________________________________________________________________________ # Generator State class ClassState(object): @@ -625,8 +167,7 @@ """ self.begin_function("", [], [self.current_type()], jVoid) self.load_jvm_var(self.current_type(), 0) - jmethod = Method(self.curclass.superclass_type.name, "", - (), jVoid, opcode=INVOKESPECIAL) + jmethod = jvm.Method.c(self.curclass.superclass_type, ()) jmethod.invoke(self) def end_constructor(self): @@ -700,14 +241,14 @@ def return_val(self, jtype): """ Returns a value from top of stack of the JvmType 'jtype' """ - self._instr(RETURN.for_type(jtype)) + self._instr(jvm.RETURN.for_type(jtype)) 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) + self.emit(jvm.OBJECTGETCLASS) + self.emit(jvm.CLASSGETNAME) def load_string(self, str): """ Pushes a Java version of a Python string onto the stack. @@ -724,7 +265,7 @@ '"') # Use LDC to load the Java version: # XXX --- support byte arrays here? Would be trickier! - self._instr(LDC, res) + self._instr(jvm.LDC, res) def load_jvm_var(self, jvartype, varidx): """ Loads from jvm slot #varidx, which is expected to hold a value of @@ -732,20 +273,20 @@ assert varidx < self.curfunc.next_offset if jvartype is jVoid: return - opc = LOAD.for_type(jvartype) + opc = jvm.LOAD.for_type(jvartype) self._instr(opc, varidx) def store_jvm_var(self, vartype, varidx): """ Loads from jvm slot #varidx, which is expected to hold a value of type vartype """ - self._instr(STORE.for_type(vartype), varidx) + self._instr(jvm.STORE.for_type(vartype), varidx) def load_from_array(self, elemtype): """ Loads something from an array; the result will be of type 'elemtype' (and hence the array is of type 'array_of(elemtype)'), where 'elemtype' is a JvmType. Assumes that the array ref and index are already pushed onto stack (in that order). """ - self._instr(ARRLOAD.for_type(elemtype)) + self._instr(jvm.ARRLOAD.for_type(elemtype)) def store_to_array(self, elemtype): """ Stores something into an array; the result will be of type @@ -753,7 +294,7 @@ 'array_of(elemtype)'), where 'elemtype' is a JvmType. Assumes that the array ref, index, and value are already pushed onto stack (in that order).""" - self._instr(ARRLOAD.for_type(elemtype)) + self._instr(jvm.ARRLOAD.for_type(elemtype)) def unique_label(self, desc, mark=False): """ Returns an opaque, unique label object that can be passed an @@ -773,7 +314,7 @@ def load_this_ptr(self): """ Convenience method. Be sure you only call it from a virtual method, not static methods. """ - self.load_jvm_var(jObject, 0) + self.load_jvm_var(jvm.jObject, 0) def load_function_argument(self, index): """ Convenience method. Loads function argument #index; note that @@ -786,9 +327,9 @@ self.prepare_generic_argument_with_jtype(jty) def prepare_generic_argument_with_jtype(self, jty): - if jty is jvmtype.jVoid: - self.emit(ACONST_NULL) - elif isinstance(jty, JvmScalarType): + if jty is jVoid: + self.emit(jvm.ACONST_NULL) + elif isinstance(jty, jvm.JvmScalarType): self.box_value(jty) def prepare_generic_result(self, ITEMTYPE): @@ -796,9 +337,9 @@ self.prepare_generic_result_with_jtype(jresty) def prepare_generic_result_with_jtype(self, jresty): - if jresty is jvmtype.jVoid: - self.emit(POP) - elif isinstance(jresty, JvmScalarType): + if jresty is jVoid: + self.emit(jvm.POP) + elif isinstance(jresty, jvm.JvmScalarType): # Perform any un-boxing required: self.downcast_jtype(jresty.box_type) self.unbox_value(jresty) @@ -810,20 +351,21 @@ """ Assuming that an value of type jscalartype is on the stack, boxes it into an Object. """ jclasstype = jscalartype.box_type - jmethod = Method.s(jclasstype, 'valueOf', (jscalartype,), jclasstype) + jmethod = jvm.Method.s( + jclasstype, 'valueOf', (jscalartype,), jclasstype) self.emit(jmethod) def unbox_value(self, jscalartype): """ Assuming that a boxed value of type jscalartype is on the stack, unboxes it. """ jclasstype = jscalartype.box_type - jmethod = Method.v( + jmethod = jvm.Method.v( jclasstype, jscalartype.unbox_method, (), jscalartype) self.emit(jmethod) def swap(self): """ Swaps the two words highest on the stack. """ - self.emit(SWAP) + self.emit(jvm.SWAP) # __________________________________________________________________ # Exception Handling @@ -869,14 +411,14 @@ _equals = { ootype.Void: (None,None), - ootype.SignedLongLong: (LCMP,IFEQ), - ootype.UnsignedLongLong: (LCMP,IFEQ), - ootype.Float: (DCMPG,IFEQ), - ootype.Signed: (None,IF_ICMPNE), - ootype.Unsigned: (None,IF_ICMPNE), - ootype.Bool: (None,IF_ICMPNE), - ootype.Char: (None,IF_ICMPNE), - ootype.UniChar: (None,IF_ICMPNE), + ootype.SignedLongLong: (jvm.LCMP, jvm.IFEQ), + ootype.UnsignedLongLong: (jvm.LCMP, jvm.IFEQ), + ootype.Float: (jvm.DCMPG, jvm.IFEQ), + ootype.Signed: (None,jvm.IF_ICMPNE), + ootype.Unsigned: (None,jvm.IF_ICMPNE), + ootype.Bool: (None,jvm.IF_ICMPNE), + ootype.Char: (None,jvm.IF_ICMPNE), + ootype.UniChar: (None,jvm.IF_ICMPNE), } def compare_values(self, OOTYPE, unequal_lbl): """ Assumes that two instances of OOTYPE are pushed on the stack; @@ -886,14 +428,14 @@ if i1: self.emit(i1) if i2: self.emit(i2, unequal_lbl) return - self.emit(OBJEQUALS) - self.emit(IFEQ, unequal_lbl) + self.emit(jvm.OBJEQUALS) + self.emit(jvm.IFEQ, unequal_lbl) _hash = { - ootype.Void: ICONST_0, - ootype.SignedLongLong: L2I, - ootype.UnsignedLongLong: L2I, - ootype.Float: D2I, + ootype.Void: jvm.ICONST_0, + ootype.SignedLongLong: jvm.L2I, + ootype.UnsignedLongLong: jvm.L2I, + ootype.Float: jvm.D2I, ootype.Signed: None, ootype.Unsigned: None, ootype.Bool: None, @@ -907,7 +449,7 @@ i1 = self._hash[OOTYPE] if i1: self.emit(i1) return - self.emit(OBJHASHCODE) + self.emit(jvm.OBJHASHCODE) # __________________________________________________________________ # Generator methods and others that are invoked by MicroInstructions @@ -919,16 +461,19 @@ it is the name of a method to invoke, or an Opcode/Method object (defined above).""" + if instr is None: + return + if isinstance(instr, str): return getattr(self, instr)(*args) - if isinstance(instr, Opcode): + if isinstance(instr, jvm.Opcode): return self._instr(instr, *args) - if isinstance(instr, Method): + if isinstance(instr, jvm.BaseMethod): return instr.invoke(self) - if isinstance(instr, Field) or isinstance(instr, Property): + if isinstance(instr, jvm.Field) or isinstance(instr, jvm.Property): return instr.load(self) raise Exception("Unknown object in call to emit(): "+repr(instr)) @@ -936,6 +481,7 @@ def _var_data(self, v): # Determine java type: jty = self.db.lltype_to_cts(v.concretetype) + import sys # Determine index in stack frame slots: # note that arguments and locals can be treated the same here return jty, self.curfunc.var_offset(v, jty) @@ -989,11 +535,11 @@ self.downcast_jtype(jtype) def downcast_jtype(self, jtype): - self._instr(CHECKCAST, jtype) + self._instr(jvm.CHECKCAST, jtype) def instanceof(self, TYPE): jtype = self.db.lltype_to_cts(TYPE) - self._instr(INSTANCEOF, jtype) + self._instr(jvm.INSTANCEOF, jtype) # included for compatibility with oosupport, but instanceof_jtype # follows our naming convention better @@ -1001,22 +547,22 @@ return self.instanceof_jtype(jtype) def instanceof_jtype(self, jtype): - self._instr(INSTANCEOF, jtype) + self._instr(jvm.INSTANCEOF, jtype) def branch_unconditionally(self, target_label): self.goto(target_label) def branch_conditionally(self, cond, target_label): if cond: - self._instr(IFNE, target_label) + self._instr(jvm.IFNE, target_label) else: - self._instr(IFEQ, target_label) + self._instr(jvm.IFEQ, target_label) def branch_if_equal(self, target_label): - self._instr(IF_ICMPEQ, target_label) + self._instr(jvm.IF_ICMPEQ, target_label) def branch_if_not_equal(self, target_label): - self._instr(IF_ICMPNE, target_label) + self._instr(jvm.IF_ICMPNE, target_label) def call_graph(self, graph): mthd = self.db.pending_function(graph) @@ -1028,7 +574,7 @@ mthd.invoke(self) # Check if we have to convert the result type at all: - gener = jvmtype.Generifier(OOCLASS) + gener = jvm.Generifier(OOCLASS) RETTYPE = gener.full_types(method_name)[1] jrettype = self.db.lltype_to_cts(RETTYPE) if jrettype != mthd.return_type: @@ -1043,7 +589,7 @@ # If necessary, load the ll_os object pointer instead: if module == 'll_os': - PYPYOS.load(self) + jvm.PYPYOS.load(self) def call_primitive(self, op, module, name): callee = op.args[0].value @@ -1052,7 +598,7 @@ # Determine what class the primitive is implemented in: if module == 'll_os': - jcls = jll_os + jcls = jvm.jll_os else: jcls = jPyPy @@ -1062,9 +608,9 @@ # the method cannot directly refer to the Java type in # .java source, as its name is not yet known. if jrettype.is_generated(): - mthd = Method.v(jcls, name, jargtypes, jObject) + mthd = jvm.Method.v(jcls, name, jargtypes, jvm.jObject) else: - mthd = Method.v(jcls, name, jargtypes, jrettype) + mthd = jvm.Method.v(jcls, name, jargtypes, jrettype) # Invoke the method self.emit(mthd) @@ -1081,13 +627,13 @@ cts_type = self.db.lltype_to_cts(OOTYPE) # treat all objects the same: - if isinstance(cts_type, jvmtype.JvmClassType): - cts_type = jObject + if isinstance(cts_type, jvm.JvmClassType): + cts_type = jvm.jObject - mthd = Method.v(jPyPy, 'oostring', [cts_type, jInt], jString) + mthd = jvm.Method.v(jPyPy, 'oostring', [cts_type, jInt], jString) self.emit(mthd) if self.db.using_byte_array: - self.emit(PYPYSTRING2BYTES) + self.emit(jvm.PYPYSTRING2BYTES) def prepare_call_oounicode(self, OOTYPE): # Load the PyPy object pointer onto the stack: @@ -1095,10 +641,10 @@ def call_oounicode(self, OOTYPE): cts_type = self.db.lltype_to_cts(OOTYPE) - mthd = Method.v(jPyPy, 'oounicode', [cts_type], jString) + mthd = jvm.Method.v(jPyPy, 'oounicode', [cts_type], jString) self.emit(mthd) if self.db.using_byte_array: - self.emit(PYPYSTRING2BYTES) + self.emit(jvm.PYPYSTRING2BYTES) def new(self, TYPE): jtype = self.db.lltype_to_cts(TYPE) @@ -1106,38 +652,43 @@ def new_with_jtype(self, jtype, ctor=None): if ctor is None: - ctor = Method.c(jtype, ()) - self.emit(NEW, jtype) - self.emit(DUP) + ctor = jvm.Method.c(jtype, ()) + self.emit(jvm.NEW, jtype) + self.emit(jvm.DUP) self.emit(ctor) + def oonewarray(self, TYPE, length): + jtype = self.db.lltype_to_cts(TYPE) + self.load(length) + jtype.make(self) + def instantiate(self): - self.emit(PYPYRUNTIMENEW) + self.emit(jvm.PYPYRUNTIMENEW) def getclassobject(self, OOINSTANCE): - jvmtype = self.db.lltype_to_cts(OOINSTANCE) - self.load_string(jvmtype.name) - CLASSFORNAME.invoke(self) + jtype = self.db.lltype_to_cts(OOINSTANCE) + self.load_string(jtype.name) + jvm.CLASSFORNAME.invoke(self) def dup(self, OOTYPE): - jvmtype = self.db.lltype_to_cts(OOTYPE) - self.dup_jtype(jvmtype) + jtype = self.db.lltype_to_cts(OOTYPE) + self.dup_jtype(jtype) - def dup_jtype(self, jvmtype): - if jvmtype.descriptor.type_width() == 1: - self.emit(DUP) + def dup_jtype(self, jtype): + if jtype.descriptor.type_width() == 1: + self.emit(jvm.DUP) else: - self.emit(DUP2) + self.emit(jvm.DUP2) def pop(self, OOTYPE): - jvmtype = self.db.lltype_to_cts(OOTYPE) - if jvmtype.descriptor.type_width() == 1: - self.emit(POP) + jtype = self.db.lltype_to_cts(OOTYPE) + if jtype.descriptor.type_width() == 1: + self.emit(jvm.POP) else: - self.emit(POP2) + self.emit(jvm.POP2) def push_null(self, OOTYPE): - self.emit(ACONST_NULL) + self.emit(jvm.ACONST_NULL) # we can't assume MALLOC_ZERO_FILLED, because for scalar type the # default item for ArrayList is null, not e.g. Integer(0) or @@ -1150,16 +701,16 @@ if TYPE is ootype.Void: return elif isinstance(value, CDefinedIntSymbolic): - self.emit(ICONST, self.DEFINED_INT_SYMBOLICS[value.expr]) + self.emit(jvm.ICONST, self.DEFINED_INT_SYMBOLICS[value.expr]) elif TYPE in (ootype.Bool, ootype.Signed): - self.emit(ICONST, int(value)) + self.emit(jvm.ICONST, int(value)) elif TYPE is ootype.Unsigned: # Converts the unsigned int into its corresponding signed value: if value > 0x7FFFFFFF: value = -((int(value) ^ 0xFFFFFFFF)+1) - self.emit(ICONST, value) + self.emit(jvm.ICONST, value) elif TYPE is ootype.Char or TYPE is ootype.UniChar: - self.emit(ICONST, ord(value)) + self.emit(jvm.ICONST, ord(value)) elif TYPE is ootype.SignedLongLong: self._push_long_constant(long(value)) elif TYPE is ootype.UnsignedLongLong: @@ -1171,7 +722,7 @@ self._push_double_constant(float(value)) elif TYPE in (ootype.String, ootype.Unicode): if value == ootype.null(TYPE): - self.emit(ACONST_NULL) + self.emit(jvm.ACONST_NULL) else: self.load_string(value._str) else: @@ -1179,25 +730,25 @@ def _push_long_constant(self, value): if value == 0: - self.emit(LCONST_0) + self.emit(jvm.LCONST_0) elif value == 1: - self.emit(LCONST_1) + self.emit(jvm.LCONST_1) else: - self.emit(LDC2, value) + self.emit(jvm.LDC2, value) def _push_double_constant(self, value): if isnan(value): - DOUBLENAN.load(self) + jvm.DOUBLENAN.load(self) elif isinf(value): - if value > 0: DOUBLEPOSINF.load(self) - else: DOUBLENEGINF.load(self) + if value > 0: jvm.DOUBLEPOSINF.load(self) + else: jvm.DOUBLENEGINF.load(self) elif value == 0.0: - self.emit(DCONST_0) + self.emit(jvm.DCONST_0) elif value == 1.0: - self.emit(DCONST_1) + self.emit(jvm.DCONST_1) else: # Big hack to avoid exponential notation: - self.emit(LDC2, "%22.22f" % value) + self.emit(jvm.LDC2, "%22.22f" % value) def create_weakref(self, OOTYPE): """ @@ -1207,7 +758,7 @@ The result will be that at the top of the stack is a weak reference. """ self.prepare_generic_argument(OOTYPE) - self.emit(PYPYWEAKREFCREATE) + self.emit(jvm.PYPYWEAKREFCREATE) def deref_weakref(self, OOTYPE): """ @@ -1215,7 +766,7 @@ that this weak ref is a pointer to. OOTYPE is the kind of object you had a weak reference to. """ - self.emit(PYPYWEAKREFGET) + self.emit(jvm.PYPYWEAKREFGET) self.prepare_generic_result(OOTYPE) # __________________________________________________________________ @@ -1223,30 +774,30 @@ def throw(self): """ Throw the object from top of the stack as an exception """ - self._instr(ATHROW) + self._instr(jvm.ATHROW) def iabs(self): - MATHIABS.invoke(self) + jvm.MATHIABS.invoke(self) def dbl_abs(self): - MATHDABS.invoke(self) + jvm.MATHDABS.invoke(self) def bitwise_negate(self): """ Invert all the bits in the "int" on the top of the stack """ - self._instr(ICONST, -1) - self._instr(IXOR) + self._instr(jvm.ICONST, -1) + self._instr(jvm.IXOR) def goto(self, label): """ Jumps unconditionally """ - self._instr(GOTO, label) + self._instr(jvm.GOTO, label) def goto_if_true(self, label): """ Jumps if the top of stack is true """ - self._instr(IFNE, label) + self._instr(jvm.IFNE, label) def goto_if_false(self, label): """ Jumps if the top of stack is false """ - self._instr(IFEQ, label) + self._instr(jvm.IFEQ, label) class JasminGenerator(JVMGenerator): Modified: pypy/dist/pypy/translator/jvm/metavm.py ============================================================================== --- pypy/dist/pypy/translator/jvm/metavm.py (original) +++ pypy/dist/pypy/translator/jvm/metavm.py Fri Apr 4 15:10:29 2008 @@ -1,8 +1,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.metavm import MicroInstruction from pypy.translator.jvm.typesystem import JvmScalarType, JvmClassType -import pypy.translator.jvm.generator as jvmgen -import pypy.translator.jvm.typesystem as jvmtype +import pypy.translator.jvm.typesystem as jvm from pypy.translator.jvm.builtin import JvmBuiltInType from pypy.translator.jvm import cmpopcodes @@ -86,13 +85,13 @@ def render(self, generator, op): self._load_func(generator, *op.args[1:4]) self._load_func(generator, *op.args[4:7]) - generator.emit(jvmgen.CUSTOMDICTMAKE) + generator.emit(jvm.CUSTOMDICTMAKE) NewCustomDict = _NewCustomDict() CASTS = { # FROM TO - (ootype.Signed, ootype.UnsignedLongLong): jvmgen.I2L, - (ootype.SignedLongLong, ootype.Signed): jvmgen.L2I, + (ootype.Signed, ootype.UnsignedLongLong): jvm.I2L, + (ootype.SignedLongLong, ootype.Signed): jvm.L2I, (ootype.UnsignedLongLong, ootype.SignedLongLong): None, } @@ -118,9 +117,9 @@ truelbl = generator.unique_label('load_comparision_result_true') endlbl = generator.unique_label('load_comparision_result_end') cmpopcodes.branch_if(generator, op.opname, truelbl) - generator.emit(jvmgen.ICONST, 0) + generator.emit(jvm.ICONST, 0) generator.goto(endlbl) generator.mark(truelbl) - generator.emit(jvmgen.ICONST, 1) + generator.emit(jvm.ICONST, 1) generator.mark(endlbl) PushComparisonResult = _PushComparisonResult() Modified: pypy/dist/pypy/translator/jvm/methods.py ============================================================================== --- pypy/dist/pypy/translator/jvm/methods.py (original) +++ pypy/dist/pypy/translator/jvm/methods.py Fri Apr 4 15:10:29 2008 @@ -7,8 +7,7 @@ """ -import pypy.translator.jvm.generator as jvmgen -import pypy.translator.jvm.typesystem as jvmtype +import pypy.translator.jvm.typesystem as jvm from pypy.rpython.ootypesystem import ootype, rclass class BaseDumpMethod(object): @@ -19,7 +18,7 @@ self.clsobj = clsobj self.name = "toString" self.jargtypes = [clsobj] - self.jrettype = jvmtype.jString + self.jrettype = jvm.jString def _print_field_value(self, fieldnm, FIELDOOTY): self.gen.load_this_ptr() @@ -27,21 +26,21 @@ fieldobj.load(self.gen) dumpmethod = self.db.toString_method_for_ootype(FIELDOOTY) self.gen.emit(dumpmethod) - self.gen.emit(jvmgen.STRINGBUILDERAPPEND) + self.gen.emit(jvm.STRINGBUILDERAPPEND) def _print(self, str): self.gen.load_string(str) - self.gen.emit(jvmgen.STRINGBUILDERAPPEND) + self.gen.emit(jvm.STRINGBUILDERAPPEND) def render(self, gen): self.gen = gen gen.begin_function( self.name, (), self.jargtypes, self.jrettype, static=False) - gen.new_with_jtype(jvmtype.jStringBuilder) + gen.new_with_jtype(jvm.jStringBuilder) self._render_guts(gen) - gen.emit(jvmgen.OBJTOSTRING) - gen.emit(jvmgen.RETURN.for_type(jvmtype.jString)) + gen.emit(jvm.OBJTOSTRING) + gen.emit(jvm.RETURN.for_type(jvm.jString)) gen.end_function() self.gen = None @@ -117,8 +116,8 @@ self.OOCLASS = OOCLASS self.clsobj = clsobj self.name = "equals" - self.jargtypes = [clsobj, jvmtype.jObject] - self.jrettype = jvmtype.jBool + self.jargtypes = [clsobj, jvm.jObject] + self.jrettype = jvm.jBool def render(self, gen): self.gen = gen @@ -156,10 +155,10 @@ # Return true or false as appropriate gen.push_primitive_constant(ootype.Bool, True) - gen.return_val(jvmtype.jBool) + gen.return_val(jvm.jBool) gen.mark(unequal_lbl) gen.push_primitive_constant(ootype.Bool, False) - gen.return_val(jvmtype.jBool) + gen.return_val(jvm.jBool) gen.end_function() @@ -171,7 +170,7 @@ self.clsobj = clsobj self.name = "hashCode" self.jargtypes = [clsobj] - self.jrettype = jvmtype.jInt + self.jrettype = jvm.jInt def render(self, gen): self.gen = gen @@ -194,10 +193,10 @@ gen.hash_value(FIELDOOTY) # XOR that with the main hash - gen.emit(jvmgen.IXOR) + gen.emit(jvm.IXOR) # Return the final hash - gen.return_val(jvmtype.jInt) + gen.return_val(jvm.jInt) gen.end_function() Modified: pypy/dist/pypy/translator/jvm/node.py ============================================================================== --- pypy/dist/pypy/translator/jvm/node.py (original) +++ pypy/dist/pypy/translator/jvm/node.py Fri Apr 4 15:10:29 2008 @@ -39,8 +39,7 @@ from pypy.translator.jvm.cmpopcodes import \ can_branch_directly, branch_if -import py -import pypy.translator.jvm.generator as jvmgen +import pypy.translator.jvm.typesystem as jvm import pypy.translator.jvm.typesystem as jvmtype from pypy.translator.jvm.log import log @@ -86,14 +85,14 @@ # XXX --- perhaps this table would be better placed in typesystem.py # so as to constrain the knowledge of lltype and ootype _type_conversion_methods = { - ootype.Signed:jvmgen.PYPYSTRTOINT, - ootype.Unsigned:jvmgen.PYPYSTRTOUINT, - lltype.SignedLongLong:jvmgen.PYPYSTRTOLONG, - lltype.UnsignedLongLong:jvmgen.PYPYSTRTOULONG, - ootype.Bool:jvmgen.PYPYSTRTOBOOL, - ootype.Float:jvmgen.PYPYSTRTODOUBLE, - ootype.Char:jvmgen.PYPYSTRTOCHAR, - ootype.UniChar:jvmgen.PYPYSTRTOCHAR, + ootype.Signed:jvm.PYPYSTRTOINT, + ootype.Unsigned:jvm.PYPYSTRTOUINT, + lltype.SignedLongLong:jvm.PYPYSTRTOLONG, + lltype.UnsignedLongLong:jvm.PYPYSTRTOULONG, + ootype.Bool:jvm.PYPYSTRTOBOOL, + ootype.Float:jvm.PYPYSTRTODOUBLE, + ootype.Char:jvm.PYPYSTRTOCHAR, + ootype.UniChar:jvm.PYPYSTRTOCHAR, ootype.String:None } @@ -109,14 +108,13 @@ # # 2. Run the initialization method for the constant class. # - gen.begin_function( - '', (), [], jVoid, static=True) - gen.emit(jvmgen.NEW, jPyPy) - gen.emit(jvmgen.DUP) + gen.begin_function('', (), [], jVoid, static=True) + gen.emit(jvm.NEW, jPyPy) + gen.emit(jvm.DUP) gen.new_with_jtype(gen.db.jInterlinkImplementation) - gen.emit(jvmgen.DUP) + gen.emit(jvm.DUP) gen.db.interlink_field.store(gen) - gen.emit(jvmgen.Method.c(jPyPy, [jPyPyInterlink])) + gen.emit(jvm.Method.c(jPyPy, [jPyPyInterlink])) gen.db.pypy_field.store(gen) gen.db.constant_generator.runtime_init(gen) gen.return_val(jVoid) @@ -143,7 +141,7 @@ conv = self._type_conversion_methods[arg.concretetype] if conv: gen.push_pypy() gen.load_jvm_var(jStringArray, 0) - gen.emit(jvmgen.ICONST, i) + gen.emit(jvm.ICONST, i) gen.load_from_array(jString) if conv: gen.emit(conv) else: @@ -151,9 +149,9 @@ # python method expects arg0 = self.graph.getargs()[0] assert isinstance(arg0.concretetype, ootype.List), str(arg0.concretetype) - assert arg0.concretetype._ITEMTYPE is ootype.String + assert arg0.concretetype.ITEM is ootype.String gen.load_jvm_var(jStringArray, 0) - gen.emit(jvmgen.PYPYARRAYTOLIST) + gen.emit(jvm.PYPYARRAYTOLIST) # Generate a call to this method gen.emit(self.db.pending_function(self.graph)) @@ -171,13 +169,13 @@ gen.add_comment('Invoking dump method for result of type ' +str(RESOOTYPE)) gen.emit(dumpmethod) # generate the string - gen.emit(jvmgen.PYPYDUMP) # dump to stdout + gen.emit(jvm.PYPYDUMP) # dump to stdout gen.goto(done_printing) gen.end_try() jexc = self.db.exception_root_object() gen.begin_catch(jexc) - gen.emit(jvmgen.PYPYDUMPEXCWRAPPER) # dumps to stdout + gen.emit(jvm.PYPYDUMPEXCWRAPPER) # dumps to stdout gen.end_catch() gen.mark(done_printing) @@ -198,12 +196,12 @@ name = None def render(self, gen): - """ Uses the gen argument, a jvmgen.Generator, to create the + """ Uses the gen argument, a jvm.Generator, to create the appropriate JVM assembly for this method. """ raise NotImplementedError def method(self): - """ Returns a jvmgen.Method object that would allow this + """ Returns a jvm.Method object that would allow this function to be invoked. """ raise NotImplementedError @@ -272,12 +270,12 @@ return self.generator.unique_label(prefix) def method(self): - """ Returns a jvmgen.Method that can invoke this function """ + """ Returns a jvm.Method that can invoke this function """ if not self.is_method: - ctor = jvmgen.Method.s + ctor = jvm.Method.s startidx = 0 else: - ctor = jvmgen.Method.v + ctor = jvm.Method.v startidx = 1 return ctor(self.classty, self.name, self.jargtypes[startidx:], self.jrettype) @@ -359,11 +357,11 @@ # exception to be caught by the normal handlers. self.ilasm.begin_catch(jexcty) self.ilasm.push_interlink() - interlink_method = jvmgen.Method.v( + interlink_method = jvm.Method.v( jPyPyInterlink, "throw"+pyexccls.__name__, [], jVoid) self.ilasm.emit(interlink_method) - self.ilasm.emit(jvmgen.ACONST_NULL) - self.ilasm.emit(jvmgen.ATHROW) + self.ilasm.emit(jvm.ACONST_NULL) # "inform" the verifier... + self.ilasm.emit(jvm.ATHROW) # ...that we throw here self.ilasm.end_try() def begin_catch(self, llexitcase): @@ -386,7 +384,7 @@ else: # the exception value is on the stack, store it in the proper place if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.emit(jvmgen.DUP) + self.ilasm.emit(jvm.DUP) self.ilasm.store(link.last_exc_value) fld = self.db.lltype_to_cts(rclass.OBJECT).lookup_field('meta') self.ilasm.emit(fld) @@ -517,9 +515,9 @@ def _trace(self, str, writeline=False): if writeline: str += '\n' - jvmgen.SYSTEMERR.load(self.generator) + jvm.SYSTEMERR.load(self.generator) self.generator.load_string(str) - jvmgen.PRINTSTREAMPRINTSTR.invoke(self.generator) + jvm.PRINTSTREAMPRINTSTR.invoke(self.generator) def _is_printable(self, res): @@ -554,10 +552,10 @@ res.concretetype) self._trace(" "+prompt+": ") - self.generator.emit(jvmgen.SYSTEMERR) + self.generator.emit(jvm.SYSTEMERR) self.generator.load(res) self.generator.emit(jmethod) - self.generator.emit(jvmgen.PRINTSTREAMPRINTSTR) + self.generator.emit(jvm.PRINTSTREAMPRINTSTR) self._trace("\n") def _trace_enabled(self): @@ -596,7 +594,7 @@ self.java_return_type = jrettype self.dump_method = ConstantStringDumpMethod( self, "StaticMethodInterface") - self.invoke_method_obj = jvmgen.Method.v( + self.invoke_method_obj = jvm.Method.v( self, 'invoke', self.java_argument_types[1:], self.java_return_type) @@ -604,7 +602,7 @@ raise KeyError(fieldnm) # no fields def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + """ Given the method name, returns a jvm.Method object """ assert isinstance(self.java_return_type, JvmType) if methodnm == 'invoke': return self.invoke_method_obj @@ -698,9 +696,9 @@ if bound_to_jty: self.bound_to_jty = bound_to_jty - self.bound_to_fld = jvmgen.Field( + self.bound_to_fld = jvm.Field( self.name, 'bound_to', bound_to_jty, False) - self.bind_method = jvmgen.Method.s( + self.bind_method = jvm.Method.s( self, 'bind', (self.bound_to_jty,), self) else: self.bound_to_jty = None @@ -731,7 +729,7 @@ gen.begin_function( 'bind', [], (self.bound_to_jty,), self, static=True) gen.new_with_jtype(self) - gen.emit(jvmgen.DUP) + gen.emit(jvm.DUP) gen.load_jvm_var(self.bound_to_jty, 0) self.bound_to_fld.store(gen) gen.return_val(self) @@ -810,10 +808,10 @@ """ JvmGeneratedClassType.__init__(self, name) self.rendered = False # has rendering occurred? - self.fields = {} # maps field name to jvmgen.Field object + self.fields = {} # maps field name to jvm.Field object self.interfaces = [] # list of JvmTypes self.methods = {} # maps method name to a Function object* - self.abstract_methods = {} # maps method name to jvmgen.Method object + self.abstract_methods = {} # maps method name to jvm.Method object self.set_super_class(supercls) # * --- actually maps to an object that defines the @@ -833,9 +831,9 @@ self.throwable = True def add_field(self, fieldobj, fielddef): - """ Creates a new field accessed via the jvmgen.Field + """ Creates a new field accessed via the jvm.Field descriptor 'fieldobj'. Must be called before render().""" - assert not self.rendered and isinstance(fieldobj, jvmgen.Field) + assert not self.rendered and isinstance(fieldobj, jvm.Field) self.fields[fieldobj.field_name] = (fieldobj, fielddef) def add_interface(self, inter): @@ -848,7 +846,7 @@ return self.super_class.lookup_field(fieldnm) def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + """ Given the method name, returns a jvm.Method object """ if methodnm in self.methods: return self.methods[methodnm].method() if methodnm in self.abstract_methods: @@ -864,7 +862,7 @@ def add_abstract_method(self, jmethod): """ Adds an abstract method to our list of methods; jmethod should - be a jvmgen.Method object """ + be a jvm.Method object """ assert jmethod.method_name not in self.methods self.abstract_methods[jmethod.method_name] = jmethod @@ -912,7 +910,7 @@ """ interlink: the JvmType of the Interlink implementation name: the name of the method - helper: a jvmgen.Method object for the helper func we should invoke + helper: a jvm.Method object for the helper func we should invoke """ self.interlink = interlink self.name = name @@ -926,7 +924,7 @@ else: self.return_type = self.helper.return_type - self.method_obj = jvmgen.Method.v(interlink, + self.method_obj = jvm.Method.v(interlink, self.name, self.helper.argument_types, self.return_type) Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Fri Apr 4 15:10:29 2008 @@ -6,7 +6,7 @@ """ from pypy.translator.oosupport.metavm import \ - PushArg, PushAllArgs, StoreResult, InstructionList, New, DoNothing, Call,\ + PushArg, PushAllArgs, StoreResult, InstructionList, New, OONewArray, DoNothing, Call,\ SetField, GetField, DownCast, RuntimeNew, OOString, OOUnicode, \ CastTo, PushPrimitive from pypy.translator.jvm.metavm import \ @@ -15,19 +15,18 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.cmpopcodes import cmp_opname -import pypy.translator.jvm.generator as jvmgen -import pypy.translator.jvm.typesystem as jvmtype +import pypy.translator.jvm.typesystem as jvm def _proc(val): if isinstance(val, list): # Lists of instructions we leave alone: return InstructionList(val) - elif isinstance(val, jvmgen.Method) and not val.is_static(): + elif isinstance(val, jvm.Method) and not val.is_static(): # For virtual methods, we first push an instance of the relevant # class, then the arguments, and then invoke the method. Note # that we only allow virtual methods of certain pre-designated # classes to be in the table. - if val.class_name == jvmtype.jPyPy.name: + if val.class_name == jvm.jPyPy.name: return InstructionList( (PushPyPy, PushAllArgs, val, StoreResult)) else: @@ -71,6 +70,7 @@ opcodes = _proc_dict({ # __________ object oriented operations __________ 'new': [New, StoreResult], + 'oonewarray': [OONewArray, StoreResult], 'runtimenew': [RuntimeNew, StoreResult], 'oosetfield': [SetField], 'oogetfield': [GetField, StoreResult], @@ -78,19 +78,19 @@ 'ooupcast': DoNothing, 'oodowncast': [DownCast, StoreResult], 'instanceof': [CastTo, StoreResult], - 'subclassof': [PushAllArgs, jvmgen.SWAP, jvmgen.CLASSISASSIGNABLEFROM, StoreResult], - 'ooidentityhash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], - 'oohash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], + 'subclassof': [PushAllArgs, jvm.SWAP, jvm.CLASSISASSIGNABLEFROM, StoreResult], + 'ooidentityhash': [PushAllArgs, jvm.OBJHASHCODE, StoreResult], + 'oohash': [PushAllArgs, jvm.OBJHASHCODE, StoreResult], 'oostring': [OOString, StoreResult], 'oounicode': [OOUnicode, StoreResult], - 'ooparse_float': jvmgen.PYPYOOPARSEFLOAT, + 'ooparse_float': jvm.PYPYOOPARSEFLOAT, 'oonewcustomdict': [NewCustomDict, StoreResult], 'same_as': DoNothing, 'hint': [PushArg(0), StoreResult], 'direct_call': [Call, StoreResult], 'indirect_call': [PushAllArgs, IndirectCall, StoreResult], - 'gc__collect': jvmgen.SYSTEMGC, + 'gc__collect': jvm.SYSTEMGC, 'gc_set_max_heap_size': Ignore, 'resume_point': Ignore, @@ -100,100 +100,100 @@ 'bool_not': 'logical_not', - 'int_neg': jvmgen.INEG, - 'int_neg_ovf': jvmgen.INEGOVF, + 'int_neg': jvm.INEG, + 'int_neg_ovf': jvm.INEGOVF, 'int_abs': 'iabs', - 'int_abs_ovf': jvmgen.IABSOVF, + 'int_abs_ovf': jvm.IABSOVF, 'int_invert': 'bitwise_negate', - 'int_add': jvmgen.IADD, - 'int_sub': jvmgen.ISUB, - 'int_mul': jvmgen.IMUL, - 'int_floordiv': jvmgen.IDIV, - 'int_floordiv_zer': _check_zer(jvmgen.IDIV), - 'int_mod': jvmgen.IREM, - 'int_and': jvmgen.IAND, - 'int_or': jvmgen.IOR, - 'int_lshift': jvmgen.ISHL, - 'int_rshift': jvmgen.ISHR, - 'int_xor': jvmgen.IXOR, - 'int_add_ovf': jvmgen.IADDOVF, - 'int_add_nonneg_ovf': jvmgen.IADDOVF, - 'int_sub_ovf': jvmgen.ISUBOVF, - 'int_mul_ovf': jvmgen.IMULOVF, - 'int_floordiv_ovf': jvmgen.IDIV, # these can't overflow! - 'int_mod_zer': _check_zer(jvmgen.IREM), - 'int_mod_ovf': jvmgen.IREMOVF, - 'int_and_ovf': jvmgen.IAND, - 'int_or_ovf': jvmgen.IOR, - - 'int_lshift_ovf': jvmgen.ISHLOVF, - 'int_lshift_ovf_val': jvmgen.ISHLOVF, # VAL... what is val used for?? - - 'int_rshift_ovf': jvmgen.ISHR, # these can't overflow! - 'int_xor_ovf': jvmgen.IXOR, - 'int_floordiv_ovf_zer': _check_zer(jvmgen.IDIV), - 'int_mod_ovf_zer': _check_zer(jvmgen.IREMOVF), + 'int_add': jvm.IADD, + 'int_sub': jvm.ISUB, + 'int_mul': jvm.IMUL, + 'int_floordiv': jvm.IDIV, + 'int_floordiv_zer': _check_zer(jvm.IDIV), + 'int_mod': jvm.IREM, + 'int_and': jvm.IAND, + 'int_or': jvm.IOR, + 'int_lshift': jvm.ISHL, + 'int_rshift': jvm.ISHR, + 'int_xor': jvm.IXOR, + 'int_add_ovf': jvm.IADDOVF, + 'int_add_nonneg_ovf': jvm.IADDOVF, + 'int_sub_ovf': jvm.ISUBOVF, + 'int_mul_ovf': jvm.IMULOVF, + 'int_floordiv_ovf': jvm.IDIV, # these can't overflow! + 'int_mod_zer': _check_zer(jvm.IREM), + 'int_mod_ovf': jvm.IREMOVF, + 'int_and_ovf': jvm.IAND, + 'int_or_ovf': jvm.IOR, + + 'int_lshift_ovf': jvm.ISHLOVF, + 'int_lshift_ovf_val': jvm.ISHLOVF, # VAL... what is val used for?? + + 'int_rshift_ovf': jvm.ISHR, # these can't overflow! + 'int_xor_ovf': jvm.IXOR, + 'int_floordiv_ovf_zer': _check_zer(jvm.IDIV), + 'int_mod_ovf_zer': _check_zer(jvm.IREMOVF), 'uint_invert': 'bitwise_negate', - 'uint_add': jvmgen.IADD, - 'uint_sub': jvmgen.ISUB, - 'uint_mul': jvmgen.PYPYUINTMUL, - 'uint_div': jvmgen.PYPYUINTDIV, + 'uint_add': jvm.IADD, + 'uint_sub': jvm.ISUB, + 'uint_mul': jvm.PYPYUINTMUL, + 'uint_div': jvm.PYPYUINTDIV, 'uint_truediv': None, # TODO - 'uint_floordiv': jvmgen.PYPYUINTDIV, - 'uint_mod': jvmgen.PYPYUINTMOD, - 'uint_and': jvmgen.IAND, - 'uint_or': jvmgen.IOR, - 'uint_lshift': jvmgen.ISHL, - 'uint_rshift': jvmgen.IUSHR, - 'uint_xor': jvmgen.IXOR, + 'uint_floordiv': jvm.PYPYUINTDIV, + 'uint_mod': jvm.PYPYUINTMOD, + 'uint_and': jvm.IAND, + 'uint_or': jvm.IOR, + 'uint_lshift': jvm.ISHL, + 'uint_rshift': jvm.IUSHR, + 'uint_xor': jvm.IXOR, - 'float_neg': jvmgen.DNEG, + 'float_neg': jvm.DNEG, 'float_abs': 'dbl_abs', - 'float_add': jvmgen.DADD, - 'float_sub': jvmgen.DSUB, - 'float_mul': jvmgen.DMUL, - 'float_truediv': jvmgen.DDIV, - - 'llong_neg': jvmgen.LNEG, - 'llong_neg_ovf': jvmgen.LNEGOVF, - 'llong_abs': jvmgen.MATHLABS, - 'llong_abs_ovf': jvmgen.LABSOVF, - 'llong_invert': jvmgen.PYPYLONGBITWISENEGATE, - - 'llong_add': jvmgen.LADD, - 'llong_sub': jvmgen.LSUB, - 'llong_mul': jvmgen.LMUL, - 'llong_div': jvmgen.LDIV, + 'float_add': jvm.DADD, + 'float_sub': jvm.DSUB, + 'float_mul': jvm.DMUL, + 'float_truediv': jvm.DDIV, + + 'llong_neg': jvm.LNEG, + 'llong_neg_ovf': jvm.LNEGOVF, + 'llong_abs': jvm.MATHLABS, + 'llong_abs_ovf': jvm.LABSOVF, + 'llong_invert': jvm.PYPYLONGBITWISENEGATE, + + 'llong_add': jvm.LADD, + 'llong_sub': jvm.LSUB, + 'llong_mul': jvm.LMUL, + 'llong_div': jvm.LDIV, 'llong_truediv': None, # TODO - 'llong_floordiv': jvmgen.LDIV, - 'llong_floordiv_zer': _check_zer(jvmgen.LDIV), - 'llong_mod': jvmgen.LREM, - 'llong_mod_zer': _check_zer(jvmgen.LREM), - 'llong_and': jvmgen.LAND, - 'llong_or': jvmgen.LOR, - 'llong_lshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult], # XXX - do we care about shifts of >(1<<32) bits?? - 'llong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHR, StoreResult], - 'llong_xor': jvmgen.LXOR, - 'llong_floordiv_ovf': jvmgen.LDIV, # these can't overflow! - 'llong_mod_ovf': jvmgen.LREMOVF, - 'llong_lshift_ovf': jvmgen.LSHLOVF, - - 'ullong_invert': jvmgen.PYPYLONGBITWISENEGATE, - - 'ullong_add': jvmgen.LADD, - 'ullong_sub': jvmgen.LSUB, - 'ullong_mul': jvmgen.LMUL, - 'ullong_div': jvmgen.LDIV, # valid? + 'llong_floordiv': jvm.LDIV, + 'llong_floordiv_zer': _check_zer(jvm.LDIV), + 'llong_mod': jvm.LREM, + 'llong_mod_zer': _check_zer(jvm.LREM), + 'llong_and': jvm.LAND, + 'llong_or': jvm.LOR, + 'llong_lshift': [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult], + 'llong_rshift': [PushAllArgs, jvm.L2I, jvm.LSHR, StoreResult], + 'llong_xor': jvm.LXOR, + 'llong_floordiv_ovf': jvm.LDIV, # these can't overflow! + 'llong_mod_ovf': jvm.LREMOVF, + 'llong_lshift_ovf': jvm.LSHLOVF, + + 'ullong_invert': jvm.PYPYLONGBITWISENEGATE, + + 'ullong_add': jvm.LADD, + 'ullong_sub': jvm.LSUB, + 'ullong_mul': jvm.LMUL, + 'ullong_div': jvm.LDIV, # valid? 'ullong_truediv': None, # TODO - 'ullong_floordiv': jvmgen.LDIV, # valid? - 'ullong_mod': jvmgen.PYPYULONGMOD, - 'ullong_lshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult], - 'ullong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LUSHR, StoreResult], - 'ullong_mod_zer': jvmgen.PYPYULONGMOD, + 'ullong_floordiv': jvm.LDIV, # valid? + 'ullong_mod': jvm.PYPYULONGMOD, + 'ullong_lshift': [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult], + 'ullong_rshift': [PushAllArgs, jvm.L2I, jvm.LUSHR, StoreResult], + 'ullong_mod_zer': jvm.PYPYULONGMOD, # when casting from bool we want that every truth value is casted # to 1: we can't simply DoNothing, because the CLI stack could @@ -201,21 +201,21 @@ # trick. #THIS COMMENT NEEDS TO BE VALIDATED AND UPDATED 'cast_bool_to_int': DoNothing, 'cast_bool_to_uint': DoNothing, - 'cast_bool_to_float': jvmgen.PYPYBOOLTODOUBLE, #PAUL, inefficient + 'cast_bool_to_float': jvm.PYPYBOOLTODOUBLE, #PAUL, inefficient 'cast_char_to_int': DoNothing, 'cast_unichar_to_int': DoNothing, 'cast_int_to_char': DoNothing, 'cast_int_to_unichar': DoNothing, 'cast_int_to_uint': DoNothing, - 'cast_int_to_float': jvmgen.I2D, - 'cast_int_to_longlong': jvmgen.I2L, + 'cast_int_to_float': jvm.I2D, + 'cast_int_to_longlong': jvm.I2L, 'cast_uint_to_int': DoNothing, - 'cast_uint_to_float': jvmgen.PYPYUINTTODOUBLE, - 'cast_float_to_int': jvmgen.D2I, - 'cast_float_to_longlong': jvmgen.PYPYDOUBLETOLONG, #PAUL - 'cast_float_to_uint': jvmgen.PYPYDOUBLETOUINT, - 'truncate_longlong_to_int': jvmgen.L2I, - 'cast_longlong_to_float': jvmgen.L2D, + 'cast_uint_to_float': jvm.PYPYUINTTODOUBLE, + 'cast_float_to_int': jvm.D2I, + 'cast_float_to_longlong': jvm.PYPYDOUBLETOLONG, #PAUL + 'cast_float_to_uint': jvm.PYPYDOUBLETOUINT, + 'truncate_longlong_to_int': jvm.L2I, + 'cast_longlong_to_float': jvm.L2D, 'cast_primitive': [PushAllArgs, CastPrimitive, StoreResult], 'is_early_constant': [PushPrimitive(ootype.Bool, False), StoreResult] Modified: pypy/dist/pypy/translator/jvm/prebuiltnodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/prebuiltnodes.py (original) +++ pypy/dist/pypy/translator/jvm/prebuiltnodes.py Fri Apr 4 15:10:29 2008 @@ -57,7 +57,7 @@ def create_interlink_node(db): """ Translates the create_interlink_impl() function and returns - a jvmgen.Method object that allows it to be called. """ + a jvm.Method object that allows it to be called. """ translator = db.genoo.translator for func, type_list in HELPERS.items(): Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java ============================================================================== --- pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java (original) +++ pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java Fri Apr 4 15:10:29 2008 @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Map; import java.text.DecimalFormat; +import java.lang.reflect.Array; /** * Class with a number of utility routines. One instance of this is @@ -407,7 +408,16 @@ sb.append("]"); return sb.toString(); } - else if (o instanceof String) { + if (o.getClass().isArray()) { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < Array.getLength(o); i++) { + sb.append(serializeObject(Array.get(o, i))).append(","); + } + sb.append("]"); + return sb.toString(); + } + if (o instanceof String) { return escaped_string((String)o); } return o.toString(); @@ -731,7 +741,7 @@ return str.substring(start, end); } - public static ArrayList ll_split_chr(String str, char c) { + public static Object[] ll_split_chr(String str, char c) { ArrayList list = new ArrayList(); int lastidx = 0, idx = 0; while ((idx = str.indexOf(c, lastidx)) != -1) @@ -741,7 +751,7 @@ lastidx = idx+1; } list.add(str.substring(lastidx)); - return list; + return list.toArray(new String[list.size()]); } public static String ll_substring(String str, int start, int cnt) { Modified: pypy/dist/pypy/translator/jvm/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_class.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_class.py Fri Apr 4 15:10:29 2008 @@ -24,7 +24,8 @@ assert self.interpret(fn, [2]) == 42 - + def test_specialize_methods(self): + py.test.skip('ABSTRACT METHOD FIX: RE-TEST AFTER MERGE') class TestJvmSpecialCase(JvmTest, BaseTestSpecialcase): pass Modified: pypy/dist/pypy/translator/jvm/test/test_list.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_list.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_list.py Fri Apr 4 15:10:29 2008 @@ -15,4 +15,17 @@ return lst[0] res = self.interpret(fn, []) assert res == 0 + + def test_bool_fixed_list(self): + """ Tests that we handle boolean fixed lists, which do not require + boxing or unboxing """ + def fn(i): + lst = [False, True] + if lst[i]: + return 22 + else: + return 44 + for i in range(0,2): + res = self.interpret(fn, [i]) + assert res == fn(i) Modified: pypy/dist/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/dist/pypy/translator/jvm/typesystem.py (original) +++ pypy/dist/pypy/translator/jvm/typesystem.py Fri Apr 4 15:10:29 2008 @@ -1,33 +1,28 @@ """ -Definition and some basic translations between PyPy ootypesystem and -JVM type system. - -Here are some tentative non-obvious decisions: - -Signed scalar types mostly map as is. - -Unsigned scalar types are a problem; the basic idea is to store them -as signed values, but execute special code when working with them. Another -option would be to use classes, or to use the "next larger" type and remember to use appropriate modulos. The jury is out on -this. Another idea would be to add a variant type system that does -not have unsigned values, and write the required helper and conversion -methods in RPython --- then it could be used for multiple backends. - -Python strings are mapped to byte arrays, not Java Strings, since -Python strings are really sets of bytes, not unicode code points. -Jury is out on this as well; this is not the approach taken by cli, -for example. - -Python Unicode strings, on the other hand, map directly to Java Strings. - -WeakRefs are mapped to a thin wrapper class, PyPyWeakRef, to allow for -mutation of the object being referenced (the ll_set method). - -Collections can hopefully map to Java collections instances. Note -that JVM does not have an idea of generic typing at its lowest level -(well, they do have signature attributes, but those don't really count -for much). +Defines the basic structures which are used to represent JVM abstraction, +such as Java types, fields, methods and opcodes. +The structures in this file generally two different, but related, +roles. First, they describe a JVM abstraction. For example, jObject +describes some of the properties of the built-in class +java.lang.Object. Second, they can represent the concrete realization +of an OOTYPE construct. For example, JvmType instances are used to +represent the translated class which will be generated for some OOTYPE +class. + +This file itself is intended to be imported from a wide variety of +locations, and thus generally restricts itself to classes and global +variables that describe intrinsic parts of the JVM. For example, +there are objects representing different opcodes, type definitions for +built-in types like java.lang.Object and java.lang.System, and +method/field declarations for well-known methods and fields on those +types. + +Other files extend this set with objects that represent the JVM +realization of some OOTYPE construct. For example, the module +builtin.py describes the JVM types that are used to define the +built-in OOTYPE types, such as lists or dictionaries. The module +node.py contains code for representing user-defined classes. """ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype @@ -69,8 +64,11 @@ def int_class_name(self): """ Converts a descriptor like Ljava/lang/Object; to internal class name java/lang/Object """ - assert self[0] == 'L' and self[-1] == ';' - return self[1:-1] + if self[0] == 'L' and self[-1] == ';': + return self[1:-1] + else: + assert self.startswith('[') + return self def type_width(self): """ Returns number of JVM words this type takes up. JVM words are a theoretically abstract quantity that basically @@ -102,6 +100,13 @@ # ______________________________________________________________________ # Basic JVM Types +# +# As described above, some of these define well-known types in the JVM +# or standard Java library. In addition, there are subtypes of +# JvmType which represent the translated version of some RPython +# class, such as a list, dictionary, or user-defined class. Those +# subtypes are generally defined in other modules, as they have +# dependencies that would cause circular imports. class JvmType(object): """ @@ -116,15 +121,23 @@ # (None for scalars and arrays) def lookup_field(self, fieldnm): - """ If the class has a field named 'fieldnm', returns a - jvmgen.Field or jvmgen.Property object that represents it and can - be used with the interpreter to load/store it. If no such field - exists, or this is not a class, then raises KeyError. """ + """ Returns a Field or Property object that represents the + field named 'fieldnm', or raises KeyError if no such field + exists. 'fieldnm' generally represents an OOTYPE field, and + thus this method is generally not implemenented by the JvmType + classes that just represent native Java classes, even if they + have fields. Instead, such fields are described as global + Field constants, either in this file or elsewhere. """ raise NotImplementedException + def lookup_method(self, methodnm): - """ Returns a jvm.generator.Method object representing the method - with the given name, or raises KeyError if that field does not - exist on this type. """ + """ Returns a BaseMethod object that represents the method + named 'methodnm', or raises KeyError if no such field exists. + 'methodnm' represents an OOTYPE method, and thus this method + is generally not implemenented by the JvmType classes that + just represent native Java classes, even if they have methods. + Instead, such methods are described as global Method constants + in this file, either in this file or elsewhere. """ raise NotImplementedException def is_generated(self): @@ -226,22 +239,6 @@ jByte = JvmScalarType('B', jByteClass, 'byteValue') jChar = JvmScalarType('C', jCharClass, 'charValue') -class JvmArrayType(JvmType): - """ - Subclass used for all array instances. - """ - def __init__(self, elemtype): - JvmType.__init__(self, desc_for_array_of(elemtype.descriptor)) - self.element_type = elemtype - def lookup_field(self, fieldnm): - raise KeyError(fieldnm) # TODO adjust interface to permit opcode here - def lookup_method(self, methodnm): - raise KeyError(methodnm) # Arrays have no methods - -jByteArray = JvmArrayType(jByte) -jObjectArray = JvmArrayType(jObject) -jStringArray = JvmArrayType(jString) - class Generifier(object): """ @@ -263,7 +260,7 @@ if hasattr(self.OOTYPE, 'SELFTYPE_T'): self.generics[self.OOTYPE.SELFTYPE_T] = (self.OOTYPE,self.OOTYPE) - for pname,pval in (('ITEMTYPE_T', '_ITEMTYPE'), + for pname,pval in (('ITEMTYPE_T', 'ITEM'), ('KEYTYPE_T', '_KEYTYPE'), ('VALUETYPE_T', '_VALUETYPE')): if hasattr(self.OOTYPE, pname): @@ -301,7 +298,7 @@ # Java Callback Interfaces # # A list of interfaces which static functions that we generate will -# automatically implement if application. See the pypy/Callback.java, +# automatically implement if applicable. See the pypy/Callback.java, # node.py/StaticMethodInterface for more information. jCallbackInterfaces = [] # collects all of the defined JvmCallbackInterfaces @@ -351,10 +348,630 @@ return self.methods[methname] def _add_methods(self): - from pypy.translator.jvm.generator import Method for methname, methspec in self.OOTYPE._class_._methods.items(): argtypes = [self.db.annotation_to_cts(arg._type) for arg in methspec.args] restype = self.db.annotation_to_cts(methspec.retval._type) self.methods[methname] = Method.v(self, methname, argtypes, restype) + +# ______________________________________________________________________ +# The bridge between RPython array and JVM arrays. The main differences +# are that (a) RPython has arrays of void type, and (b) RPython arrays +# have methods, whereas Java methods don't. We inline those methods +# into the appropriate bytecode. + +class _JvmVoidArray(JvmClassType): + """ + A special case for void arrays. These are represented by an instance + of the VoidArray class, which implements the required methods. + """ + + method_types = { + 'll_length': ([], jInt), + 'll_getitem_fast': ([jInt], jVoid), + 'll_setitem_fast': ([jInt], jVoid), + } + + def __init__(self): + JvmClassType.__init__(self, 'pypy.VoidArray') + + def make(self, gen): + # Construct a new VoidArray object, assuming the length has + # been pushed onto the stack already. + gen.emit(PYPYVOIDARRAYMAKE) + + def lookup_field(self, fieldnm): + raise KeyError(fieldnm) # no fields + + def lookup_method(self, methodnm): + jargtypes, jrettype = self.method_types[methodnm] + return Method.v(self, methodnm, jargtypes, jrettype) + +class JvmArrayType(JvmType): + """ + Subclass used for all array instances. + """ + def __init__(self, elemtype): + JvmType.__init__(self, desc_for_array_of(elemtype.descriptor)) + self.element_type = elemtype + def make(self, gen): + # Issues the opcode to build a new array of the appropriate type. + # Assumes the length has been pushed onto the stack already. + gen.emit(NEWARRAY.for_type(self)) + def lookup_field(self, fieldnm): + raise KeyError(fieldnm) + def lookup_method(self, methodnm): + # Arrays don't have methods in Java, but they do in the ootype system + if methodnm == "ll_length": + return OpcodeMethod([], jInt, ARRAYLENGTH) + elif methodnm == "ll_getitem_fast": + return OpcodeMethod([jInt], self.element_type, + ARRLOAD.for_type(self.element_type)) + elif methodnm == "ll_setitem_fast": + return OpcodeMethod([jInt, self.element_type], jVoid, + ARRSTORE.for_type(self.element_type)) + else: + raise KeyError(methodnm) + +jBoolArray = JvmArrayType(jBool) +jByteArray = JvmArrayType(jByte) +jObjectArray = JvmArrayType(jObject) +jStringArray = JvmArrayType(jString) +jDoubleArray = JvmArrayType(jDouble) +jCharArray = JvmArrayType(jChar) +jIntArray = JvmArrayType(jInt) +jVoidArray = _JvmVoidArray() + +# ______________________________________________________________________ +# Opcodes +# +# Objects describing the various opcodes which we use. In some cases, +# there are also opcode families, which consist of a set of related +# opcodes that are specialized by the types they operate on (i.e., +# IADD, DADD, etc). + +class Opcode(object): + def __init__(self, jvmstr): + """ + flags is a set of flags (see above) that describe opcode #UPDATE + jvmstr is the name for jasmin printouts + """ + self.jvmstr = jvmstr + self.flags = None #Should flags be added to args? + + def __repr__(self): + return "" % (self.jvmstr, self.flags) + + def specialize(self, args): + """ Process the argument list according to the various flags. + Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing + the new opcode, and ARGS is a list of arguments or empty tuple. + Most of these do not do anything. """ + return (self.jvmstr, args) + +class IntConstOpcode(Opcode): + """ The ICONST opcode specializes itself for small integer opcodes. """ + def specialize(self, args): + assert len(args) == 1 + if args[0] == -1: + return self.jvmstr + "_m1", () + elif args[0] >= 0 and args[0] <= 5: + return self.jvmstr + "_" + str(args[0]), () + # Non obvious: convert ICONST to LDC if the constant is out of + # range + return "ldc", args + +class VarOpcode(Opcode): + """ An Opcode which takes a variable index as an argument; specialized + to small integer indices. """ + def specialize(self, args): + assert len(args) == 1 + if args[0] >= 0 and args[0] <= 3: + return self.jvmstr + "_" + str(args[0]), () + return Opcode.specialize(self, args) + +class IntClassNameOpcode(Opcode): + """ An opcode which takes an internal class name as its argument; + the actual argument will be a JvmType instance. """ + def specialize(self, args): + args = [args[0].descriptor.int_class_name()] + return self.jvmstr, args + +class OpcodeFamily(object): + """ + Many opcodes in JVM have variants that depend on the type of the + operands; for example, one must choose the correct ALOAD, ILOAD, + or DLOAD depending on whether one is loading a reference, integer, + or double variable respectively. Each instance of this class + defines one 'family' of opcodes, such as the LOAD family shown + above, and produces Opcode objects specific to a particular type. + """ + def __init__(self, opcclass, suffix): + """ + opcclass is the opcode subclass to use (see above) when + instantiating a particular opcode + + jvmstr is the name for jasmin printouts + """ + self.opcode_class = opcclass + self.suffix = suffix + self.cache = {} + + def _o(self, prefix): + try: + return self.cache[prefix] + except KeyError: + self.cache[prefix] = obj = self.opcode_class( + prefix+self.suffix) + return obj + + def for_type(self, argtype): + """ Returns a customized opcode of this family appropriate to + 'argtype', a JvmType object. """ + + desc = argtype.descriptor + + # These are always true: + if desc[0] == 'L': return self._o("a") # Objects + if desc[0] == '[': return self._o("a") # Arrays + if desc == 'I': return self._o("i") # Integers + if desc == 'J': return self._o("l") # Integers + if desc == 'D': return self._o("d") # Doubles + if desc == 'V': return self._o("") # Void [used by RETURN] + + # Chars/Bytes/Booleans are normally represented as ints + # in the JVM, but some opcodes are different. They use a + # different OpcodeFamily (see ArrayOpcodeFamily for ex) + if desc == 'C': return self._o("i") # Characters + if desc == 'B': return self._o("i") # Bytes + if desc == 'Z': return self._o("i") # Boolean + + assert False, "Unknown argtype=%s" % repr(argtype) + raise NotImplementedError + +class ArrayOpcodeFamily(OpcodeFamily): + """ Opcode family specialized for array access instr """ + def for_type(self, argtype): + desc = argtype.descriptor + if desc == 'J': return self._o("l") # Integers + if desc == 'D': return self._o("d") # Doubles + if desc == 'C': return self._o("c") # Characters + if desc == 'B': return self._o("b") # Bytes + if desc == 'Z': return self._o("b") # Boolean (access as bytes) + return OpcodeFamily.for_type(self, argtype) + +class NewArrayOpcodeFamily(object): + def __init__(self): + self.cache = {} + + def for_type(self, arraytype): + try: + return self.cache[arraytype] + except KeyError: + pass + desc = arraytype.descriptor + if desc == '[I': + s = "newarray int" + elif desc == '[D': + s = "newarray double" + elif desc == '[C': + s = "newarray char" + elif desc == '[B': + s = "newarray byte" + elif desc == '[Z': + s = "newarray boolean" + else: + s = "anewarray " + arraytype.element_type.descriptor.int_class_name() + self.cache[arraytype] = obj = Opcode(s) + return obj + +NEWARRAY = NewArrayOpcodeFamily() +ARRAYLENGTH = Opcode("arraylength") + +# Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx +# variants compare a single integer arg against 0, and the IF_ICMPxx +# variants compare 2 integer arguments against each other. +for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'): + ifop = "if%s" % cmpop + if_icmpop = "if_icmp%s" % cmpop + globals()[ifop.upper()] = Opcode(ifop) + globals()[if_icmpop.upper()] = Opcode(if_icmpop) + +# Compare references, either against NULL or against each other +IFNULL = Opcode('ifnull') +IFNONNULL = Opcode('ifnonnull') +IF_ACMPEQ = Opcode('if_acmpeq') +IF_ACMPNE = Opcode('if_acmpne') + +# Method invocation +INVOKESTATIC = Opcode('invokestatic') +INVOKEVIRTUAL = Opcode('invokevirtual') +INVOKESPECIAL = Opcode('invokespecial') +INVOKEINTERFACE = Opcode('invokeinterface') + +# Other opcodes +LDC = Opcode('ldc') # single-word types +LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs +GOTO = Opcode('goto') +ICONST = IntConstOpcode('iconst') +ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly +ACONST_NULL=Opcode('aconst_null') +DCONST_0 = Opcode('dconst_0') +DCONST_1 = Opcode('dconst_1') +LCONST_0 = Opcode('lconst_0') +LCONST_1 = Opcode('lconst_1') +GETFIELD = Opcode('getfield') +PUTFIELD = Opcode('putfield') +GETSTATIC = Opcode('getstatic') +PUTSTATIC = Opcode('putstatic') +CHECKCAST = IntClassNameOpcode('checkcast') +INEG = Opcode('ineg') +IXOR = Opcode('ixor') +IADD = Opcode('iadd') +ISUB = Opcode('isub') +IMUL = Opcode('imul') +IDIV = Opcode('idiv') +IREM = Opcode('irem') +IAND = Opcode('iand') +IOR = Opcode('ior') +ISHL = Opcode('ishl') +ISHR = Opcode('ishr') +IUSHR = Opcode('iushr') +LCMP = Opcode('lcmp') +DCMPG = Opcode('dcmpg') +DCMPL = Opcode('dcmpl') +NOP = Opcode('nop') +I2D = Opcode('i2d') +I2L = Opcode('i2l') +D2I= Opcode('d2i') +#D2L= Opcode('d2l') #PAUL +L2I = Opcode('l2i') +L2D = Opcode('l2d') +ATHROW = Opcode('athrow') +DNEG = Opcode('dneg') +DADD = Opcode('dadd') +DSUB = Opcode('dsub') +DMUL = Opcode('dmul') +DDIV = Opcode('ddiv') +DREM = Opcode('drem') +LNEG = Opcode('lneg') +LADD = Opcode('ladd') +LSUB = Opcode('lsub') +LMUL = Opcode('lmul') +LDIV = Opcode('ldiv') +LREM = Opcode('lrem') +LAND = Opcode('land') +LOR = Opcode('lor') +LXOR = Opcode('lxor') +LSHL = Opcode('lshl') +LSHR = Opcode('lshr') +LUSHR = Opcode('lushr') +NEW = IntClassNameOpcode('new') +DUP = Opcode('dup') +DUP2 = Opcode('dup2') +DUP_X1 = Opcode('dup_x1') +POP = Opcode('pop') +POP2 = Opcode('pop2') +SWAP = Opcode('swap') +INSTANCEOF= IntClassNameOpcode('instanceof') +# Loading/storing local variables +LOAD = OpcodeFamily(VarOpcode, "load") +STORE = OpcodeFamily(VarOpcode, "store") +RETURN = OpcodeFamily(Opcode, "return") + +# Loading/storing from arrays +# *NOTE*: This family is characterized by the type of the ELEMENT, +# not the type of the ARRAY. +# +# Also: here I break from convention by naming the objects ARRLOAD +# rather than ALOAD, even though the suffix is 'aload'. This is to +# avoid confusion with the ALOAD opcode. +ARRLOAD = ArrayOpcodeFamily(Opcode, "aload") +ARRSTORE = ArrayOpcodeFamily(Opcode, "astore") + +# ______________________________________________________________________ +# Methods and Fields +# +# These structures are used throughout the code to refer to JVM +# methods and fields. Similarly to JvmType instances, they are used +# both to represent random fields/methods in the JVM, and to represent +# the translation of an OOTYPE field/method. Therefore, these may not +# actually generate code corresponding to a real JVM method: for +# example, arrays use a BaseMethod subclass to generate the +# appropriate JVM opcodes that correspond to RPython arrays. +# Likewise, the Property class (see below) allows us to use a pair of +# JVM methods to represent an OOTYPE field. + +class BaseMethod(object): + def __init__(self, argtypes, rettype): + self.argument_types = argtypes # List of jvmtypes + self.return_type = rettype # jvmtype + + def is_static(self): + raise NotImplementedError + + def invoke(self, gen): + raise NotImplementedError + +class OpcodeMethod(BaseMethod): + """ + Represents a "method" that is actually implemented by a single opcode, + such as ARRAYLENGTH + """ + def __init__(self, argtypes, rettype, opcode, static=False): + """ + argtypes = an array of jvm types indicating what we expect on stack + rettype = the type we will push on the stack (if any) + opcode = the opcode to emit + static = should we be considered static? if true, then we will + not push the receiver onto the stack in metavm + """ + BaseMethod.__init__(self, argtypes, rettype) + self.opcode = opcode + self.static = static + + def is_static(self): + return self.static + + def invoke(self, gen): + gen.emit(self.opcode) + +class Method(BaseMethod): + + """ + Represents a method implemented by a genuine JVM method. Unlike + OpcodeMethod, when we emit the opcode this class is an argument to + it, and contains the extra info about the class/method being + invoked that is required. + """ + + # Create a constructor: + def c(classty, argtypes): + return Method(classty.name, "", argtypes, jVoid, + opcode=INVOKESPECIAL) + c = staticmethod(c) + + # Create a virtual or interface method: + def v(classty, methnm, argtypes, rettype): + """ + Shorthand to create a virtual method. + 'class' - JvmType object for the class + 'methnm' - name of the method (Python string) + 'argtypes' - list of JvmType objects, one for each argument but + not the this ptr + 'rettype' - JvmType for return type + """ + assert argtypes is not None + assert rettype is not None + classnm = classty.name + if isinstance(classty, JvmInterfaceType): + opc = INVOKEINTERFACE + else: + assert isinstance(classty, JvmClassType) + opc = INVOKEVIRTUAL + return Method(classnm, methnm, argtypes, rettype, opcode=opc) + v = staticmethod(v) + + # Create a static method: + def s(classty, methnm, argtypes, rettype): + """ + Shorthand to create a static method. + 'class' - JvmType object for the class + 'methnm' - name of the method (Python string) + 'argtypes' - list of JvmType objects, one for each argument but + not the this ptr + 'rettype' - JvmType for return type + """ + assert isinstance(classty, JvmType) + classnm = classty.name + return Method(classnm, methnm, argtypes, rettype) + s = staticmethod(s) + + def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC): + BaseMethod.__init__(self, argtypes, rettype) + self.opcode = opcode + self.class_name = classnm # String, ie. "java.lang.Math" + self.method_name = methnm # String "abs" + + # Compute the method descriptior, which is a string like "()I": + argtypesdesc = [a.descriptor for a in argtypes] + rettypedesc = rettype.descriptor + self.descriptor = desc_for_method(argtypesdesc, rettypedesc) + def invoke(self, gen): + gen._instr(self.opcode, self) + def is_static(self): + return self.opcode == INVOKESTATIC + def jasmin_syntax(self): + res = "%s/%s%s" % (self.class_name.replace('.','/'), + self.method_name, + self.descriptor) + # A weird, inexplicable quirk of Jasmin syntax is that it requires + # the number of arguments after an invokeinterface call: + if self.opcode == INVOKEINTERFACE: + res += " %d" % (len(self.argument_types)+1,) + return res + +class Field(object): + + """ + Represents an actual JVM field. Use the methods + fld.load(gen) / gen.emit(fld) + or + fld.store(gen) + to load the field's value onto the stack, or store into the field. + If this is not a static field, you must have pushed the object + containing the field and the field's value first. + + See also Property. + """ + + @staticmethod + def i(classty, fieldnm, fieldty, OOTYPE=None): + """ + Shorthand to create an instance field. + 'class' - JvmType object for the class containing the field + 'fieldnm' - name of the field (Python string) + 'fieldty' - JvmType object for the type of the field + 'OOTYPE' - optional OOTYPE object for the type of the field + """ + return Field(classty.name, fieldnm, fieldty, False, OOTYPE) + + @staticmethod + def s(classty, fieldnm, fieldty, OOTYPE=None): + """ + Shorthand to create a static field. + 'class' - JvmType object for the class containing the field + 'fieldnm' - name of the field (Python string) + 'fieldty' - JvmType object for the type of the field + 'OOTYPE' - optional OOTYPE object for the type of the field + """ + return Field(classty.name, fieldnm, fieldty, True, OOTYPE) + + def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None): + # All fields are public + self.class_name = classnm # String, ie. "java.lang.Math" + self.field_name = fieldnm # String "someField" + self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None + self.jtype = jtype # JvmType + self.is_static = static # True or False + def load(self, gen): + if self.is_static: + gen._instr(GETSTATIC, self) + else: + gen._instr(GETFIELD, self) + def store(self, gen): + if self.is_static: + gen._instr(PUTSTATIC, self) + else: + gen._instr(PUTFIELD, self) + def jasmin_syntax(self): + return "%s/%s %s" % ( + self.class_name.replace('.','/'), + self.field_name, + self.jtype.descriptor) + +class Property(object): + """ + An object which acts like a Field, but when a value is loaded or + stored it actually invokes accessor methods. Use like a field + (prop.load(gen), prop.store(gen), etc). + """ + def __init__(self, field_name, get_method, put_method, OOTYPE=None): + self.get_method = get_method + self.put_method = put_method + self.field_name = field_name + self.OOTYPE = OOTYPE + + # Synthesize the Field attributes from the get_method/put_method: + self.class_name = get_method.class_name + assert put_method.class_name == self.class_name + self.jtype = get_method.return_type + self.is_static = get_method.is_static + def load(self, gen): + self.get_method.invoke(gen) + def store(self, gen): + self.put_method.invoke(gen) + # jasmin_syntax is not needed, since this object itself never appears + # as an argument an Opcode + +# ___________________________________________________________________________ +# Methods +# +# "Method" objects describe all the information needed to invoke a +# method. We create one for each node.Function object, as well as for +# various helper methods (defined below). To invoke a method, you +# push its arguments and then use generator.emit(methobj) where +# methobj is its Method instance. + +OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt) +OBJTOSTRING = Method.v(jObject, 'toString', (), jString) +OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool) +SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid) +INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString) +LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString) +DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString) +CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString) +MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt) +IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt) +MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong) +LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong) +MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble) +INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt) +LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong) +IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt) +LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong) +ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt) +LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong) +IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt) +LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong) +MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble) +IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt) +LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong) +IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt) +LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong) +IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt) +LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong) +ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt) +LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong) +MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble) +PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid) +CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass) +CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool) +STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append', + (jString,), jStringBuilder) +PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt) +PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt) +PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt) +PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt) +PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt) +PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong) +PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble) +PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt) +PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL +PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong) +PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt) +PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt) +PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong) +PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong) +PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool) +PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble) +PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar) +PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble) +PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid) +PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid) +PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString) +PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString) +PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString) +PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString) +PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString) +PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString) +PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString) +PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString) +PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString) +PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) +PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) +PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList) +PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble) +OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) +CLASSGETNAME = Method.v(jClass, 'getName', (), jString) +CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make', + (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict) +PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef) +PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject) +PYPYVOIDARRAYMAKE = Method.s(jVoidArray, 'make', (jInt,), jVoidArray) + +# ___________________________________________________________________________ +# Fields +# +# Field objects encode information about fields. + +SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream) +SYSTEMERR = Field.s(jSystem, 'err', jPrintStream) +DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble) +DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble) +DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble) + +PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink) +PYPYOS = Field.i(jPyPy, 'os', jll_os) + Modified: pypy/dist/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/constant.py (original) +++ pypy/dist/pypy/translator/oosupport/constant.py Fri Apr 4 15:10:29 2008 @@ -207,6 +207,8 @@ return genoo.ClassConst(self.db, value, uniq) elif isinstance(value, ootype._list): return genoo.ListConst(self.db, value, uniq) + elif isinstance(value, ootype._array): + return genoo.ArrayConst(self.db, value, uniq) elif isinstance(value, ootype._static_meth): return genoo.StaticMethodConst(self.db, value, uniq) elif isinstance(value, ootype._custom_dict): @@ -582,7 +584,7 @@ if not self.value: return for item in self.value._list: - self._record_const_if_complex(self.value._TYPE._ITEMTYPE, item) + self._record_const_if_complex(self.value._TYPE.ITEM, item) def create_pointer(self, gen): assert not self.is_null() @@ -607,16 +609,12 @@ can be overloaded by the backend if your conditions are wider. The default is not to initialize if the list is a list of Void. """ - return self.value._TYPE._ITEMTYPE is ootype.Void - try: - return self.value._list == [0] * len(self.value._list) - except: - return False + return self.value._TYPE.ITEM is ootype.Void def initialize_data(self, constgen, gen): assert not self.is_null() SELFTYPE = self.value._TYPE - ITEMTYPE = self.value._TYPE._ITEMTYPE + ITEM = self.value._TYPE.ITEM # check for special cases and avoid initialization if self._do_not_initialize(): @@ -627,11 +625,61 @@ constgen._consider_split_current_function(gen) gen.dup(SELFTYPE) push_constant(self.db, ootype.Signed, idx, gen) - push_constant(self.db, ITEMTYPE, item, gen) - gen.prepare_generic_argument(ITEMTYPE) + push_constant(self.db, ITEM, item, gen) + gen.prepare_generic_argument(ITEM) gen.call_method(SELFTYPE, 'll_setitem_fast') # ______________________________________________________________________ +# Array constants + +class ArrayConst(AbstractConst): + def __init__(self, db, list, count): + AbstractConst.__init__(self, db, list, count) + self.name = 'ARRAY__%d' % count + + def record_dependencies(self): + if not self.value: + return + for item in self.value._array: + self._record_const_if_complex(self.value._TYPE.ITEM, item) + + def create_pointer(self, gen): + from pypy.objspace.flow.model import Constant + assert not self.is_null() + SELFTYPE = self.value._TYPE + + # Create the array + length = Constant(len(self.value._array), ootype.Signed) + gen.oonewarray(SELFTYPE, length) + + def _do_not_initialize(self): + """ Returns True if the array should not be initialized; this + can be overloaded by the backend if your conditions are wider. + The default is not to initialize if the array is a array of + Void. """ + return self.value._TYPE.ITEM is ootype.Void + + def initialize_data(self, constgen, gen): + assert not self.is_null() + SELFTYPE = self.value._TYPE + ITEM = self.value._TYPE.ITEM + + # check for special cases and avoid initialization + if self._do_not_initialize(): + return + + # set each item in the list using the OOTYPE methods + for idx, item in enumerate(self.value._array): + constgen._consider_split_current_function(gen) + gen.dup(SELFTYPE) + push_constant(self.db, ootype.Signed, idx, gen) + push_constant(self.db, ITEM, item, gen) + self._setitem(SELFTYPE, gen) + + def _setitem(self, SELFTYPE, gen): + gen.call_method(SELFTYPE, 'll_setitem_fast') + +# ______________________________________________________________________ # Dictionary constants class DictConst(AbstractConst): Modified: pypy/dist/pypy/translator/oosupport/genoo.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/genoo.py (original) +++ pypy/dist/pypy/translator/oosupport/genoo.py Fri Apr 4 15:10:29 2008 @@ -22,6 +22,7 @@ RecordConst = ooconst.RecordConst ClassConst = ooconst.ClassConst ListConst = ooconst.ListConst + ArrayConst = ooconst.ArrayConst StaticMethodConst = ooconst.StaticMethodConst CustomDictConst = ooconst.CustomDictConst DictConst = ooconst.DictConst Modified: pypy/dist/pypy/translator/oosupport/metavm.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/metavm.py (original) +++ pypy/dist/pypy/translator/oosupport/metavm.py Fri Apr 4 15:10:29 2008 @@ -214,6 +214,13 @@ Stack: ... -> newobj, ... """ raise NotImplementedError + def oonewarray(self, TYPE, length): + """ Creates a new array of the given type with the given length. + + Stack: ... -> newobj, ... """ + raise NotImplementedError + + def push_null(self, TYPE): """ Push a NULL value onto the stack (the NULL value represents a pointer to an instance of OOType TYPE, if it matters to you). """ @@ -413,6 +420,14 @@ return generator.new(op.args[0].value) + +class _OONewArray(MicroInstruction): + def render(self, generator, op): + if op.args[0].value is ootype.Void: + return + generator.oonewarray(op.args[0].value, op.args[1]) + + class BranchUnconditionally(MicroInstruction): def __init__(self, label): self.label = label @@ -497,6 +512,7 @@ generator.isinstance(class_name) New = _New() +OONewArray = _OONewArray() PushAllArgs = _PushAllArgs() StoreResult = _StoreResult() From arigo at codespeak.net Fri Apr 4 15:11:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 15:11:14 +0200 (CEST) Subject: [pypy-svn] r53331 - in pypy/branch: fixed-list-ootype fixed-list-ootype-2 Message-ID: <20080404131114.EB3E016A7EE@codespeak.net> Author: arigo Date: Fri Apr 4 15:11:14 2008 New Revision: 53331 Removed: pypy/branch/fixed-list-ootype/ pypy/branch/fixed-list-ootype-2/ Log: Remove the merged branches. From arigo at codespeak.net Fri Apr 4 16:09:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 16:09:02 +0200 (CEST) Subject: [pypy-svn] r53332 - in pypy/dist/pypy: annotation rpython/module rpython/test Message-ID: <20080404140902.112F816A7E6@codespeak.net> Author: arigo Date: Fri Apr 4 16:09:00 2008 New Revision: 53332 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/rpython/module/support.py pypy/dist/pypy/rpython/test/test_rstr.py Log: (antocuni, niko, arigo, (cfbolz you've been spotted lurking)) Support for prebuilt ootype._string constants in the annotator. Support for null string in string_to_ll(). Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Apr 4 16:09:00 2008 @@ -415,7 +415,7 @@ result = SomeOOClass(x._INSTANCE) # NB. can be None elif isinstance(x, ootype.instance_impl): # XXX result = SomeOOInstance(ootype.typeOf(x)) - elif isinstance(x, ootype._record): + elif isinstance(x, (ootype._record, ootype._string)): result = SomeOOInstance(ootype.typeOf(x)) elif callable(x): if hasattr(x, '__self__') and x.__self__ is not None: Modified: pypy/dist/pypy/rpython/module/support.py ============================================================================== --- pypy/dist/pypy/rpython/module/support.py (original) +++ pypy/dist/pypy/rpython/module/support.py Fri Apr 4 16:09:00 2008 @@ -54,6 +54,8 @@ _mixin_ = True def to_rstr(s): + if s is None: + return ootype.null(ootype.String) return ootype.oostring(s, -1) to_rstr = staticmethod(to_rstr) 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 Fri Apr 4 16:09:00 2008 @@ -806,6 +806,20 @@ res = self.interpret(f, [self.string_to_ll(const("abba"))]) assert res + def test_prebuilt_ll_strings(self): + llstr0 = self.string_to_ll(None) + assert not llstr0 + llstr1 = self.string_to_ll("hello") + def f(i): + if i == 0: + return llstr0 + else: + return llstr1 + res = self.interpret(f, [0]) + assert res == self.string_to_ll(None) + res = self.interpret(f, [1]) + assert self.ll_to_string(res) == "hello" + def FIXME_test_str_to_pystringobj(): def f(n): if n >= 0: From cami at codespeak.net Fri Apr 4 17:16:02 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 4 Apr 2008 17:16:02 +0200 (CEST) Subject: [pypy-svn] r53333 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080404151602.9DAC816A80D@codespeak.net> Author: cami Date: Fri Apr 4 17:15:59 2008 New Revision: 53333 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Log: added flag booleans added flag register updated test Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Fri Apr 4 17:15:59 2008 @@ -99,6 +99,75 @@ if not useCycles: self.cpu.cycles += 1 return self.cpu.read(self.hl.get(useCycles)) + +class FlagRegister(Register): + + def __init__(self, cpu): + self.cpu = cpu + self.reset() + + def reset(self, keepZ=False, keepN=False, keepH=False, keepC=False,\ + keepP=False, keepS=False): + if not keepZ: + self.zFlag = True + if not keepN: + self.nFlag = False + if not keepH: + self.hFlag = False + if not keepC: + self.cFlag = False + if not keepP: + self.pFlag = False + if not keepS: + self.sFlag = False + self.lower = 0x00 + + def get(self, useCycles=True): + value = 0 + value += (int(self.cFlag) << 4) + value += (int(self.hFlag) << 5) + value += (int(self.nFlag) << 6) + value += (int(self.zFlag) << 7) + return value + self.lower + + def set(self, value, useCycles=True): + self.cFlag = bool(value & (1 << 4)) + self.hFlag = bool(value & (1 << 5)) + self.nFlag = bool(value & (1 << 6)) + self.zFlag = bool(value & (1 << 7)) + self.lower = value & 0x0F + if useCycles: + self.cpu.cycles -= 1 + + def zeroFlagAdd(self, a, reset=False): + if (reset): + self.reset() + if isinstance(a, (Register)): + a = a.get() + self.zFlag = (a==0) + + def cFlagAdd(self, s, compareAnd=0x01, reset=False): + if (reset): + self.reset() + if (s & compareAnd) != 0: + self.cFlag = True + + def hFlagCompare(self, a, b): + if isinstance(a, (Register)): + a = a.get() + if isinstance(b, (Register)): + b = b.get() + if (a & 0x0F) < (b & 0x0F): + self.hFlag = True + + def cFlagCompare(self, a, b): + if isinstance(a, (Register)): + a = a.get() + if isinstance(b, (Register)): + b = b.get() + if a < b: + self.cFlag = True + # ___________________________________________________________________________ class CPU(object): @@ -131,12 +200,19 @@ self.sp = DoubleRegister(self, constants.RESET_SP) self.a = Register(self, constants.RESET_A) - self.f = Register(self, constants.RESET_F) + self.f = FlagRegister(self) self.af = DoubleRegister(self, self.a, self.f) self.reset() def reset(self): + self.resetRegisters() + self.f.reset() + self.ime = False + self.halted = False + self.cycles = 0 + + def resetRegisters(self): self.a.reset(); self.f.reset(); self.bc.reset(); @@ -144,9 +220,6 @@ self.hl.reset(); self.sp.reset(); self.pc.reset(); - self.ime = False - self.halted = False - self.cycles = 0 def getAF(self): return self.af @@ -198,25 +271,50 @@ val += 0x80 return val - # Flags ............................................ + + def isZ(self): + """ zero flag""" + return self.f.zFlag + + def isC(self): + """ carry flag, true if the result did not fit in the register""" + return self.f.cFlag + + def isH(self): + """ half carry, carry from bit 3 to 4""" + return self.f.hFlag + + def isN(self): + """ subtract flag, true if the last operation was a subtraction""" + return self.f.nFlag + + def isS(self): + return self.f.sFlag + + def isP(self): + return self.f.pFlag + + def isNotZ(self): + return not self.isZ() + + def isNotC(self): + return not self.isC() + + def isNotH(self): + return not self.isH() + + def isNotN(self): + return not self.isN() + + + # Flags ............................................ def setROM(self, banks): self.rom = banks - def zeroFlagAdd(self, s, resetF=False): - if (resetF): - self.f.set(0, False) - if s == 0: - self.f.add(constants.Z_FLAG, False) - def cFlagAdd(self, s, compareAnd=0x01, resetF=False): - if (resetF): - self.f.set(0, False) - if (s & compareAnd) != 0: - self.f.add(constants.C_FLAG, False) - def emulate(self, ticks): self.cycles += ticks self.interrupt() @@ -229,29 +327,32 @@ self.ime = False self.call(address) return - if (self.halted): + if self.halted: if (self.interrupt.isPending()): self.halted = False # Zerd no Densetsu self.cycles -= 4 elif (self.cycles > 0): self.cycles = 0 - if (self.ime and self.interrupt.isPending()): - if (self.interrupt.isPending(constants.VBLANK)): - self.interrupt(0x40) - self.interrupt.lower(constants.VBLANK) - elif (self.interrupt.isPending(constants.LCD)): - self.interrupt(0x48) - self.interrupt.lower(constants.LCD) - elif (self.interrupt.isPending(constants.TIMER)): - self.interrupt(0x50) - self.interrupt.lower(constants.TIMER) - elif (self.interrupt.isPending(constants.SERIAL)): - self.interrupt(0x58) - self.interrupt.lower(constants.SERIAL) - elif (self.interrupt.isPending(constants.JOYPAD)): - self.interrupt(0x60) - self.interrupt.lower(constants.JOYPAD) + if self.ime and self.interrupt.isPending(): + self.lowerPendingInterrupt() + + def lowerPendingInterrupt(self): + if (self.interrupt.isPending(constants.VBLANK)): + self.interrupt(0x40) + self.interrupt.lower(constants.VBLANK) + elif (self.interrupt.isPending(constants.LCD)): + self.interrupt(0x48) + self.interrupt.lower(constants.LCD) + elif (self.interrupt.isPending(constants.TIMER)): + self.interrupt(0x50) + self.interrupt.lower(constants.TIMER) + elif (self.interrupt.isPending(constants.SERIAL)): + self.interrupt(0x58) + self.interrupt.lower(constants.SERIAL) + elif (self.interrupt.isPending(constants.JOYPAD)): + self.interrupt(0x60) + self.interrupt.lower(constants.JOYPAD) # Execution def fetchExecute(self): @@ -336,46 +437,46 @@ # ALU, 1 cycle def addA(self, getter, setter=None): - data = getter() - s = (self.a.get() + data) & 0xFF - self.zeroFlagAdd(s, resetF=True) - if s < self.a.get(): - self.f.add(constants.C_FLAG, False) - if (s & 0x0F) < (self.a.get() & 0x0F): - self.f.add(constants.H_FLAG, False) - self.a.set(s) # 1 cycle + added = (self.a.get() + getter()) & 0xFF + self.f.zeroFlagAdd(added, reset=True) + self.f.hFlagCompare(added, self.a) + self.f.cFlagCompare(added, self.a) + self.a.set(added) # 1 cycle # 2 cycles def addHL(self, register): - self.hl.set(self.hl.get() + register.get()); # 1 cycle - s = self.hl.get() - self.f.set((self.f.get() & constants.Z_FLAG), False) - if ((s >> 8) & 0x0F) < (self.hl.getHi() & 0x0F): - self.f.add(constants.H_FLAG, False) - if s < self.hl.get(): - self.f.add(constants.C_FLAG, False) + added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle + self.f.reset(keepZ=True) + self.f.hFlagCompare((added >> 8), self.hl) + self.f.cFlagCompare(added, self.hl) + self.hl.set(added); self.cycles -= 1 # 1 cycle def addWithCarry(self, getter, setter=None): - s = self.a.get() + getter() + ((self.f.get() & constants.C_FLAG) >> 4) - self.f.set(0, False) - self.zeroFlagAdd(s) + s = self.a.get() + getter(); + if self.f.cFlag: + s +=1 + self.f.reset() + self.f.zeroFlagAdd(s) if s >= 0x100: - self.f.add(constants.C_FLAG, False) + self.f.cFlag= True if ((s ^ self.a.get() ^ getter()) & 0x10) != 0: - self.f.add(constants.H_FLAG, False) + self.f.hFlag= True self.a.set(s & 0xFF) # 1 cycle # 1 cycle def subtractWithCarry(self, getter, setter=None): - s = self.a.get() - getter() - ((self.f.get() & constants.C_FLAG) >> 4) - self.f.set(constants.N_FLAG, False) - self.zeroFlagAdd(s) + s = self.a.get() - getter(); + if self.f.cFlag: + s -= 1 + self.f.reset() + self.f.nFlag = True + self.f.zeroFlagAdd(s) if (s & 0xFF00) != 0: - self.f.add(constants.C_FLAG, False) + self.f.cFlag = True if ((s ^ self.a.get() ^ getter()) & 0x10) != 0: - self.f.add(constants.H_FLAG, False) + self.f.hFlag = True self.a.set(s & 0xFF) # 1 cycle # 1 cycle @@ -386,30 +487,31 @@ # 1 cycle def compareA(self, getter, setter=None): s = (self.a.get() - getter()) & 0xFF - self.f.set(constants.N_FLAG) # 1 cycle - self.zeroFlagAdd(s) + self.f.reset() + self.f.nFlag = True + self.f.zeroFlagAdd(s) self.hcFlagFinish(s) + self.cycles -= 1 def hcFlagFinish(self, data): if data > self.a.get(): - self.f.add(constants.C_FLAG, False) - if (data & 0x0F) > (self.a.get() & 0x0F): - self.f.add(constants.H_FLAG, False) + self.f.cFlag = True + self.f.hFlagCompare(self.a, data) # 1 cycle def AND(self, getter, setter=None): self.a.set(self.a.get() & getter()) # 1 cycle - self.zeroFlagAdd(self.a.get(), resetF=True) + self.f.zeroFlagAdd(self.a, reset=True) # 1 cycle def XOR(self, getter, setter=None): self.a.set( self.a.get() ^ getter()) # 1 cycle - self.zeroFlagAdd(self.a.get(), resetF=True) + self.f.zeroFlagAdd(self.a, reset=True) # 1 cycle def OR(self, getter, setter=None): self.a.set(self.a.get() | getter()) # 1 cycle - self.zeroFlagAdd(self.a.get(), resetF=True) + self.f.zeroFlagAdd(self.a, reset=True) def incDoubleRegister(self, doubleRegister): doubleRegister.inc() @@ -420,20 +522,19 @@ # 1 cycle def inc(self, getter, setter): data = (getter() + 1) & 0xFF - self.decIncFlagFinish(data, setter) + self.decIncFlagFinish(data, setter, 0x00) # 1 cycle def dec(self, getter, setter): data = (getter() - 1) & 0xFF - self.decIncFlagFinish(data, setter) - self.f.add(constants.N_FLAG, False) + self.decIncFlagFinish(data, setter, 0x0F) + self.f.nFlag = True - def decIncFlagFinish(self, data, setter): - self.f.set(0, False) - self.zeroFlagAdd(data) - if (data & 0x0F) == 0x0F: - self.f.add(constants.H_FLAG, False) - self.f.add((self.f.get() & constants.C_FLAG), False) + def decIncFlagFinish(self, data, setter, compare): + self.f.reset(keepC=True) + self.f.zeroFlagAdd(data) + if (data & 0x0F) == compare: + self.f.hFlag = True setter(data) # 1 cycle # 1 cycle @@ -443,23 +544,23 @@ # rotateLeftCircularA 1 cycle def rotateLeftCircularA(self): - self.cFlagAdd(self.a.get(), 0x80, resetF=True) + self.f.cFlagAdd(self.a.get(), 0x80, reset=True) self.a.set(((self.a.get() & 0x7F) << 1) + ((self.a.get() & 0x80) >> 7)) # 1 cycle def rotateLeft(self, getter, setter): s = ((getter() & 0x7F) << 1) - if (self.f.get() & constants.C_FLAG) != 0: + if self.f.cFlag: s += 0x01 self.flagsAndSetterFinish(s, setter, 0x80) # 1 cycle # RLA 1 cycle def rotateLeftA(self): s = ((self.a.get() & 0x7F) << 1) - if (self.f.get() & constants.C_FLAG) != 0: + if self.f.cFlag: s += 0x01 - self.cFlagAdd(self.a.get(), 0x80, resetF=True) + self.f.cFlagAdd(self.a.get(), 0x80, reset=True) self.a.set(s) # 1 cycle # 1 cycle @@ -469,20 +570,22 @@ # RRCA 1 cycle def rotateRightCircularA(self): - self.cFlagAdd(self.a.get(), resetF=True) + self.f.cFlagAdd(self.a.get(), reset=True) self.a.set(((self.a.get() >> 1) & 0x7F) + ((self.a.get() << 7) & 0x80)) #1 cycle # 1 cycle def rotateRight(self, getter, setter): - s = (getter() >> 1) + ((self.f.get() & constants.C_FLAG) << 3) + s = (getter() >> 1) + if self.f.cFlag: + s += 0x08 self.flagsAndSetterFinish(s, setter) # 1 cycle # RRA 1 cycle def rotateRightA(self): s = ((self.a.get() >> 1) & 0x7F) - if (self.f.get() & constants.C_FLAG) != 0: + if self.f.cFlag: s += 0x80 - self.cFlagAdd(self.a.get(), resetF=True) + self.f.cFlagAdd(self.a.get(), reset=True) self.a.set(s) # 1 cycle # 2 cycles @@ -502,23 +605,22 @@ # 2 cycles def flagsAndSetterFinish(self, s, setter, compareAnd=0x01): - self.f.set(0) # 1 cycle - self.zeroFlagAdd(s) - self.cFlagAdd(s, compareAnd) + self.f.zeroFlagAdd(s, reset=True) + self.f.cFlagAdd(s, compareAnd) setter(s) # 1 cycle # 1 cycle def swap(self, getter, setter): s = ((getter() << 4) & 0xF0) + ((getter() >> 4) & 0x0F) - self.f.set(0) # 1 cycle - self.zeroFlagAdd(s) + self.f.zeroFlagAdd(s, reset=True) setter(s) # 2 cycles def testBit(self, getter, setter, n): - self.f.set((self.f.get() & constants.C_FLAG) + constants.H_FLAG, False) + self.f.reset(keepC=True) + self.f.hFlag = True if (getter() & (1 << n)) == 0: - self.f.add(constants.Z_FLAG, False) + self.f.zFlag = True self.cycles -= 2 # 2 cycles @@ -559,7 +661,7 @@ hi = self.fetch() # 1 cycle address = (hi << 8) + lo self.write(address, self.sp.getLo()) # 2 cycles - self.write((address + 1) & 0xFFFF, self.sp.getHi()) # 2 cycles + self.write((address + 1), self.sp.getHi()) # 2 cycles self.cycles += 1 # LD (nnnn),A 4 cycles @@ -613,9 +715,11 @@ self.sp.set(self.hl.get()) # 1 cycle self.cycles -= 1 + # def complementA(self): - self.a.set(self.a.get() ^ 0xFF, False) - self.f.set(self.f.get() | (constants.N_FLAG + constants.H_FLAG)) + self.a.set(self.a.get() ^ 0xFF) + self.f.nFlag = True + self.f.hFlag = True # DAA 1 cycle def decimalAdjustAccumulator(self): @@ -634,10 +738,10 @@ self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle else: self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle - self.f.set((self.f.get() & constants.N_FLAG), False) + self.f.reset(keepN=True) if delta >= 0x60: - self.f.add(constants.C_FLAG, False) - self.zeroFlagAdd(self.a.get()) + self.f.cFlag = True + self.f.zeroFlagAdd(self.a) # INC rr def incDoubleRegister(self, register): @@ -661,27 +765,27 @@ def getFetchAddedSP(self): offset = self.fetch() # 1 cycle s = (self.sp.get() + offset) & 0xFFFF - self.f.set(0, False) + self.f.reset() if (offset >= 0): if s < self.sp.get(): - self.f.add(constants.C_FLAG, False) + self.f.cFlag = True if (s & 0x0F00) < (self.sp.get() & 0x0F00): - self.f.add(constants.H_FLAG, False) + self.f.hFlag = True else: if s > self.sp.get(): - self.f.add(constants.C_FLAG, False) + self.f.cFlag = True if (s & 0x0F00) > (self.sp.get() & 0x0F00): - self.f.add(constants.H_FLAG, False) + self.f.hFlag = True return s # CCF/SCF def complementCarryFlag(self): - # Flip C-flag and keep Z-flag - self.f.set((self.f.get() & (constants.Z_FLAG | constants.C_FLAG)) ^ constants.C_FLAG, False) + self.f.reset(keepZ=True, keepC=True) + self.f.cFlag = not self.f.cFlag; def setCarryFlag(self): - # Set C-flag to true and keep Z-flag - self.f.set((self.f.get() & constants.Z_FLAG) | constants.C_FLAG, False) + self.f.reset(keepZ=True) + self.f.cFlag = True # NOP 1 cycle def nop(self): @@ -724,24 +828,6 @@ self.unconditionalCall() # 6 cycles else: self.pc.add(2) # 3 cycles - - def isNZ(self): - return not self.isZ() - - def isNC(self): - return not self.isC() - - def isZ(self): - return (self.f.get() & constants.Z_FLAG) != 0 - - def isC(self): - return (self.f.get() & constants.C_FLAG) != 0 - - def isH(self): - return (self.f.get() & constants.H_FLAG) != 0 - - def isN(self): - return (self.f.get() & constants.N_FLAG) != 0 # RET 4 cycles def ret(self): @@ -769,7 +855,7 @@ self.interrupt() # RST nn 4 cycles - def rst(self, nn): + def restart(self, nn): self.call(nn) # 4 cycles # DI/EI 1 cycle @@ -919,14 +1005,14 @@ (0xEE, lambda s: CPU.XOR(s, s.fetch)), (0xF6, lambda s: CPU.OR(s, s.fetch)), (0xFE, lambda s: CPU.compareA(s, s.fetch)), - (0xC7, lambda s: CPU.rst(s, 0x00)), - (0xCF, lambda s: CPU.rst(s, 0x08)), - (0xD7, lambda s: CPU.rst(s, 0x10)), - (0xDF, lambda s: CPU.rst(s, 0x18)), - (0xE7, lambda s: CPU.rst(s, 0x20)), - (0xEF, lambda s: CPU.rst(s, 0x28)), - (0xF7, lambda s: CPU.rst(s, 0x30)), - (0xFF, lambda s: CPU.rst(s, 0x38)), + (0xC7, lambda s: CPU.restart(s, 0x00)), + (0xCF, lambda s: CPU.restart(s, 0x08)), + (0xD7, lambda s: CPU.restart(s, 0x10)), + (0xDF, lambda s: CPU.restart(s, 0x18)), + (0xE7, lambda s: CPU.restart(s, 0x20)), + (0xEF, lambda s: CPU.restart(s, 0x28)), + (0xF7, lambda s: CPU.restart(s, 0x30)), + (0xFF, lambda s: CPU.restart(s, 0x38)), ] REGISTER_GROUP_OP_CODES = [ @@ -948,7 +1034,7 @@ REGISTER_SET_A = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getSP] REGISTER_SET_B = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getAF] -FLAG_REGISTER_SET = [CPU.isNZ, CPU.isZ, CPU.isNC, CPU.isC] +FLAG_REGISTER_SET = [CPU.isNotZ, CPU.isZ, CPU.isNotC, CPU.isC] REGISTER_OP_CODES = [ (0x01, 0x10, CPU.fetchDoubleRegister, REGISTER_SET_A), (0x09, 0x10, CPU.addHL, REGISTER_SET_A), Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Fri Apr 4 17:15:59 2008 @@ -224,17 +224,17 @@ cpu = get_cpu() cpu.f.set(constants.Z_FLAG) assert cpu.isZ() == True - assert cpu.isNZ() == False + assert cpu.isNotZ() == False cpu.f.set(~constants.Z_FLAG) assert cpu.isZ() == False - assert cpu.isNZ() == True + assert cpu.isNotZ() == True cpu.f.set(constants.C_FLAG) assert cpu.isC() == True - assert cpu.isNC() == False + assert cpu.isNotC() == False cpu.f.set(~constants.C_FLAG) assert cpu.isC() == False - assert cpu.isNC() == True + assert cpu.isNotC() == True def test_flags_memory_access(): cpu = get_cpu() @@ -679,10 +679,10 @@ def test_0x2F(): cpu = get_cpu() value = 0x12 + fValue = cpu.f.get() cpu.a.set(value) - cpu.f.set(value) cycle_test(cpu, 0x2F, 1) - assert_default_registers(cpu, a=value^0xFF, f=value|constants.N_FLAG+constants.H_FLAG) + assert_default_registers(cpu, a=value^0xFF, f=fValue+constants.N_FLAG+constants.H_FLAG) # scf def test_0x37(): @@ -840,7 +840,7 @@ else: assert cpu.a.get() == (valueA ^ value) if cpu.a.get() == 0: - assert cpu.f.get() == constants.Z_FLAG + assert cpu.f.zFlag == True else: assert cpu.f.get() == 0 value += 1 @@ -916,7 +916,7 @@ prepare_for_pop(cpu, value >> 8, value & 0xFF) cpu.f.set(~flags[i]) cycle_test(cpu, opCode, 2) - assert_default_registers(cpu, f=~flags[i] & 0xFF) + assert_default_registers(cpu, f=cpu.f.get()) value += 3 opCode += 0x08 From arigo at codespeak.net Fri Apr 4 17:41:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 17:41:31 +0200 (CEST) Subject: [pypy-svn] r53334 - pypy/branch/less-meta-instances Message-ID: <20080404154131.C9DEE16A808@codespeak.net> Author: arigo Date: Fri Apr 4 17:41:31 2008 New Revision: 53334 Added: pypy/branch/less-meta-instances/ - copied from r53333, pypy/dist/ Log: (antocuni, arigo, niko earlier) A branch in which to try to make ootypesystem.rclass.OBJECT empty. This requires removing the "meta" field and only creating meta-classes and meta-instances when necessary instead of systematically. From arigo at codespeak.net Fri Apr 4 17:42:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 17:42:50 +0200 (CEST) Subject: [pypy-svn] r53335 - in pypy/branch/less-meta-instances/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem Message-ID: <20080404154250.D9CC516A808@codespeak.net> Author: arigo Date: Fri Apr 4 17:42:50 2008 New Revision: 53335 Modified: pypy/branch/less-meta-instances/pypy/annotation/description.py pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py pypy/branch/less-meta-instances/pypy/rpython/rpbc.py Log: (antocuni, arigo, niko earlier) In-progress. Modified: pypy/branch/less-meta-instances/pypy/annotation/description.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/annotation/description.py (original) +++ pypy/branch/less-meta-instances/pypy/annotation/description.py Fri Apr 4 17:42:50 2008 @@ -466,6 +466,9 @@ for name, value in cls.__dict__.items(): self.add_source_attribute(name, value, mixin) + def getallclassdefs(self): + return self._classdefs.values() + def getclassdef(self, key): try: return self._classdefs[key] Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py Fri Apr 4 17:42:50 2008 @@ -373,6 +373,8 @@ v_inst1 = hop.gendirectcall(ll_instantiate, vtypeptr) return hop.genop('cast_pointer', [v_inst1], resulttype = r_instance) + def getlowleveltype(self): + return rclass.CLASSTYPE # ____________________________________________________________ Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py Fri Apr 4 17:42:50 2008 @@ -26,8 +26,8 @@ self.fn_raise_OSError = self.make_raise_OSError(rtyper) def make_exception_matcher(self, rtyper): - # ll_exception_matcher(real_exception_meta, match_exception_meta) - s_classtype = annmodel.SomeOOInstance(self.lltype_of_exception_type) + # ll_exception_matcher(real_exception_class, match_exception_class) + s_classtype = annmodel.SomeOOClass(ootype.ROOT) helper_fn = rtyper.annotate_helper_fn(rclass.ll_issubclass, [s_classtype, s_classtype]) return helper_fn @@ -63,7 +63,6 @@ r_class = rclass.getclassrepr(rtyper, None) r_class.setup() default_excinst = ootype.new(self.lltype_of_exception_value) - default_excinst.meta = r_class.get_meta_instance() # build the table in order base classes first, subclasses last sortedtable = [] Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py Fri Apr 4 17:42:50 2008 @@ -7,49 +7,52 @@ from pypy.rpython.rclass import AbstractClassRepr, AbstractInstanceRepr, \ getinstancerepr, getclassrepr, get_type_repr from pypy.rpython.ootypesystem import ootype +from pypy.rpython.exceptiondata import standardexceptions from pypy.tool.pairtype import pairtype from pypy.tool.sourcetools import func_with_new_name -CLASSTYPE = ootype.Instance("Object_meta", ootype.ROOT, - fields={"class_": ootype.Class}) -OBJECT = ootype.Instance("Object", ootype.ROOT, - fields={'meta': CLASSTYPE}) +OBJECT = ootype.Instance("Object", ootype.ROOT) +META = ootype.Instance("Meta", ootype.ROOT, + fields={"class_": ootype.Class}) class ClassRepr(AbstractClassRepr): def __init__(self, rtyper, classdef): AbstractClassRepr.__init__(self, rtyper, classdef) - + # This is the Repr for a reference to the class 'classdef' or + # any subclass. In the simple case, the lowleveltype is just + # ootype.Class. If we need to store class attributes, we use a + # "meta" class where the attributes are defined, and the class + # reference is a reference to an instance of this meta class. + extra_access_sets = self.rtyper.class_pbc_attributes.get( + classdef, {}) + has_class_attributes = bool(extra_access_sets) if self.classdef is not None: self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) - base_type = self.rbase.lowleveltype - self.lowleveltype = ootype.Instance( - self.classdef.name + "_meta", base_type) + meta_base_type = self.rbase.lowleveltype + baseclass_has_meta = meta_base_type != ootype.Class + else: + baseclass_has_meta = False + + if not has_class_attributes and not baseclass_has_meta: + self.lowleveltype = ootype.Class # simple case else: - # we are ROOT - self.lowleveltype = CLASSTYPE + if self.classdef is None: + raise TyperError("the root 'object' class should not have" + " class attributes") + if self.classdef.classdesc.pyobj in standardexceptions: + raise TyperError("Standard exception class %r should not have" + " class attributes" % (self.classdef.name,)) + if not baseclass_has_meta: + meta_base_type = META + self.lowleveltype = ootype.Instance( + self.classdef.name + "_meta", meta_base_type) def _setup_repr(self): - clsfields = {} pbcfields = {} - if self.classdef is not None: + if self.lowleveltype != ootype.Class: # class attributes llfields = [] - """ - attrs = self.classdef.attrs.items() - attrs.sort() - for name, attrdef in attrs: - if attrdef.readonly: - s_value = attrdef.s_value - s_unboundmethod = self.prepare_method(s_value) - if s_unboundmethod is not None: - allmethods[name] = True - s_value = s_unboundmethod - r = self.rtyper.getrepr(s_value) - mangled_name = 'cls_' + name - clsfields[name] = mangled_name, r - llfields.append((mangled_name, r.lowleveltype)) - """ # attributes showing up in getattrs done on the class as a PBC extra_access_sets = self.rtyper.class_pbc_attributes.get( self.classdef, {}) @@ -61,18 +64,20 @@ self.rbase.setup() ootype.addFields(self.lowleveltype, dict(llfields)) - #self.clsfields = clsfields self.pbcfields = pbcfields self.meta_instance = None def get_meta_instance(self, cast_to_root_meta=True): + if self.lowleveltype == ootype.Class: + raise TyperError("no meta-instance for class %r" % + (self.classdef,)) if self.meta_instance is None: self.meta_instance = ootype.new(self.lowleveltype) self.setup_meta_instance(self.meta_instance, self) meta_instance = self.meta_instance if cast_to_root_meta: - meta_instance = ootype.ooupcast(CLASSTYPE, meta_instance) + meta_instance = ootype.ooupcast(META, meta_instance) return meta_instance def setup_meta_instance(self, meta_instance, rsubcls): @@ -88,14 +93,6 @@ llvalue = r.convert_desc_or_const(value) setattr(meta_instance, mangled_name, llvalue) - #mro = list(rsubcls.classdef.getmro()) - #for fldname in self.clsfields: - # mangled_name, r = self.clsfields[fldname] - # if r.lowleveltype is Void: - # continue - # value = rsubcls.classdef.classdesc.read_attribute(fldname, None) - # if value is not None: - # assign(mangled_name, value) # extra PBC attributes for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): if rsubcls.classdef.classdesc not in access_set.descs: @@ -107,15 +104,20 @@ assign(mangled_name, attrvalue) # then initialize the 'super' portion of the vtable - meta_instance_super = ootype.ooupcast( - self.rbase.lowleveltype, meta_instance) - self.rbase.setup_meta_instance(meta_instance_super, rsubcls) + self.rbase.setup_meta_instance(meta_instance, rsubcls) getruntime = get_meta_instance def fromclasstype(self, vclass, llops): - return llops.genop('oodowncast', [vclass], - resulttype=self.lowleveltype) + assert ootype.isSubclass(vclass.concretetype, META) + if self.lowleveltype == ootype.Class: + c_class_ = inputconst(ootype.Void, 'class_') + return llops.genop('oogetfield', [vclass, c_class_], + resulttype=ootype.Class) + else: + assert ootype.isSubclass(self.lowleveltype, vclass.concretetype) + return llops.genop('oodowncast', [vclass], + resulttype=self.lowleveltype) def getpbcfield(self, vcls, access_set, attr, llops): if (access_set, attr) not in self.pbcfields: @@ -127,12 +129,11 @@ def rtype_issubtype(self, hop): class_repr = get_type_repr(self.rtyper) - vmeta1, vmeta2 = hop.inputargs(class_repr, class_repr) - return hop.gendirectcall(ll_issubclass, vmeta1, vmeta2) + vcls1, vcls2 = hop.inputargs(class_repr, class_repr) + return hop.genop('subclassof', [vcls1, vcls2], resulttype=ootype.Bool) -def ll_issubclass(meta1, meta2): - class1 = meta1.class_ - class2 = meta2.class_ +def ll_issubclass(class1, class2): + # helper for exceptiondata.py return ootype.subclassof(class1, class2) # ____________________________________________________________ @@ -237,7 +238,7 @@ mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception - + # # hash() support if self.rtyper.needs_hash_support(self.classdef): @@ -255,6 +256,12 @@ baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) + # if this class has a corresponding metaclass, attach + # a getmeta() method to get the corresponding meta_instance + if classrepr.lowleveltype != ootype.Class: + oovalue = classrepr.get_meta_instance() + self.attach_class_attr_accessor('getmeta', oovalue) + for mangled, (name, s_value) in allmethods.iteritems(): methdescs = s_value.descriptions origin = dict([(methdesc.originclassdef, methdesc) for @@ -329,7 +336,12 @@ for mangled, (s_value, value) in self.classattributes.items(): r = self.rtyper.getrepr(s_value) - m = self.attach_class_attr_accessor(mangled, value, r) + if value is None: + self.attach_abstract_class_attr_accessor(mangled, + r.lowleveltype) + else: + oovalue = r.convert_desc_or_const(value) + self.attach_class_attr_accessor(mangled, oovalue) # step 4: do the same with instance fields whose default # values are overridden in subclasses. Not sure it's the best @@ -359,21 +371,21 @@ ootype.overrideDefaultForFields(self.lowleveltype, overridden_defaults) - def attach_class_attr_accessor(self, mangled, value, r_value): + def attach_abstract_class_attr_accessor(self, mangled, attrtype): + M = ootype.Meth([], attrtype) + m = ootype.meth(M, _name=mangled, abstract=True) + ootype.addMethods(self.lowleveltype, {mangled: m}) + + def attach_class_attr_accessor(self, mangled, oovalue): def ll_getclassattr(self): return oovalue - M = ootype.Meth([], r_value.lowleveltype) - if value is None: - m = ootype.meth(M, _name=mangled, abstract=True) - else: - oovalue = r_value.convert_desc_or_const(value) - ll_getclassattr = func_with_new_name(ll_getclassattr, - 'll_get_' + mangled) - graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype]) - m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr, - graph=graph) - + M = ootype.Meth([], ootype.typeOf(oovalue)) + ll_getclassattr = func_with_new_name(ll_getclassattr, + 'll_get_' + mangled) + graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype]) + m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr, + graph=graph) ootype.addMethods(self.lowleveltype, {mangled: m}) def get_ll_hash_function(self): @@ -446,8 +458,7 @@ if hop.args_s[0].can_be_none(): return hop.gendirectcall(ll_inst_type, vinst) else: - cmeta = inputconst(ootype.Void, "meta") - return hop.genop('oogetfield', [vinst, cmeta], resulttype=CLASSTYPE) + return hop.genop('classof', [vinst], resulttype=ootype.Class) def null_instance(self): return ootype.null(self.lowleveltype) @@ -463,10 +474,6 @@ classrepr = getclassrepr(self.rtyper, self.classdef) v_instance = llops.genop("new", [inputconst(ootype.Void, self.lowleveltype)], self.lowleveltype) - cmeta = inputconst(ootype.Void, "meta") - cmeta_instance = inputconst(CLASSTYPE, classrepr.get_meta_instance()) - llops.genop("oosetfield", [v_instance, cmeta, cmeta_instance], - resulttype=ootype.Void) return v_instance def initialize_prebuilt_instance(self, value, classdef, result): @@ -539,7 +546,7 @@ def ll_inst_type(obj): if obj: - return obj.meta + return ootype.classof(obj) else: # type(None) -> NULL (for now) - return ootype.null(CLASSTYPE) + return ootype.nullruntimeclass Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py Fri Apr 4 17:42:50 2008 @@ -4,11 +4,12 @@ AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr, \ none_frozen_pbc_repr from pypy.rpython.rclass import rtype_new_instance, getinstancerepr +from pypy.rpython.rclass import getclassrepr, get_type_repr from pypy.rpython.rpbc import get_concrete_calltable from pypy.rpython import callparse from pypy.rpython.ootypesystem import ootype from pypy.rpython.ootypesystem.rclass import ClassRepr, InstanceRepr -from pypy.rpython.ootypesystem.rclass import mangle +from pypy.rpython.ootypesystem.rclass import mangle, META from pypy.annotation import model as annmodel from pypy.annotation import description from pypy.tool.pairtype import pairtype @@ -42,17 +43,24 @@ class ClassesPBCRepr(AbstractClassesPBCRepr): - def _instantiate_runtime_class(self, hop, v_meta, r_instance): + def _instantiate_runtime_class(self, hop, v_class, r_instance): classdef = hop.s_result.classdef - c_class_ = hop.inputconst(ootype.Void, "class_") - v_class = hop.genop('oogetfield', [v_meta, c_class_], - resulttype=ootype.Class) resulttype = getinstancerepr(hop.rtyper, classdef).lowleveltype - v_instance = hop.genop('runtimenew', [v_class], resulttype=resulttype) - c_meta = hop.inputconst(ootype.Void, "meta") - hop.genop('oosetfield', [v_instance, c_meta, v_meta], - resulttype=ootype.Void) - return v_instance + # convert v_class from META to ootype.Class if necessary: + v_class = get_type_repr(hop.rtyper).fromclasstype(v_class, hop.llops) + return hop.genop('runtimenew', [v_class], resulttype=resulttype) + + def getlowleveltype(self): + classdescs = self.s_pbc.descriptions.keys() + # if any of the classdefs get the lowleveltype ootype.Class, + # we can only pick ootype.Class for us too. Otherwise META. + for classdesc in classdescs: + for classdef in classdesc.getallclassdefs(): + r_class = getclassrepr(self.rtyper, classdef) + if r_class.lowleveltype == ootype.Class: + return ootype.Class + else: + return META def row_method_name(methodname, rowname): Modified: pypy/branch/less-meta-instances/pypy/rpython/rpbc.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/rpbc.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/rpbc.py Fri Apr 4 17:42:50 2008 @@ -642,7 +642,7 @@ if s_pbc.is_constant(): self.lowleveltype = Void else: - self.lowleveltype = rtyper.type_system.rclass.CLASSTYPE + self.lowleveltype = self.getlowleveltype() def get_access_set(self, attrname): """Return the ClassAttrFamily corresponding to accesses to 'attrname' @@ -774,8 +774,6 @@ if r_clspbc.lowleveltype is Void: return inputconst(r_cls, r_clspbc.s_pbc.const) # convert from ptr-to-object-vtable to ptr-to-more-precise-vtable - assert (r_clspbc.lowleveltype == - r_clspbc.rtyper.type_system.rclass.CLASSTYPE) return r_cls.fromclasstype(v, llops) class __extend__(pairtype(AbstractClassesPBCRepr, AbstractClassesPBCRepr)): From arigo at codespeak.net Fri Apr 4 18:18:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 18:18:24 +0200 (CEST) Subject: [pypy-svn] r53336 - in pypy/branch/less-meta-instances/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20080404161824.DD60316A829@codespeak.net> Author: arigo Date: Fri Apr 4 18:18:22 2008 New Revision: 53336 Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py pypy/branch/less-meta-instances/pypy/rpython/rclass.py pypy/branch/less-meta-instances/pypy/rpython/rpbc.py pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py Log: (antocuni, arigo) More progress... Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py Fri Apr 4 18:18:22 2008 @@ -166,7 +166,10 @@ if cast_to_typeptr: vtable = cast_vtable_to_typeptr(vtable) return vtable - getruntime = getvtable + + def getruntime(self, expected_type): + assert expected_type == CLASSTYPE + return self.getvtable() def setup_vtable(self, vtable, rsubcls): """Initialize the 'self' portion of the 'vtable' belonging to the Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py Fri Apr 4 18:18:22 2008 @@ -83,7 +83,7 @@ def setup_meta_instance(self, meta_instance, rsubcls): if self.classdef is None: rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) - setattr(meta_instance, 'class_', rinstance.lowleveltype._class) + meta_instance.class_ = ootype.runtimeClass(rinstance.lowleveltype) else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls @@ -106,8 +106,15 @@ # then initialize the 'super' portion of the vtable self.rbase.setup_meta_instance(meta_instance, rsubcls) - getruntime = get_meta_instance - + def getruntime(self, expected_type): + if expected_type == ootype.Class: + rinstance = getinstancerepr(self.rtyper, self.classdef) + return ootype.runtimeClass(rinstance.lowleveltype) + else: + assert ootype.isSubclass(expected_type, META) + meta = self.get_meta_instance(cast_to_root_meta=False) + return ootype.ooupcast(expected_type, meta) + def fromclasstype(self, vclass, llops): assert ootype.isSubclass(vclass.concretetype, META) if self.lowleveltype == ootype.Class: Modified: pypy/branch/less-meta-instances/pypy/rpython/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/rclass.py Fri Apr 4 18:18:22 2008 @@ -61,7 +61,8 @@ raise TyperError("not a subclass of %r: %r" % ( self.classdef.name, desc)) - return getclassrepr(self.rtyper, subclassdef).getruntime() + r_subclass = getclassrepr(self.rtyper, subclassdef) + return r_subclass.getruntime(self.lowleveltype) def convert_const(self, value): if not isinstance(value, (type, types.ClassType)): Modified: pypy/branch/less-meta-instances/pypy/rpython/rpbc.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/rpbc.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/rpbc.py Fri Apr 4 18:18:22 2008 @@ -665,7 +665,9 @@ raise TyperError("%r not in %r" % (cls, self)) if self.lowleveltype is Void: return None - return rclass.get_type_repr(self.rtyper).convert_desc(desc) + subclassdef = desc.getuniqueclassdef() + r_subclass = rclass.getclassrepr(self.rtyper, subclassdef) + return r_subclass.getruntime(self.lowleveltype) def convert_const(self, cls): if cls is None: Modified: pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py Fri Apr 4 18:18:22 2008 @@ -97,16 +97,31 @@ assert res == 4 def test_runtime_exception(self): + class MyExc(Exception): + pass + class Sub1(MyExc): + pass + class Sub2(MyExc): + pass def pick(flag): if flag: - return TypeError + return Sub1 else: - return ValueError - def f(flag): + return Sub2 + def g(flag): ex = pick(flag) raise ex() - self.interpret_raises(TypeError, f, [True]) - self.interpret_raises(ValueError, f, [False]) + def f(flag): + try: + g(flag) + except Sub1: + return 1 + except Sub2: + return 2 + else: + return 3 + assert self.interpret(f, [True]) == 1 + assert self.interpret(f, [False]) == 2 def test_classattr_as_defaults(self): def dummyfn(): From arigo at codespeak.net Fri Apr 4 18:39:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 18:39:35 +0200 (CEST) Subject: [pypy-svn] r53337 - in pypy/branch/less-meta-instances/pypy/rpython: ootypesystem test Message-ID: <20080404163935.68DBA16A85A@codespeak.net> Author: arigo Date: Fri Apr 4 18:39:34 2008 New Revision: 53337 Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py Log: (antocuni, arigo) More small fixes; test_class passes! Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py Fri Apr 4 18:39:34 2008 @@ -75,15 +75,14 @@ v_obj, v_cls = hop.inputargs(instance_repr, class_repr) if isinstance(v_cls, Constant): - c_cls = hop.inputconst(ootype.Void, v_cls.value.class_._INSTANCE) + c_cls = hop.inputconst(ootype.Void, v_cls.value._INSTANCE) return hop.genop('instanceof', [v_obj, c_cls], resulttype=ootype.Bool) else: return hop.gendirectcall(ll_isinstance, v_obj, v_cls) -def ll_isinstance(inst, meta): - c1 = inst.meta.class_ - c2 = meta.class_ - return ootype.subclassof(c1, c2) +def ll_isinstance(inst, class_): + c1 = ootype.classof(inst) + return ootype.subclassof(c1, class_) def rtype_instantiate(hop): if hop.args_s[0].is_constant(): Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py Fri Apr 4 18:39:34 2008 @@ -423,14 +423,21 @@ return hop.genop("oosend", [cname, v_inst], resulttype = hop.r_result.lowleveltype) elif attr == '__class__': - if hop.r_result.lowleveltype is ootype.Void: + expected_type = hop.r_result.lowleveltype + if expected_type is ootype.Void: # special case for when the result of '.__class__' is constant [desc] = hop.s_result.descriptions return hop.inputconst(ootype.Void, desc.pyobj) + elif expected_type == ootype.Class: + return hop.genop('classof', [v_inst], + resulttype = ootype.Class) else: - cmeta = inputconst(ootype.Void, "meta") - return hop.genop('oogetfield', [v_inst, cmeta], - resulttype=CLASSTYPE) + assert expected_type == META + _, meth = v_inst.concretetype._lookup('getmeta') + assert meth + c_getmeta = hop.inputconst(ootype.Void, 'getmeta') + return hop.genop('oosend', [c_getmeta, v_inst], + resulttype = META) else: raise TyperError("no attribute %r on %r" % (attr, self)) Modified: pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/test/test_rclass.py Fri Apr 4 18:39:34 2008 @@ -816,8 +816,8 @@ t.buildrtyper(type_system=self.type_system).specialize() graph = graphof(t, f) TYPEA = graph.startblock.operations[0].args[0].value - TYPEB = graph.startblock.operations[2].args[0].value - TYPEC = graph.startblock.operations[4].args[0].value + TYPEB = graph.startblock.operations[1].args[0].value + TYPEC = graph.startblock.operations[2].args[0].value _, destra = TYPEA._lookup("o__del__") _, destrb = TYPEB._lookup("o__del__") _, destrc = TYPEC._lookup("o__del__") From arigo at codespeak.net Fri Apr 4 18:42:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 18:42:15 +0200 (CEST) Subject: [pypy-svn] r53338 - pypy/branch/less-meta-instances/pypy/rpython Message-ID: <20080404164215.16D8016A4F6@codespeak.net> Author: arigo Date: Fri Apr 4 18:42:14 2008 New Revision: 53338 Modified: pypy/branch/less-meta-instances/pypy/rpython/llinterp.py Log: (antocuni, arigo) And now test_rpbc passes too. Modified: pypy/branch/less-meta-instances/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/llinterp.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/llinterp.py Fri Apr 4 18:42:14 2008 @@ -37,7 +37,7 @@ return ''.join(etype.name).rstrip('\x00') else: # ootype! - return etype.class_._INSTANCE._name.split(".")[-1] + return etype._INSTANCE._name.split(".")[-1] class LLInterpreter(object): """ low level interpreter working with concrete values. """ From fijal at codespeak.net Fri Apr 4 18:47:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 18:47:47 +0200 (CEST) Subject: [pypy-svn] r53339 - pypy/branch/js-refactoring/pypy/lang/js/test/ecma Message-ID: <20080404164747.C73D816A88B@codespeak.net> Author: fijal Date: Fri Apr 4 18:47:47 2008 New Revision: 53339 Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Log: cache shellfile, greatly speeds up running ecma tests. Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Fri Apr 4 18:47:47 2008 @@ -37,8 +37,9 @@ cls.interp = Interpreter() shellpath = rootdir/'shell.js' - t = load_file(str(shellpath)) - cls.interp.run(t) + if not hasattr(cls, 'shellfile'): + cls.shellfile = load_file(str(shellpath)) + cls.interp.run(cls.shellfile) cls.testcases = cls.interp.global_context.resolve_identifier('testcases') cls.tc = cls.interp.global_context.resolve_identifier('tc') init_interp = classmethod(init_interp) From arigo at codespeak.net Fri Apr 4 18:55:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 18:55:43 +0200 (CEST) Subject: [pypy-svn] r53340 - in pypy/branch/less-meta-instances/pypy/rpython: ootypesystem test Message-ID: <20080404165543.90F5416A8A0@codespeak.net> Author: arigo Date: Fri Apr 4 18:55:41 2008 New Revision: 53340 Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/less-meta-instances/pypy/rpython/test/test_normalizecalls.py pypy/branch/less-meta-instances/pypy/rpython/test/test_rbuiltin.py Log: Fix instantiate(). Fix some other tests. Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rbuiltin.py Fri Apr 4 18:55:41 2008 @@ -98,17 +98,12 @@ else: r_instance = hop.s_result.rtyper_makerepr(hop.rtyper) INSTANCE = r_instance.lowleveltype - c_instance = hop.inputconst(ootype.Void, INSTANCE) - v_cls = hop.inputarg(hop.args_r[0], arg=0) - v_obj = hop.gendirectcall(ll_instantiate, c_instance, v_cls) + class_repr = rclass.get_type_repr(hop.rtyper) + v_cls = hop.inputarg(class_repr, arg=0) + v_obj = hop.genop('runtimenew', [v_cls], resulttype=ootype.ROOT) v_instance = hop.genop('oodowncast', [v_obj], resulttype=hop.r_result.lowleveltype) - c_meta = hop.inputconst(ootype.Void, "meta") - hop.genop("oosetfield", [v_instance, c_meta, v_cls], resulttype=ootype.Void) return v_instance -def ll_instantiate(INST, C): - return ootype.runtimenew(C.class_) - BUILTIN_TYPER = {} BUILTIN_TYPER[ootype.new] = rtype_new BUILTIN_TYPER[ootype.oonewarray] = rtype_oonewarray Modified: pypy/branch/less-meta-instances/pypy/rpython/test/test_normalizecalls.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/test/test_normalizecalls.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/test/test_normalizecalls.py Fri Apr 4 18:55:41 2008 @@ -219,6 +219,7 @@ def test_add_more_subclasses(self): from pypy.rpython import rclass from pypy.rpython.lltypesystem.rclass import ll_issubclass + from pypy.rpython.lltypesystem.rclass import CLASSTYPE class Sub3(PBase): def newmethod(self): return 3 @@ -232,9 +233,9 @@ bk = translator.annotator.bookkeeper rtyper = translator.rtyper base_classdef = bk.getuniqueclassdef(PBase) - base_vtable = rclass.getclassrepr(rtyper, base_classdef).getruntime() + base_vtable = rclass.getclassrepr(rtyper, base_classdef).getruntime(CLASSTYPE) sub3_classdef = bk.getuniqueclassdef(Sub3) - sub3_vtable = rclass.getclassrepr(rtyper, sub3_classdef).getruntime() + sub3_vtable = rclass.getclassrepr(rtyper, sub3_classdef).getruntime(CLASSTYPE) assert ll_issubclass(sub3_vtable, base_vtable) assert not ll_issubclass(base_vtable, sub3_vtable) Modified: pypy/branch/less-meta-instances/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/test/test_rbuiltin.py Fri Apr 4 18:55:41 2008 @@ -530,24 +530,19 @@ class TestOOtype(BaseTestRbuiltin, OORtypeMixin): - def test_instantiate_meta(self): - class A: - pass - def f(): - return instantiate(A) - res = self.interpret(f, []) - assert res.meta # check that it's not null - def test_instantiate_multiple_meta(self): class A: - pass + x = 2 class B(A): - pass + x = 3 + def do_stuff(cls): + return cls.x def f(i): if i == 1: cls = A else: cls = B + do_stuff(cls) return instantiate(cls) res = self.interpret(f, [1]) - assert res.meta # check that it's not null + assert res.getmeta() # check that it exists From arigo at codespeak.net Fri Apr 4 19:00:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Apr 2008 19:00:20 +0200 (CEST) Subject: [pypy-svn] r53341 - pypy/branch/less-meta-instances/pypy/rpython/ootypesystem Message-ID: <20080404170020.28ED816A860@codespeak.net> Author: arigo Date: Fri Apr 4 19:00:18 2008 New Revision: 53341 Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py Log: We can set OBJECT to ootype.ROOT now that it's empty. Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py Fri Apr 4 19:00:18 2008 @@ -11,7 +11,7 @@ from pypy.tool.pairtype import pairtype from pypy.tool.sourcetools import func_with_new_name -OBJECT = ootype.Instance("Object", ootype.ROOT) +OBJECT = ootype.ROOT META = ootype.Instance("Meta", ootype.ROOT, fields={"class_": ootype.Class}) From pedronis at codespeak.net Fri Apr 4 19:00:48 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 19:00:48 +0200 (CEST) Subject: [pypy-svn] r53343 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080404170048.C137816A85C@codespeak.net> Author: pedronis Date: Fri Apr 4 19:00:47 2008 New Revision: 53343 Modified: pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py pypy/dist/pypy/lib/app_test/ctypes/test_funcptr.py pypy/dist/pypy/lib/app_test/ctypes/test_functions.py pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py pypy/dist/pypy/lib/app_test/ctypes/test_init.py pypy/dist/pypy/lib/app_test/ctypes/test_parameters.py pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py pypy/dist/pypy/lib/app_test/ctypes/test_stringptr.py pypy/dist/pypy/lib/app_test/ctypes/test_struct_fields.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py pypy/dist/pypy/lib/app_test/ctypes/test_values.py Log: reviewed tests and skips. tried to make skip messages more clear and consistent. in the test_stringptr.py case the tests were mostly passing, I modified them and put a skip test passed!... at the end of them test_guess_argtypes needs fixing Modified: pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py Fri Apr 4 19:00:47 2008 @@ -89,7 +89,7 @@ ## self.check_type(c_char_p, "def") def test_unsupported_restype_1(self): - py.test.skip("WIP") + py.test.skip("we are less strict about callback return type sanity") # Only "fundamental" result types are supported for callback # functions, the type must have a non-NULL stgdict->setfunc. # POINTER(c_double), for example, is not supported. @@ -137,7 +137,7 @@ class TestMoreCallbacks(BaseCTypesTestChecker): def test_callback_with_struct_argument(self): - py.test.skip("WIP") + py.test.skip("callbacks with struct arguments not implemented yet") class RECT(Structure): _fields_ = [("left", c_int), ("top", c_int), ("right", c_int), ("bottom", c_int)] Modified: pypy/dist/pypy/lib/app_test/ctypes/test_funcptr.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_funcptr.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_funcptr.py Fri Apr 4 19:00:47 2008 @@ -42,7 +42,7 @@ # The following no longer raises a TypeError - it is now # possible, as in C, to call cdecl functions with more parameters. #self.assertRaises(TypeError, c, 1, 2, 3) - py.test.skip("PyPy's CTypes doesn't implement this") + py.test.skip("cdecl funcptrs ignoring extra args is not implemented") assert c(1, 2, 3, 4, 5, 6) == 3 if not WINFUNCTYPE is CFUNCTYPE and os.name != "ce": raises(TypeError, s, 1, 2, 3) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_functions.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_functions.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_functions.py Fri Apr 4 19:00:47 2008 @@ -393,7 +393,7 @@ assert result == "bcd" def test_sf1651235(self): - py.test.skip("XXX parameter checking for callbacks should be stricter") + py.test.skip("we are less strict in checking callback parameters") # see http://www.python.org/sf/1651235 proto = CFUNCTYPE(c_int, RECT, POINT) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py Fri Apr 4 19:00:47 2008 @@ -1,9 +1,12 @@ """ This test checks whether args wrapping behavior is correct """ +import py import sys +py.test.skip("FIXME") + from ctypes import * def test_wrap_args(): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_init.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_init.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_init.py Fri Apr 4 19:00:47 2008 @@ -1,7 +1,7 @@ import py from ctypes import * -py.test.skip("XXX subclassing behavior and implementation details tests") +py.test.skip("subclassing semantics and implementation details not implemented") class X(Structure): _fields_ = [("a", c_int), Modified: pypy/dist/pypy/lib/app_test/ctypes/test_parameters.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_parameters.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_parameters.py Fri Apr 4 19:00:47 2008 @@ -22,7 +22,7 @@ def test_subclasses(self): - py.test.skip("XXX subclassing problem") + py.test.skip("subclassing semantics not implemented") from ctypes import c_void_p, c_char_p # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new class CVOIDP(c_void_p): @@ -52,7 +52,7 @@ # XXX Replace by c_char_p tests def test_cstrings(self): - py.test.skip("Implementation specific IMO") + py.test.skip("testing implementation internals") from ctypes import c_char_p, byref # c_char_p.from_param on a Python String packs the string @@ -151,7 +151,7 @@ ## check_perf() def test_noctypes_argtype(self): - py.test.skip("We implement details differently") + py.test.skip("we implement details differently") from ctypes import CDLL, c_void_p, ArgumentError import conftest dll = CDLL(str(conftest.sofile)) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py Fri Apr 4 19:00:47 2008 @@ -26,7 +26,7 @@ def test_int_callback(self): - py.test.skip("XXX subclassing not implemented") + py.test.skip("subclassing semantics and implementation details not implemented") args = [] def func(arg): args.append(arg) @@ -43,7 +43,7 @@ assert type(args[-1]) == int def test_int_struct(self): - py.test.skip("XXX wrong behaviour") + py.test.skip("subclassing semantics and implementation details not implemented") class X(Structure): _fields_ = [("x", MyInt)] Modified: pypy/dist/pypy/lib/app_test/ctypes/test_stringptr.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_stringptr.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_stringptr.py Fri Apr 4 19:00:47 2008 @@ -11,7 +11,6 @@ class TestStringPtr(BaseCTypesTestChecker): def test__POINTER_c_char(self): - py.test.skip("uses getrefcount") class X(Structure): _fields_ = [("str", POINTER(c_char))] x = X() @@ -19,20 +18,22 @@ # NULL pointer access raises(ValueError, getattr, x.str, "contents") b = c_buffer("Hello, World") - from sys import getrefcount as grc - assert grc(b) == 2 + #from sys import getrefcount as grc + #assert grc(b) == 2 x.str = b - assert grc(b) == 3 + #assert grc(b) == 3 # POINTER(c_char) and Python string is NOT compatible # POINTER(c_char) and c_buffer() is compatible for i in range(len(b)): assert b[i] == x.str[i] - raises(TypeError, setattr, x, "str", "Hello, World") + # XXX pypy modified: + #raises(TypeError, setattr, x, "str", "Hello, World") + x = b = None + py.test.skip("test passes! but modified to avoid getrefcount and detail issues") def test__c_char_p(self): - py.test.skip("XXX not implemented") class X(Structure): _fields_ = [("str", c_char_p)] x = X() @@ -42,8 +43,11 @@ assert x.str == None x.str = "Hello, World" assert x.str == "Hello, World" - b = c_buffer("Hello, World") - raises(TypeError, setattr, x, "str", b) + # XXX pypy modified: + #b = c_buffer("Hello, World") + #raises(TypeError, setattr, x, "str", b) + x = None + py.test.skip("test passes! but modified to avoid detail issues") def test_functions(self): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_struct_fields.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_struct_fields.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_struct_fields.py Fri Apr 4 19:00:47 2008 @@ -26,14 +26,14 @@ raises(AttributeError, setattr, X, "_fields_", []) def test_2(self): - py.test.skip("no _fields_ unsupported") + py.test.skip("absent _fields_ semantics not implemented") class X(Structure): pass X() raises(AttributeError, setattr, X, "_fields_", []) def test_3(self): - py.test.skip("fails: no _fields_ and subclassing") + py.test.skip("subclassing semantics not implemented") class X(Structure): pass class Y(Structure): @@ -41,7 +41,7 @@ raises(AttributeError, setattr, X, "_fields_", []) def test_4(self): - py.test.skip("fails: no _fields_ and subclassing") + py.test.skip("subclassing semantics not implemented") class X(Structure): pass class Y(X): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Fri Apr 4 19:00:47 2008 @@ -161,7 +161,7 @@ # offset is always relative to the class... def test_packed(self): - py.test.skip("Custom alignment not supported") + py.test.skip("custom alignment not supported") class X(Structure): _fields_ = [("a", c_byte), ("b", c_longlong)] @@ -284,7 +284,7 @@ raises(ValueError, PersonW, u"1234567890123") def test_init_errors(self): - py.test.skip("Very fragile errors") + py.test.skip("not implemented error details") class Phone(Structure): _fields_ = [("areacode", c_char*6), ("number", c_char*12)] @@ -332,7 +332,7 @@ ## (AttributeError, "class must define a '_fields_' attribute")) def test_abstract_class(self): - py.test.skip("_abstract_ not implemented") + py.test.skip("_abstract_ semantics not implemented") class X(Structure): _abstract_ = "something" # try 'X()' @@ -358,7 +358,7 @@ assert p.age == 6 def test_subclassing_field_is_a_tuple(self): - py.test.skip("suclassing not supported") + py.test.skip("subclassing semantics not implemented") class Person(Structure): _fields_ = (("name", c_char*6), ("age", c_int)) @@ -429,7 +429,7 @@ def test_vice_versa(self): - py.test.skip("XXX mutually dependent lazily defined structures") + py.test.skip("mutually dependent lazily defined structures error semantics") class First(Structure): pass class Second(Structure): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_values.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_values.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_values.py Fri Apr 4 19:00:47 2008 @@ -26,7 +26,7 @@ class TestWin_Values(BaseCTypesTestChecker): """This test only works when python itself is a dll/shared library""" def setup_class(cls): - py.test.skip("only when cpython itself is a dll") + py.test.skip("tests expect and access cpython dll") def test_optimizeflag(self): # This test accesses the Py_OptimizeFlag intger, which is From pedronis at codespeak.net Fri Apr 4 19:01:47 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 19:01:47 +0200 (CEST) Subject: [pypy-svn] r53344 - pypy/dist/pypy/doc Message-ID: <20080404170147.AD18F16A8A9@codespeak.net> Author: pedronis Date: Fri Apr 4 19:01:46 2008 New Revision: 53344 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: first pass over ctypes-implementation.txt Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Fri Apr 4 19:01:46 2008 @@ -1,93 +1,100 @@ -======================================== -PyPy's ctypes implementation document -======================================== +============================= +PyPy's ctypes implementation +============================= -* application level code - code written in full python +terminology: + +* application level code - code written in full Python * interpreter level code - code written in RPython, compiled to something else, say C, part of the interpreter. -PyPy's ctypes implementation is right now mostly a proof of concept, -based on the idea of quick prototyping. The main idea was to use libffi -(same as CPython's ctypes implementation), but try to keep as much -code as possible in Python, not RPython. In CPython's situation, -the equivalent would be to write as little as possible code in C. - -Low-level part (called \_rawffi) -================================ - -We implemented direct bindings to libffi in RPython, allowing to create simple -types (arrays, structures), living in C world, managed by hand. It also -supports calling C functions. -This part contains no special code to keep objects alive and is kept very minimal. -We tried to keep this as small as possible to allow porting our ctypes -implementation to other platforms easily. It's also thinkable that Jython uses -our ctypes implementation by writing their version of _rawffi. - -High-level part (lib/\_ctypes) -=============================== - -This part implements the same interface as the \_ctypes module in CPython, -but it's written in full python. This approach allowed us to experiment -quickly and provide a working implementation in 2 months of real time. - -Reuse of the highest level (lib/ctypes) -======================================== +PyPy's ctypes implementation in its current state proves the +feasibility of implementing a module with the same interface and +behavior for PyPy as ctypes for CPython. -We just reused the part which is application level in CPython as well. +PyPy's implementation internally uses `libffi`_ like CPython's ctypes. +In our implementation as much as possible of the code is written in +full Python, not RPython, In CPython's situation, the equivalent would +be to write as little as possible code in C. We essentially favored +rapid experimentation over worrying about speed for this first trial +implementation. This allowed to provide a working implementation with +a large part of ctypes features in 2 months real time. -Ctypes-platform -=============== +We reused the ``ctypes`` package as-is from CPython. We implemented +``_ctypes`` which is a C module in CPython mostly in pure Python based on +a lower-level layer extension module ``_rawffi``. -We released `ctypes-configure`_, which is a package trying to overcome -portability of ctypes-based code. +.. _`libffi`: http://sources.redhat.com/libffi/ -.. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html +Low-level part: ``_rawffi`` +============================ + +This PyPy extension module (``pypy/module/_rawffi``) exposes a simple interface +to create C objects (arrays and structures) and calling functions +in dynamic libraries through libffi. Freeing objects in most cases and making +sure that objects referring to each other are kept alive is responsibility of the higher levels. + +This module uses bindings to libffi which are defined in ``pypy/rlib/libffi.py``. + +We tried to keep this module as small as possible. It is conceivable +that other implementations (e.g. Jython) could use our ctypes +implementation by writing their version of ``_rawffi``. + +High-level parts +================= + +The reused ``ctypes`` package lives in ``pypy/lib/ctypes``. ``_ctypes`` +implementing the same interface as ``_ctypes`` in CPython is in +``pypy/lib/_ctypes``. -Limitations -=========== +Discussion and limitations +============================= -* No support for PyXxx functions from libpython, for obvious reasons. +Reimplementing ctypes features was in general possible. PyPy supports +pluggable garbage collectors, some of them are moving collectors, this +means that the strategy of passing direct references inside Python +objects to an external library is not feasible (unless the GCs +support pinning, which not the case right now). The consequence of +this is that sometimes copying instead of sharing is required, this +may result in some semantics differences. C objects created with +_rawffi itself are allocated outside of the GC heap, so they can be +passed to external functions without worries. -* Subclassing works differently (ie it follows python subclassing scheme - instead of ctypes subclassing scheme, which does not do - inheritance) +Porting the implementation to interpreter-level should likely improve +its speed, Further the current layering and the current _rawffi +interface require more object allocations and copying than strictly +necessary, this too could be improved. -* It's not supposed to work on other platform than linux +The implementation was developed and has only been tested on Linux. -* We copy strings instead of having pointers to raw buffers, which - changes keepalive logic a bit +Here is a list of the limitations and missing features of the +current implementation: -* Custom alignment is not supported +* No support for ``PyXxx`` functions from ``libpython``, for obvious reasons. -* Callbacks with structures and arrays by-value are unsupported +* We copy Python strings instead of having pointers to raw buffers -Minor unsupported features: -=========================== +* Features we did not get to implement: -* \_check\_retval\_ is not supported + - custom alignment and bit-fields -* \_abstract\_ is not supported + - resizing (``resize()`` function) -* reprs are different + - non-native byte-order objects -Speed -===== + - callbacks accepting by-value structures -Our ctypes implementation was created without putting to much effort into -making it fast. First of all most of it is written as pure-python code which -makes it slow. Obvious optimization would be to reimplement certain parts -of it at interp-level. Other, also very important, issue is that pypy's I/O -operations are generally slow. This is mostly due to model in which -unmanaged memory (outside of gc scope) must be the only one that goes to C -level. This is a huge simplifaction which allowed us to not worry about -that when developing moving gcs. At some point we will improve C-level -operations by either introducing pinning or by some other, yet undecided -means. + - expected semantics when ctypes types are subclassed + +Getting the code and test suites +================================= + +... Running example code -==================== +===================== You need a translation with ``--withmod-_rawffi`` in order to run any ctypes code. For most examples ``--allworkingmodules`` translation option @@ -116,6 +123,15 @@ The `stress tests`_ of Johnathan Hartley is also working. -.. _`pysqlite-ctypes`: XXX link +.. _`pysqlite-ctypes`: http://XXX-link .. _`pyglet`: http://pyglet.org/ .. _`stress tests`: http://tartley.com/?p=264 + + +ctypes configure +================= + +We also released `ctypes-configure`_, which is a package trying to overcome +the portability issues of ctypes-based code. + +.. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html From fijal at codespeak.net Fri Apr 4 19:14:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 19:14:05 +0200 (CEST) Subject: [pypy-svn] r53345 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080404171405.EA5CD16A8E7@codespeak.net> Author: fijal Date: Fri Apr 4 19:14:05 2008 New Revision: 53345 Modified: pypy/dist/pypy/lib/_ctypes/function.py Log: make this a static method Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Fri Apr 4 19:14:05 2008 @@ -134,7 +134,8 @@ return self._ptr return self.dll._handle.ptr(self.name, argshapes, resshape) - def _guess_argtypes(self, args): + @staticmethod + def _guess_argtypes(args): from _ctypes import _CData from ctypes import c_char_p, c_void_p, c_int, Array, Structure res = [] From fijal at codespeak.net Fri Apr 4 19:14:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 19:14:56 +0200 (CEST) Subject: [pypy-svn] r53346 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080404171456.2875516A8ED@codespeak.net> Author: fijal Date: Fri Apr 4 19:14:55 2008 New Revision: 53346 Modified: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py Log: unskip this test Modified: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py Fri Apr 4 19:14:55 2008 @@ -2,11 +2,8 @@ """ This test checks whether args wrapping behavior is correct """ import py - import sys -py.test.skip("FIXME") - from ctypes import * def test_wrap_args(): From fijal at codespeak.net Fri Apr 4 19:32:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 19:32:36 +0200 (CEST) Subject: [pypy-svn] r53347 - pypy/branch/jit-hotpath/pypy/jit/codegen/demo Message-ID: <20080404173236.99F6A16A8A9@codespeak.net> Author: fijal Date: Fri Apr 4 19:32:34 2008 New Revision: 53347 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/demo/conftest.py pypy/branch/jit-hotpath/pypy/jit/codegen/demo/support.py Log: adapt this to run on ia32 backend Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/demo/conftest.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/demo/conftest.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/demo/conftest.py Fri Apr 4 19:32:34 2008 @@ -11,7 +11,8 @@ help="choose a fixed random seed"), Option('--backend', action="store", default='llgraph', - choices=['llgraph', 'dump', 'ppc', 'i386', 'llvm', 'ppcfew'], + choices=['llgraph', 'dump', 'ppc', 'i386', 'ia32', 'llvm', + 'ppcfew'], dest="backend", help="select the backend to run the functions with"), Option('--nb-blocks', action="store", type="int", Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/demo/support.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/demo/support.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/demo/support.py Fri Apr 4 19:32:34 2008 @@ -20,6 +20,10 @@ from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp from pypy.jit.codegen.i386.codebuf import machine_code_dumper run_in_subprocess = True +elif demo_conftest.option.backend == 'ia32': + from pypy.jit.codegen.ia32.rgenop import RI386GenOp as RGenOp + from pypy.jit.codegen.i386.codebuf import machine_code_dumper + run_in_subprocess = True elif demo_conftest.option.backend == 'ppc': from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp run_in_subprocess = True From fijal at codespeak.net Fri Apr 4 19:35:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 19:35:04 +0200 (CEST) Subject: [pypy-svn] r53348 - pypy/branch/jit-hotpath/pypy/jit/codegen Message-ID: <20080404173504.9093B16A90A@codespeak.net> Author: fijal Date: Fri Apr 4 19:35:04 2008 New Revision: 53348 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py Log: adapt this a bit Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py Fri Apr 4 19:35:04 2008 @@ -7,6 +7,8 @@ class ProcessorAutodetectError(Exception): pass +x86_backend = 'i386' + def autodetect(): mach = None try: @@ -17,7 +19,7 @@ if not mach: platform = sys.platform.lower() if platform.startswith('win'): # assume an Intel Windows - return 'i386' + return x86_backend # assume we have 'uname' mach = os.popen('uname -m', 'r').read().strip() if not mach: @@ -25,12 +27,12 @@ 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', - 'i586': 'i386', - 'i686': 'i386', - 'i86pc': 'i386', # Solaris/Intel - 'x86': 'i386', # Apple + return {'i386': x86_backend, + 'i486': x86_backend, + 'i586': x86_backend, + 'i686': x86_backend, + 'i86pc': x86_backend, # Solaris/Intel + 'x86': x86_backend, # Apple 'Power Macintosh': 'ppc', }[mach] except KeyError: From pedronis at codespeak.net Fri Apr 4 19:39:58 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 19:39:58 +0200 (CEST) Subject: [pypy-svn] r53349 - in pypy/dist/pypy/lib/app_test: . ctypes Message-ID: <20080404173958.C14C216A91E@codespeak.net> Author: pedronis Date: Fri Apr 4 19:39:58 2008 New Revision: 53349 Added: pypy/dist/pypy/lib/app_test/test_ctypes_support.py - copied unchanged from r53346, pypy/dist/pypy/lib/app_test/ctypes/test_support.py Removed: pypy/dist/pypy/lib/app_test/ctypes/test_support.py Modified: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py pypy/dist/pypy/lib/app_test/ctypes/test_keepalive.py Log: clarify that these are pypy white-box tests ctypes_support is really pypy only, move it out Modified: pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_guess_argtypes.py Fri Apr 4 19:39:58 2008 @@ -8,7 +8,7 @@ def test_wrap_args(): if not hasattr(sys, 'pypy_translation_info'): - py.test.skip("whitebox test") + py.test.skip("pypy white-box test") from _ctypes.function import CFuncPtr guess = CFuncPtr._guess_argtypes Modified: pypy/dist/pypy/lib/app_test/ctypes/test_keepalive.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_keepalive.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_keepalive.py Fri Apr 4 19:39:58 2008 @@ -98,7 +98,7 @@ def test_primitive(self): if not hasattr(sys, 'pypy_translation_info'): - py.test.skip("whitebox test") + py.test.skip("pypy white-box test") assert c_char_p("abc")._objects['0']._buffer[0] == "a" assert c_int(3)._objects is None From pedronis at codespeak.net Fri Apr 4 19:45:45 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 19:45:45 +0200 (CEST) Subject: [pypy-svn] r53350 - in pypy/dist/pypy/lib/app_test: ctypes ctypes_tests Message-ID: <20080404174545.84DA116A926@codespeak.net> Author: pedronis Date: Fri Apr 4 19:45:45 2008 New Revision: 53350 Added: pypy/dist/pypy/lib/app_test/ctypes_tests/ - copied from r53349, pypy/dist/pypy/lib/app_test/ctypes/ Removed: pypy/dist/pypy/lib/app_test/ctypes/ Log: avoid dangerous name clash with the ctypes package itself From pedronis at codespeak.net Fri Apr 4 20:16:13 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 20:16:13 +0200 (CEST) Subject: [pypy-svn] r53351 - pypy/dist/pypy/doc Message-ID: <20080404181613.8A6F216A962@codespeak.net> Author: pedronis Date: Fri Apr 4 20:16:08 2008 New Revision: 53351 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: how to get the code an run the tests section Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Fri Apr 4 20:16:08 2008 @@ -91,11 +91,41 @@ Getting the code and test suites ================================= -... +A stable revision of PyPy containing the ctypes implementation can be checked out with subversion from: + +http://codespeak.net/svn/pypy/branch/ctypes-stable XXX make the branch + +The various tests can be run on Linux. + +If one goes inside the checkout it is possible to run ``_rawffi`` tests with:: + + $ cd pypy + $ python test_all.py module/_rawffi/ + +The ctypes implementation test suite is derived from the tests for +ctypes 1.0.2, we have skipped some tests corresponding to not +implemented features or implementation details, we have also added +some tests. + +To run the test suite a compiled pypy-c is required with the proper configuration. To build the required pypy-c one should inside the checkout:: + + $ cd pypy/translator/goal + $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --witmod-_rawffi + +this should produce a pypy-c executable in the ``goal`` directory. + +To run the tests then:: + + $ cd ../.. # back to pypy/ + $ ./translator/goal/pypy-c test_all.py lib/app_test/ctypes_tests + +There should be 255 passed and 36 skipped tests. Running example code ===================== +XXX not reviewed or tried yet + You need a translation with ``--withmod-_rawffi`` in order to run any ctypes code. For most examples ``--allworkingmodules`` translation option also makes sense. Known applications to run are `pysqlite-ctypes`_ and From fijal at codespeak.net Fri Apr 4 20:33:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 20:33:04 +0200 (CEST) Subject: [pypy-svn] r53352 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080404183304.CE2DA16A97E@codespeak.net> Author: fijal Date: Fri Apr 4 20:33:04 2008 New Revision: 53352 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: test for array of floats (passes on llgraph backend) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Fri Apr 4 20:33:04 2008 @@ -2208,6 +2208,51 @@ res = fnptr(21, -21, 0) assert res == 42 + def test_array_of_floats(self): + if self.RGenOpPacked is None: + py.test.skip("requires RGenOpPacked") + rgenop = self.RGenOpPacked() + A = lltype.GcArray(lltype.Float) + FUNC3 = lltype.FuncType([lltype.Float]*2 + [lltype.Signed], lltype.Float) + varsizealloctoken = rgenop.varsizeAllocToken(A) + arraytoken = rgenop.arrayToken(A) + float_kind = rgenop.kindToken(lltype.Float) + # ------------------------------------------------------------ + builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph( + rgenop.sigToken(FUNC3), 'float_array') + builder0.start_writing() + v3 = builder0.genop_malloc_varsize(varsizealloctoken, + rgenop.genconst(2)) + v4 = builder0.genop1('ptr_iszero', v3) + builder1 = builder0.jump_if_false(v4, [v2, v0, v3, v1]) + builder2 = builder0.pause_writing([]) + builder1.start_writing() + builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(0), v0) + builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(1), v1) + v5 = builder1.genop_getarrayitem(arraytoken, v3, v2) + v6 = builder1.genop_getarraysize(arraytoken, v3) + v6b = builder1.genop1('cast_int_to_float', v6) + v7 = builder1.genop2('float_mul', v5, v6b) + builder3 = builder1.pause_writing([v7]) + builder3.start_writing() + args_gv = [v7] + label0 = builder3.enter_next_block(args_gv) + [v8] = args_gv + builder4 = builder3.pause_writing([v8]) + builder2.start_writing() + builder2.finish_and_goto([rgenop.genconst(-1.0)], label0) + builder4.start_writing() + args_gv = [v8] + label1 = builder4.enter_next_block(args_gv) + [v9] = args_gv + builder4.finish_and_return(rgenop.sigToken(FUNC3), v9) + builder0.end() + + fnptr = self.cast_whatever(gv_callable, [lltype.Float]*2 + + [lltype.Signed], lltype.Float) + res = fnptr(3.1, -3.2, 1) + assert res == -6.4 + def test_interior_access(self): # for assembler backends, the 'interior' lloperations can be # simply expressed as a sequence of genop_getsubstruct and From cfbolz at codespeak.net Fri Apr 4 20:42:15 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Apr 2008 20:42:15 +0200 (CEST) Subject: [pypy-svn] r53353 - pypy/dist/pypy/doc Message-ID: <20080404184215.1CE8616A963@codespeak.net> Author: cfbolz Date: Fri Apr 4 20:42:14 2008 New Revision: 53353 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: small problems Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Fri Apr 4 20:42:14 2008 @@ -16,7 +16,7 @@ PyPy's implementation internally uses `libffi`_ like CPython's ctypes. In our implementation as much as possible of the code is written in -full Python, not RPython, In CPython's situation, the equivalent would +full Python, not RPython. In CPython's situation, the equivalent would be to write as little as possible code in C. We essentially favored rapid experimentation over worrying about speed for this first trial implementation. This allowed to provide a working implementation with @@ -110,7 +110,7 @@ To run the test suite a compiled pypy-c is required with the proper configuration. To build the required pypy-c one should inside the checkout:: $ cd pypy/translator/goal - $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --witmod-_rawffi + $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --withmod-_rawffi this should produce a pypy-c executable in the ``goal`` directory. @@ -161,7 +161,7 @@ ctypes configure ================= -We also released `ctypes-configure`_, which is a package trying to overcome -the portability issues of ctypes-based code. +We also released `ctypes-configure`_, which is an experimental package trying to +approach the portability issues of ctypes-based code. .. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html From pedronis at codespeak.net Fri Apr 4 21:04:55 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 21:04:55 +0200 (CEST) Subject: [pypy-svn] r53355 - pypy/dist/pypy/doc Message-ID: <20080404190455.45F9416A982@codespeak.net> Author: pedronis Date: Fri Apr 4 21:04:54 2008 New Revision: 53355 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: that is going to be a tag Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Fri Apr 4 21:04:54 2008 @@ -93,7 +93,7 @@ A stable revision of PyPy containing the ctypes implementation can be checked out with subversion from: -http://codespeak.net/svn/pypy/branch/ctypes-stable XXX make the branch +http://codespeak.net/svn/pypy/tag/ctypes-stable XXX make the tag The various tests can be run on Linux. From fijal at codespeak.net Fri Apr 4 21:14:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 21:14:28 +0200 (CEST) Subject: [pypy-svn] r53356 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080404191428.AA3DD16A99D@codespeak.net> Author: fijal Date: Fri Apr 4 21:14:26 2008 New Revision: 53356 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: make tests more verbose - setarrayitem with constant Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Fri Apr 4 21:14:26 2008 @@ -2179,13 +2179,15 @@ rgenop.sigToken(FUNC3), 'generated') builder0.start_writing() v3 = builder0.genop_malloc_varsize(varsizealloctoken, - rgenop.genconst(2)) + rgenop.genconst(3)) v4 = builder0.genop1('ptr_iszero', v3) builder1 = builder0.jump_if_false(v4, [v2, v0, v3, v1]) builder2 = builder0.pause_writing([]) builder1.start_writing() builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(0), v0) builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(1), v1) + builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(2), + rgenop.genconst(123)) v5 = builder1.genop_getarrayitem(arraytoken, v3, v2) v6 = builder1.genop_getarraysize(arraytoken, v3) v7 = builder1.genop2('int_mul', v5, v6) @@ -2206,7 +2208,9 @@ fnptr = self.cast(gv_callable, 3) res = fnptr(21, -21, 0) - assert res == 42 + assert res == 63 + res = fnptr(21, -21, 2) + assert res == 123 * 3 def test_array_of_floats(self): if self.RGenOpPacked is None: @@ -2222,13 +2226,15 @@ rgenop.sigToken(FUNC3), 'float_array') builder0.start_writing() v3 = builder0.genop_malloc_varsize(varsizealloctoken, - rgenop.genconst(2)) + rgenop.genconst(3)) v4 = builder0.genop1('ptr_iszero', v3) builder1 = builder0.jump_if_false(v4, [v2, v0, v3, v1]) builder2 = builder0.pause_writing([]) builder1.start_writing() builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(0), v0) builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(1), v1) + builder1.genop_setarrayitem(arraytoken, v3, rgenop.genconst(2), + rgenop.genconst(2.3)) v5 = builder1.genop_getarrayitem(arraytoken, v3, v2) v6 = builder1.genop_getarraysize(arraytoken, v3) v6b = builder1.genop1('cast_int_to_float', v6) @@ -2251,7 +2257,9 @@ fnptr = self.cast_whatever(gv_callable, [lltype.Float]*2 + [lltype.Signed], lltype.Float) res = fnptr(3.1, -3.2, 1) - assert res == -6.4 + assert res == -3.2 * 3 + res = fnptr(3.1, -3.2, 2) + assert res == 2.3*3 def test_interior_access(self): # for assembler backends, the 'interior' lloperations can be From fijal at codespeak.net Fri Apr 4 21:42:31 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 21:42:31 +0200 (CEST) Subject: [pypy-svn] r53357 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080404194231.7F02216A9E7@codespeak.net> Author: fijal Date: Fri Apr 4 21:42:29 2008 New Revision: 53357 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: start of refactoring of get/set arrayitem. test for floats fails, but thats not very surprising Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Fri Apr 4 21:42:29 2008 @@ -66,6 +66,9 @@ def operand(self, builder): raise NotImplementedError + def movetonewaddr(self, builder, arg): + raise NotImplementedError + def __repr__(self): return self.token + 'var@%d' % (self.stackpos,) @@ -82,6 +85,11 @@ def newvar(self, builder): return builder.returnintvar(self.operand(builder)) + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(eax, self.operand(builder)) + builder.mc.MOV(dstop, eax) + class AddressVar(IntVar): ll_type = llmemory.Address token = 'a' @@ -95,6 +103,11 @@ def newvar(self, builder): return builder.returnboolvar(self.operand(builder)) + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(eax, self.operand(builder)) + builder.mc.MOV(destop, al) + ll_type = lltype.Bool token = 'b' SIZE = 1 @@ -107,6 +120,14 @@ raise NotImplementedError("This requires moving around float mem") return builder.returnfloatvar(self.operand(builder)) + def movetonewaddr(self, builder, arg): + dstop1 = builder.itemaddr(arg) + dstop2 = builder.itemaddr(arg, WORD) + builder.mc.MOV(eax, builder.stack_access(self.stackpos)) + builder.mc.MOV(dstop1, eax) + builder.mc.MOV(eax, builder.stack_access(self.stackpos - 1)) + builder.mc.MOV(dstop2, eax) + ll_type = lltype.Float token = 'f' SIZE = 2 @@ -185,6 +206,9 @@ except TypeError: # from Symbolics return "const=%r" % (self.value,) + def movetonewaddr(self, builder, addr): + raise NotImplementedError + def repr(self): return "const=$%s" % (self.value,) @@ -194,6 +218,10 @@ def newvar(self, builder): return builder.returnintvar(self.operand(builder)) + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(dstop, self.operand(builder)) + class FloatConst(Const): SIZE = 2 # XXX hack for annotator @@ -208,11 +236,23 @@ self.rawbuf[0] = floatval def newvar(self, builder): - return builder.newfloatfrommem(self.rawbuf) + return builder.newfloatfrommem(None, None, 0, + rffi.cast(rffi.INT, self.rawbuf)) def operand(self, builder): return heap64(rffi.cast(rffi.INT, self.rawbuf)) + def movetonewaddr(self, builder, arg): + dstop1 = builder.itemaddr(arg) + dstop2 = builder.itemaddr(arg, WORD) + builder.mc.MOV(dstop1, imm(rffi.cast(rffi.INTP, self.rawbuf)[0])) + builder.mc.MOV(dstop2, imm(rffi.cast(rffi.INTP, self.rawbuf)[1])) + + def repr(self): + return "const=$%s" % (self.rawbuf[0],) + + __repr__ = repr + class BoolConst(Const): SIZE = 1 @@ -222,13 +262,17 @@ def newvar(self, builder): return builder.returnboolvar(self.operand(builder)) + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(dstop, self.operand(builder)) + ##class FnPtrConst(IntConst): ## def __init__(self, value, mc): ## self.value = value ## self.mc = mc # to keep it alive -class AddrConst(GenConst): +class AddrConst(IntConst): SIZE = 1 def __init__(self, addr): @@ -240,10 +284,6 @@ def newvar(self, builder): return builder.returnintvar(self.operand(builder)) - def nonimmoperand(self, builder, tmpregister): - builder.mc.MOV(tmpregister, self.operand(builder)) - return tmpregister - @specialize.arg(1) def revealconst(self, T): if T is llmemory.Address: @@ -533,38 +573,49 @@ self.mc.LEA(eax, mem(edx, offset)) return self.returnintvar(eax) - def itemaddr(self, base, arraytoken, gv_index): - # uses ecx + def _compute_itemaddr(self, arg, addoffset=0): + base, arraytoken, gv_index = arg lengthoffset, startoffset, itemoffset = arraytoken - if itemoffset == 1: - memSIBx = memSIB8 - else: - memSIBx = memSIB if isinstance(gv_index, IntConst): startoffset += itemoffset * gv_index.value - op = memSIBx(base, None, 0, startoffset) + return (base, None, 0, startoffset + addoffset) elif itemoffset in SIZE2SHIFT: self.mc.MOV(ecx, gv_index.operand(self)) - op = memSIBx(base, ecx, SIZE2SHIFT[itemoffset], startoffset) + return (base, ecx, SIZE2SHIFT[itemoffset], startoffset + + addoffset) else: self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - op = memSIBx(base, ecx, 0, startoffset) - return op + return (base, ecx, 0, startoffset + addoffset) + + def itemaddr(self, arg, addoffset=0): + # uses ecx + base, arraytoken, gv_index = arg + lengthoffset, startoffset, itemoffset = arraytoken + if itemoffset == 1: + memSIBx = memSIB8 + else: + memSIBx = memSIB + base, reg, shift, ofs = self._compute_itemaddr(arg, addoffset) + return memSIBx(base, reg, shift, ofs) def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) - op = self.itemaddr(edx, arraytoken, gv_index) _, _, itemsize = arraytoken - if itemsize != WORD: - if itemsize > 2: - raise NotImplementedError("itemsize != 1,2,4") + if itemsize > WORD: + # XXX assert not different type than float, probably + # need to sneak one in arraytoken + base, reg, shift, ofs = self._compute_itemaddr((edx, arraytoken, + gv_index)) + return self.newfloatfrommem(base, reg, shift, ofs) + op = self.itemaddr((edx, arraytoken, gv_index)) + if itemsize < WORD: self.mc.MOVZX(eax, op) op = eax return self.returnintvar(op) def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) - op = self.itemaddr(edx, arraytoken, gv_index) + op = self.itemaddr((edx, arraytoken, gv_index)) self.mc.LEA(eax, op) return self.returnintvar(eax) @@ -574,19 +625,23 @@ return self.returnintvar(mem(edx, lengthoffset)) def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): - self.mc.MOV(eax, gv_value.operand(self)) - self.mc.MOV(edx, gv_ptr.operand(self)) - destop = self.itemaddr(edx, arraytoken, gv_index) _, _, itemsize = arraytoken - if itemsize != WORD: - if itemsize == 1: - self.mc.MOV(destop, al) - return - elif itemsize == 2: - self.mc.o16() # followed by the MOV below - else: - raise NotImplementedError("setarrayitme for fieldsize != 1,2,4") - self.mc.MOV(destop, eax) + self.mc.MOV(edx, gv_ptr.operand(self)) + destaddr = self.itemaddr((edx, arraytoken, gv_index)) + gv_value.movetonewaddr(self, (edx, arraytoken, gv_index)) + #if itemsize <= WORD: + # self.mc.MOV(eax, gv_value.operand(self)) + # if itemsize != WORD: + # if itemsize == 1: + # self.mc.MOV(destop, al) + # return + # elif itemsize == 2: + # self.mc.o16() # followed by the MOV below + # else: + # raise NotImplementedError("setarrayitme for fieldsize == 3") + # self.mc.MOV(destop, eax) + #else: + # self.move_bigger_value(destop, gv_value, itemsize) def genop_malloc_fixedsize(self, size): # XXX boehm only, no atomic/non atomic distinction for now @@ -597,7 +652,7 @@ 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) + op_size = self.itemaddr((None, varsizealloctoken, gv_size)) self.mc.LEA(edx, op_size) self.push(edx) self.mc.CALL(rel32(gc_malloc_fnaddr())) @@ -745,12 +800,10 @@ raise NotImplementedError("Return float var not on fp stack") return res - def newfloatfrommem(self, rawbuf): - # XXX obscure pointer arithmetics on ints. Think how do to it - # better + def newfloatfrommem(self, base, reg, shift, ofs): res = FloatVar(self.stackdepth + 1) - self.mc.PUSH(heap(rffi.cast(rffi.INT, rawbuf))) - self.mc.PUSH(heap(rffi.cast(rffi.INT, rawbuf) + WORD)) + self.mc.PUSH(memSIB(base, reg, shift, ofs)) + self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) self.stackdepth += 2 return res @@ -1145,7 +1198,7 @@ # ____________________________________________________________ def _remap_bigger_values(args_gv, arg_positions): - """ This function cheates and changes all FloatVars into double + """ This function cheats and changes all FloatVars into double IntVars. This might be probably optimized in some way in order to provide greater performance, but should be enough for now """ @@ -1159,11 +1212,16 @@ res_positions.append(pos) else: assert gv.SIZE == 2 - assert isinstance(gv, FloatVar) - res_gv.append(IntVar(gv.stackpos)) - res_gv.append(IntVar(gv.stackpos - 1)) + if isinstance(gv, FloatVar): + res_gv.append(IntVar(gv.stackpos)) + res_gv.append(IntVar(gv.stackpos - 1)) + else: + assert isinstance(gv, FloatConst) + buf = rffi.cast(rffi.INTP, gv.rawbuf) + res_gv.append(IntConst(buf[0])) + res_gv.append(IntConst(buf[1])) res_positions.append(pos) - res_positions.append(pos - 1) + res_positions.append(pos - 1) # no repeats please if not objectmodel.we_are_translated(): assert sorted(dict.fromkeys(res_positions).keys()) == sorted(res_positions) @@ -1468,9 +1526,9 @@ arrayfield_offset+items_offset, item_size) - @staticmethod + @classmethod @specialize.memo() - def arrayToken(A): + def arrayToken(cls, A): return (llmemory.ArrayLengthOffset(A), llmemory.ArrayItemsOffset(A), llmemory.ItemOffset(A.OF)) From fijal at codespeak.net Fri Apr 4 21:52:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 21:52:04 +0200 (CEST) Subject: [pypy-svn] r53358 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080404195204.BF41016A9B9@codespeak.net> Author: fijal Date: Fri Apr 4 21:52:04 2008 New Revision: 53358 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Boom, test is passing :) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Fri Apr 4 21:52:04 2008 @@ -802,8 +802,8 @@ def newfloatfrommem(self, base, reg, shift, ofs): res = FloatVar(self.stackdepth + 1) - self.mc.PUSH(memSIB(base, reg, shift, ofs)) self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) + self.mc.PUSH(memSIB(base, reg, shift, ofs)) self.stackdepth += 2 return res From pedronis at codespeak.net Fri Apr 4 21:54:07 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 4 Apr 2008 21:54:07 +0200 (CEST) Subject: [pypy-svn] r53359 - pypy/branch/ctypes-stable Message-ID: <20080404195407.DC89116A9C0@codespeak.net> Author: pedronis Date: Fri Apr 4 21:54:04 2008 New Revision: 53359 Added: pypy/branch/ctypes-stable/ - copied from r53355, pypy/dist/ Log: making a branch to the baseline for the stable ctypes delivery tag From fijal at codespeak.net Fri Apr 4 21:56:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 21:56:02 +0200 (CEST) Subject: [pypy-svn] r53360 - pypy/branch/jit-hotpath/pypy/jit/codegen Message-ID: <20080404195602.4633516A9F3@codespeak.net> Author: fijal Date: Fri Apr 4 21:56:01 2008 New Revision: 53360 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py Log: revert last checkin here Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py Fri Apr 4 21:56:01 2008 @@ -7,8 +7,6 @@ class ProcessorAutodetectError(Exception): pass -x86_backend = 'i386' - def autodetect(): mach = None try: @@ -19,7 +17,7 @@ if not mach: platform = sys.platform.lower() if platform.startswith('win'): # assume an Intel Windows - return x86_backend + return 'i386' # assume we have 'uname' mach = os.popen('uname -m', 'r').read().strip() if not mach: @@ -27,12 +25,12 @@ 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': x86_backend, - 'i486': x86_backend, - 'i586': x86_backend, - 'i686': x86_backend, - 'i86pc': x86_backend, # Solaris/Intel - 'x86': x86_backend, # Apple + return {'i386': 'i386', + 'i486': 'i386', + 'i586': 'i386', + 'i686': 'i386', + 'i86pc': 'i386', # Solaris/Intel + 'x86': 'i386', # Apple 'Power Macintosh': 'ppc', }[mach] except KeyError: From fijal at codespeak.net Fri Apr 4 21:56:25 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 21:56:25 +0200 (CEST) Subject: [pypy-svn] r53361 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080404195625.D024216A9F3@codespeak.net> Author: fijal Date: Fri Apr 4 21:56:25 2008 New Revision: 53361 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: make annotator happier Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Fri Apr 4 21:56:25 2008 @@ -1534,18 +1534,15 @@ llmemory.ItemOffset(A.OF)) @staticmethod - @specialize.arg(0) - def map_arg(arg): - if isinstance(arg, lltype.Ptr): - return llmemory.Address - return arg - - @classmethod @specialize.memo() - def sigToken(cls, FUNCTYPE): - return ([LL_TO_GENVAR[cls.map_arg(arg)] for arg in FUNCTYPE.ARGS if arg + def sigToken(FUNCTYPE): + def map_arg(arg): + if isinstance(arg, lltype.Ptr): + return llmemory.Address + return arg + return ([LL_TO_GENVAR[map_arg(arg)] for arg in FUNCTYPE.ARGS if arg is not lltype.Void], - LL_TO_GENVAR[cls.map_arg(FUNCTYPE.RESULT)]) + LL_TO_GENVAR[map_arg(FUNCTYPE.RESULT)]) @staticmethod def erasedType(T): From fijal at codespeak.net Fri Apr 4 22:52:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Apr 2008 22:52:46 +0200 (CEST) Subject: [pypy-svn] r53363 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080404205246.1F35216AA14@codespeak.net> Author: fijal Date: Fri Apr 4 22:52:45 2008 New Revision: 53363 Added: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (contents, props changed) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Split rgenop into two files, it looks nicer IMO Added: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- (empty file) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Fri Apr 4 22:52:45 2008 @@ -0,0 +1,271 @@ + +from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch +from pypy.rpython.lltypesystem import lltype, rffi, llmemory +from pypy.rlib.unroll import unrolling_iterable +from pypy.rlib.objectmodel import specialize +from pypy.jit.codegen.i386.ri386 import * + +WORD = 4 + +class Var(GenVar): + token = 'x' + # XXX hack for annotator + stackpos = 0 + + def __init__(self, stackpos): + # 'stackpos' is an index relative to the pushed arguments + # (where N is the number of arguments of the function + # and B is a small integer for stack alignment purposes): + # + # 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 + + def nonimmoperand(self, builder, tmpregister): + return self.operand(builder) + + def operand(self, builder): + raise NotImplementedError + + def movetonewaddr(self, builder, arg): + raise NotImplementedError + + def __repr__(self): + return self.token + 'var@%d' % (self.stackpos,) + + repr = __repr__ + +class IntVar(Var): + ll_type = lltype.Signed + token = 'i' + SIZE = 1 + + def operand(self, builder): + return builder.stack_access(self.stackpos) + + def newvar(self, builder): + return builder.returnintvar(self.operand(builder)) + + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(eax, self.operand(builder)) + builder.mc.MOV(dstop, eax) + +class AddressVar(IntVar): + ll_type = llmemory.Address + token = 'a' + SIZE = 1 + +class BoolVar(Var): + # represents a boolean as an integer which *must* be exactly 0 or 1 + def operand(self, builder): + return builder.stack_access(self.stackpos) + + def newvar(self, builder): + return builder.returnboolvar(self.operand(builder)) + + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(eax, self.operand(builder)) + builder.mc.MOV(destop, al) + + ll_type = lltype.Bool + token = 'b' + SIZE = 1 + +class FloatVar(Var): + def operand(self, builder): + return builder.stack_access64(self.stackpos) + + def newvar(self, builder): + raise NotImplementedError("This requires moving around float mem") + return builder.returnfloatvar(self.operand(builder)) + + def movetonewaddr(self, builder, arg): + dstop1 = builder.itemaddr(arg) + dstop2 = builder.itemaddr(arg, WORD) + builder.mc.MOV(eax, builder.stack_access(self.stackpos)) + builder.mc.MOV(dstop1, eax) + builder.mc.MOV(eax, builder.stack_access(self.stackpos - 1)) + builder.mc.MOV(dstop2, eax) + + ll_type = lltype.Float + token = 'f' + SIZE = 2 + +LL_TO_GENVAR = {} +TOKEN_TO_GENVAR = {} +TOKEN_TO_SIZE = {} +for value in [IntVar, FloatVar, BoolVar, AddressVar]: + assert hasattr(value, 'll_type') + LL_TO_GENVAR[value.ll_type] = value.token + TOKEN_TO_GENVAR[value.token] = value + TOKEN_TO_SIZE[value.token] = value.SIZE +LL_TO_GENVAR[lltype.Unsigned] = 'i' +LL_TO_GENVAR[lltype.Char] = 'i' +# we might want to have different value for chare +# but I see no point now +LL_TO_GENVAR[lltype.Void] = 'v' + +UNROLLING_TOKEN_TO_GENVAR = unrolling_iterable(TOKEN_TO_GENVAR.items()) + +def token_to_genvar(i, arg): + for tok, value in UNROLLING_TOKEN_TO_GENVAR: + if tok == i: + return value(arg) + +##class Const(GenConst): + +## def revealconst(self, TYPE): +## if isinstance(self, IntConst): +## self.revealconst_int(TYPE) +## elif isinstance(self, PtrConst): +## self.revealconst_ptr(TYPE) + +## if isinstance(TYPE, lltype.Ptr): +## if isinstance(self, PtrConst): +## return self.revealconst_ptr(TYPE) +## el +## return self.revealconst_ptr(TYPE) +## elif TYPE is lltype.Float: +## assert isinstance(self, DoubleConst) +## return self.revealconst_double() +## else: +## assert isinstance(TYPE, lltype.Primitive) +## assert TYPE is not lltype.Void, "cannot make red boxes of voids" +## assert isinstance(self, IntConst) +## return self.revealconst_primitive(TYPE) +## return self.value +## revealconst._annspecialcase_ = 'specialize:arg(1)' + + +class Const(GenConst): + + def __init__(self, value): + self.value = value + + def operand(self, builder): + return imm(self.value) + + def nonimmoperand(self, builder, tmpregister): + builder.mc.MOV(tmpregister, self.operand(builder)) + return tmpregister + + @specialize.arg(1) + def revealconst(self, T): + if isinstance(T, lltype.Ptr): + 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) + + def __repr__(self): + "NOT_RPYTHON" + try: + return "const=%s" % (imm(self.value).assembler(),) + except TypeError: # from Symbolics + return "const=%r" % (self.value,) + + def movetonewaddr(self, builder, addr): + raise NotImplementedError + + def repr(self): + return "const=$%s" % (self.value,) + +class IntConst(Const): + SIZE = 1 + + def newvar(self, builder): + return builder.returnintvar(self.operand(builder)) + + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(dstop, self.operand(builder)) + +class FloatConst(Const): + SIZE = 2 + # XXX hack for annotator + rawbuf = lltype.nullptr(rffi.DOUBLEP.TO) + + def __init__(self, floatval): + # XXX we should take more care who is creating this and + # eventually release this buffer + # never moves and never dies + self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', + immortal=True) + self.rawbuf[0] = floatval + + def newvar(self, builder): + return builder.newfloatfrommem(None, None, 0, + rffi.cast(rffi.INT, self.rawbuf)) + + def operand(self, builder): + return heap64(rffi.cast(rffi.INT, self.rawbuf)) + + def movetonewaddr(self, builder, arg): + dstop1 = builder.itemaddr(arg) + dstop2 = builder.itemaddr(arg, WORD) + builder.mc.MOV(dstop1, imm(rffi.cast(rffi.INTP, self.rawbuf)[0])) + builder.mc.MOV(dstop2, imm(rffi.cast(rffi.INTP, self.rawbuf)[1])) + + def repr(self): + return "const=$%s" % (self.rawbuf[0],) + + __repr__ = repr + +class BoolConst(Const): + SIZE = 1 + + def operand(self, builder): + return imm8(self.value) + + def newvar(self, builder): + return builder.returnboolvar(self.operand(builder)) + + def movetonewaddr(self, builder, arg): + dstop = builder.itemaddr(arg) + builder.mc.MOV(dstop, self.operand(builder)) + +##class FnPtrConst(IntConst): +## def __init__(self, value, mc): +## self.value = value +## self.mc = mc # to keep it alive + + +class AddrConst(IntConst): + SIZE = 1 + + def __init__(self, addr): + self.addr = addr + + def operand(self, builder): + return imm(llmemory.cast_adr_to_int(self.addr)) + + def newvar(self, builder): + return builder.returnintvar(self.operand(builder)) + + @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" + + def __repr__(self): + "NOT_RPYTHON" + return "const=%r" % (self.addr,) + + def repr(self): + return "const=<0x%x>" % (llmemory.cast_adr_to_int(self.addr),) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Fri Apr 4 22:52:45 2008 @@ -1,16 +1,16 @@ import sys, py, os from pypy.rlib.objectmodel import specialize -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.codegen.i386.ri386 import * 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 -from pypy.rlib.unroll import unrolling_iterable from pypy.rpython.annlowlevel import llhelper -from pypy.rpython.lltypesystem import rffi +from pypy.jit.codegen.ia32.objmodel import IntVar, FloatVar, Var,\ + BoolVar, IntConst, AddrConst, BoolConst, FloatConst,\ + LL_TO_GENVAR, TOKEN_TO_SIZE, token_to_genvar, WORD -WORD = 4 DEBUG_CALL_ALIGN = True if sys.platform == 'darwin': CALL_ALIGN = 4 @@ -39,269 +39,6 @@ p = cast(c_void_p(addr), POINTER(c_int)) p[0] = value -class Var(GenVar): - token = 'x' - # XXX hack for annotator - stackpos = 0 - - def __init__(self, stackpos): - # 'stackpos' is an index relative to the pushed arguments - # (where N is the number of arguments of the function - # and B is a small integer for stack alignment purposes): - # - # 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 - - def nonimmoperand(self, builder, tmpregister): - return self.operand(builder) - - def operand(self, builder): - raise NotImplementedError - - def movetonewaddr(self, builder, arg): - raise NotImplementedError - - def __repr__(self): - return self.token + 'var@%d' % (self.stackpos,) - - repr = __repr__ - -class IntVar(Var): - ll_type = lltype.Signed - token = 'i' - SIZE = 1 - - def operand(self, builder): - return builder.stack_access(self.stackpos) - - def newvar(self, builder): - return builder.returnintvar(self.operand(builder)) - - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) - builder.mc.MOV(eax, self.operand(builder)) - builder.mc.MOV(dstop, eax) - -class AddressVar(IntVar): - ll_type = llmemory.Address - token = 'a' - SIZE = 1 - -class BoolVar(Var): - # represents a boolean as an integer which *must* be exactly 0 or 1 - def operand(self, builder): - return builder.stack_access(self.stackpos) - - def newvar(self, builder): - return builder.returnboolvar(self.operand(builder)) - - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) - builder.mc.MOV(eax, self.operand(builder)) - builder.mc.MOV(destop, al) - - ll_type = lltype.Bool - token = 'b' - SIZE = 1 - -class FloatVar(Var): - def operand(self, builder): - return builder.stack_access64(self.stackpos) - - def newvar(self, builder): - raise NotImplementedError("This requires moving around float mem") - return builder.returnfloatvar(self.operand(builder)) - - def movetonewaddr(self, builder, arg): - dstop1 = builder.itemaddr(arg) - dstop2 = builder.itemaddr(arg, WORD) - builder.mc.MOV(eax, builder.stack_access(self.stackpos)) - builder.mc.MOV(dstop1, eax) - builder.mc.MOV(eax, builder.stack_access(self.stackpos - 1)) - builder.mc.MOV(dstop2, eax) - - ll_type = lltype.Float - token = 'f' - SIZE = 2 - -LL_TO_GENVAR = {} -TOKEN_TO_GENVAR = {} -TOKEN_TO_SIZE = {} -for value in [IntVar, FloatVar, BoolVar, AddressVar]: - assert hasattr(value, 'll_type') - LL_TO_GENVAR[value.ll_type] = value.token - TOKEN_TO_GENVAR[value.token] = value - TOKEN_TO_SIZE[value.token] = value.SIZE -LL_TO_GENVAR[lltype.Unsigned] = 'i' -LL_TO_GENVAR[lltype.Char] = 'i' -# we might want to have different value for chare -# but I see no point now -LL_TO_GENVAR[lltype.Void] = 'v' - -UNROLLING_TOKEN_TO_GENVAR = unrolling_iterable(TOKEN_TO_GENVAR.items()) - -def token_to_genvar(i, arg): - for tok, value in UNROLLING_TOKEN_TO_GENVAR: - if tok == i: - return value(arg) - -##class Const(GenConst): - -## def revealconst(self, TYPE): -## if isinstance(self, IntConst): -## self.revealconst_int(TYPE) -## elif isinstance(self, PtrConst): -## self.revealconst_ptr(TYPE) - -## if isinstance(TYPE, lltype.Ptr): -## if isinstance(self, PtrConst): -## return self.revealconst_ptr(TYPE) -## el -## return self.revealconst_ptr(TYPE) -## elif TYPE is lltype.Float: -## assert isinstance(self, DoubleConst) -## return self.revealconst_double() -## else: -## assert isinstance(TYPE, lltype.Primitive) -## assert TYPE is not lltype.Void, "cannot make red boxes of voids" -## assert isinstance(self, IntConst) -## return self.revealconst_primitive(TYPE) -## return self.value -## revealconst._annspecialcase_ = 'specialize:arg(1)' - - -class Const(GenConst): - - def __init__(self, value): - self.value = value - - def operand(self, builder): - return imm(self.value) - - def nonimmoperand(self, builder, tmpregister): - builder.mc.MOV(tmpregister, self.operand(builder)) - return tmpregister - - @specialize.arg(1) - def revealconst(self, T): - if isinstance(T, lltype.Ptr): - 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) - - def __repr__(self): - "NOT_RPYTHON" - try: - return "const=%s" % (imm(self.value).assembler(),) - except TypeError: # from Symbolics - return "const=%r" % (self.value,) - - def movetonewaddr(self, builder, addr): - raise NotImplementedError - - def repr(self): - return "const=$%s" % (self.value,) - -class IntConst(Const): - SIZE = 1 - - def newvar(self, builder): - return builder.returnintvar(self.operand(builder)) - - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) - builder.mc.MOV(dstop, self.operand(builder)) - -class FloatConst(Const): - SIZE = 2 - # XXX hack for annotator - rawbuf = lltype.nullptr(rffi.DOUBLEP.TO) - - def __init__(self, floatval): - # XXX we should take more care who is creating this and - # eventually release this buffer - # never moves and never dies - self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', - immortal=True) - self.rawbuf[0] = floatval - - def newvar(self, builder): - return builder.newfloatfrommem(None, None, 0, - rffi.cast(rffi.INT, self.rawbuf)) - - def operand(self, builder): - return heap64(rffi.cast(rffi.INT, self.rawbuf)) - - def movetonewaddr(self, builder, arg): - dstop1 = builder.itemaddr(arg) - dstop2 = builder.itemaddr(arg, WORD) - builder.mc.MOV(dstop1, imm(rffi.cast(rffi.INTP, self.rawbuf)[0])) - builder.mc.MOV(dstop2, imm(rffi.cast(rffi.INTP, self.rawbuf)[1])) - - def repr(self): - return "const=$%s" % (self.rawbuf[0],) - - __repr__ = repr - -class BoolConst(Const): - SIZE = 1 - - def operand(self, builder): - return imm8(self.value) - - def newvar(self, builder): - return builder.returnboolvar(self.operand(builder)) - - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) - builder.mc.MOV(dstop, self.operand(builder)) - -##class FnPtrConst(IntConst): -## def __init__(self, value, mc): -## self.value = value -## self.mc = mc # to keep it alive - - -class AddrConst(IntConst): - SIZE = 1 - - def __init__(self, addr): - self.addr = addr - - def operand(self, builder): - return imm(llmemory.cast_adr_to_int(self.addr)) - - def newvar(self, builder): - return builder.returnintvar(self.operand(builder)) - - @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" - - def __repr__(self): - "NOT_RPYTHON" - return "const=%r" % (self.addr,) - - def repr(self): - return "const=<0x%x>" % (llmemory.cast_adr_to_int(self.addr),) - class Label(GenLabel): From jared.grubb at codespeak.net Fri Apr 4 23:43:52 2008 From: jared.grubb at codespeak.net (jared.grubb at codespeak.net) Date: Fri, 4 Apr 2008 23:43:52 +0200 (CEST) Subject: [pypy-svn] r53365 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080404214352.792F016AA9F@codespeak.net> Author: jared.grubb Date: Fri Apr 4 23:43:51 2008 New Revision: 53365 Added: pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py (contents, props changed) Removed: pypy/dist/pypy/rlib/parsing/test/testoutput1.pickle pypy/dist/pypy/rlib/parsing/test/testoutput7.pickle Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Log: Move PCRE regex tests into a py file rather than pickle file Added: pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py Fri Apr 4 23:43:51 2008 @@ -0,0 +1,385 @@ +# Auto-generated file of regular expressions from PCRE library + +# The PCRE library is distributed under the BSD license. We have borrowed some +# of the regression tests (the ones that fit under the DFA scope) in order to +# exercise our regex implementation. Those tests are distributed under PCRE's +# BSD license. Here is the text: + +# PCRE LICENCE +# ------------ +# +# PCRE is a library of functions to support regular expressions whose syntax +# and semantics are as close as possible to those of the Perl 5 language. +# +# Release 7 of PCRE is distributed under the terms of the "BSD" licence, as +# specified below. The documentation for PCRE, supplied in the "doc" +# directory, is distributed under the same terms as the software itself. +# +# The basic library functions are written in C and are freestanding. Also +# included in the distribution is a set of C++ wrapper functions. +# +# THE BASIC LIBRARY FUNCTIONS +# --------------------------- +# +# Written by: Philip Hazel +# Email local part: ph10 +# Email domain: cam.ac.uk +# +# University of Cambridge Computing Service, +# Cambridge, England. +# +# Copyright (c) 1997-2008 University of Cambridge +# All rights reserved. +# +# THE C++ WRAPPER FUNCTIONS +# ------------------------- +# +# Contributed by: Google Inc. +# +# Copyright (c) 2007-2008, Google Inc. +# All rights reserved. +# +# THE "BSD" LICENCE +# ----------------- +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of the University of Cambridge nor the name of Google +# Inc. nor the names of their contributors may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# End + +suite = [] +suite.append(['abc', '', [('abc', ' 0: abc')]]) +suite.append(['ab*c', '', [('abc', ' 0: abc'), ('abbbbc', ' 0: abbbbc'), ('ac', ' 0: ac')]]) +suite.append(['ab+c', '', [('abc', ' 0: abc'), ('abbbbbbc', ' 0: abbbbbbc'), ('*** Failers', None), ('ac', None), ('ab', None)]]) +suite.append(['a*', '', [('a', ' 0: a'), ('aaaaaaaaaaaaaaaaa', ' 0: aaaaaaaaaaaaaaaaa'), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', ' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')]]) +suite.append(['(a|abcd|african)', '', [('a', ' 0: a'), ('abcd', ' 0: abcd'), ('african', ' 0: african')]]) +suite.append(['^abc', '', [('abcdef', ' 0: abc'), ('*** Failers', None), ('xyzabc', None), ('xyz\nabc', None)]]) +suite.append(['x\\dy\\Dz', '', [('x9yzz', ' 0: x9yzz'), ('x0y+z', ' 0: x0y+z'), ('*** Failers', None), ('xyz', None), ('xxy0z', None)]]) +suite.append(['x\\sy\\Sz', '', [('x yzz', ' 0: x yzz'), ('x y+z', ' 0: x y+z'), ('*** Failers', None), ('xyz', None), ('xxyyz', None)]]) +suite.append(['x\\wy\\Wz', '', [('xxy+z', ' 0: xxy+z'), ('*** Failers', None), ('xxy0z', None), ('x+y+z', None)]]) +suite.append(['x.y', '', [('x+y', ' 0: x+y'), ('x-y', ' 0: x-y'), ('*** Failers', None), ('x\ny', None)]]) +suite.append(['a\\d$', '', [('ba0', ' 0: a0'), ('ba0\n', ' 0: a0'), ('*** Failers', None), ('ba0\ncd', None)]]) +suite.append(['[^a]', '', [('abcd', ' 0: b')]]) +suite.append(['ab?\\w', '', [('abz', ' 0: abz'), ('abbz', ' 0: abb'), ('azz', ' 0: az')]]) +suite.append(['x{0,3}yz', '', [('ayzq', ' 0: yz'), ('axyzq', ' 0: xyz'), ('axxyz', ' 0: xxyz'), ('axxxyzq', ' 0: xxxyz'), ('axxxxyzq', ' 0: xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None)]]) +suite.append(['x{3}yz', '', [('axxxyzq', ' 0: xxxyz'), ('axxxxyzq', ' 0: xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None), ('ayzq', None), ('axyzq', None), ('axxyz', None)]]) +suite.append(['x{2,3}yz', '', [('axxyz', ' 0: xxyz'), ('axxxyzq', ' 0: xxxyz'), ('axxxxyzq', ' 0: xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None), ('ayzq', None), ('axyzq', None)]]) +suite.append(['[^a]+', '', [('bac', ' 0: b'), ('bcdefax', ' 0: bcdef'), ('*** Failers', ' 0: *** F'), ('aaaaa', None)]]) +suite.append(['[^a]*', '', [('bac', ' 0: b'), ('bcdefax', ' 0: bcdef'), ('*** Failers', ' 0: *** F'), ('aaaaa', ' 0: ')]]) +suite.append(['[^a]{3,5}', '', [('xyz', ' 0: xyz'), ('awxyza', ' 0: wxyz'), ('abcdefa', ' 0: bcdef'), ('abcdefghijk', ' 0: bcdef'), ('*** Failers', ' 0: *** F'), ('axya', None), ('axa', None), ('aaaaa', None)]]) +suite.append(['\\d*', '', [('1234b567', ' 0: 1234'), ('xyz', ' 0: ')]]) +suite.append(['\\D*', '', [('a1234b567', ' 0: a'), ('xyz', ' 0: xyz')]]) +suite.append(['\\d+', '', [('ab1234c56', ' 0: 1234'), ('*** Failers', None), ('xyz', None)]]) +suite.append(['\\D+', '', [('ab123c56', ' 0: ab'), ('*** Failers', ' 0: *** Failers'), ('789', None)]]) +suite.append(['\\d?A', '', [('045ABC', ' 0: 5A'), ('ABC', ' 0: A'), ('*** Failers', None), ('XYZ', None)]]) +suite.append(['\\D?A', '', [('ABC', ' 0: A'), ('BAC', ' 0: BA'), ('9ABC', ' 0: A'), ('*** Failers', None)]]) +suite.append(['a+', '', [('aaaa', ' 0: aaaa')]]) +suite.append(['^.*xyz', '', [('xyz', ' 0: xyz'), ('ggggggggxyz', ' 0: ggggggggxyz')]]) +suite.append(['^.+xyz', '', [('abcdxyz', ' 0: abcdxyz'), ('axyz', ' 0: axyz'), ('*** Failers', None), ('xyz', None)]]) +suite.append(['^.?xyz', '', [('xyz', ' 0: xyz'), ('cxyz', ' 0: cxyz')]]) +suite.append(['^\\d{2,3}X', '', [('12X', ' 0: 12X'), ('123X', ' 0: 123X'), ('*** Failers', None), ('X', None), ('1X', None), ('1234X', None)]]) +suite.append(['^[abcd]\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('*** Failers', None), ('e45', None), ('abcd', None), ('abcd1234', None), ('1234', None)]]) +suite.append(['^[abcd]*\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('abcd1234', ' 0: abcd1'), ('1234', ' 0: 1'), ('*** Failers', None), ('e45', None), ('abcd', None)]]) +suite.append(['^[abcd]+\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('abcd1234', ' 0: abcd1'), ('*** Failers', None), ('1234', None), ('e45', None), ('abcd', None)]]) +suite.append(['^a+X', '', [('aX', ' 0: aX'), ('aaX', ' 0: aaX')]]) +suite.append(['^[abcd]?\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('1234', ' 0: 1'), ('*** Failers', None), ('abcd1234', None), ('e45', None)]]) +suite.append(['^[abcd]{2,3}\\d', '', [('ab45', ' 0: ab4'), ('bcd93', ' 0: bcd9'), ('*** Failers', None), ('1234', None), ('a36', None), ('abcd1234', None), ('ee45', None)]]) +suite.append(['^(abc)*\\d', '', [('abc45', ' 0: abc4'), ('abcabcabc45', ' 0: abcabcabc4'), ('42xyz', ' 0: 4'), ('*** Failers', None)]]) +suite.append(['^(abc)+\\d', '', [('abc45', ' 0: abc4'), ('abcabcabc45', ' 0: abcabcabc4'), ('*** Failers', None), ('42xyz', None)]]) +suite.append(['^(abc)?\\d', '', [('abc45', ' 0: abc4'), ('42xyz', ' 0: 4'), ('*** Failers', None), ('abcabcabc45', None)]]) +suite.append(['^(abc){2,3}\\d', '', [('abcabc45', ' 0: abcabc4'), ('abcabcabc45', ' 0: abcabcabc4'), ('*** Failers', None), ('abcabcabcabc45', None), ('abc45', None), ('42xyz', None)]]) +suite.append(['^(a*\\w|ab)=(a*\\w|ab)', '', [('ab=ab', ' 0: ab=ab')]]) +suite.append(['^abc', '', [('abcdef', ' 0: abc'), ('*** Failers', None)]]) +suite.append(['^(a*|xyz)', '', [('bcd', ' 0: '), ('aaabcd', ' 0: aaa'), ('xyz', ' 0: xyz'), ('*** Failers', ' 0: ')]]) +suite.append(['xyz$', '', [('xyz', ' 0: xyz'), ('xyz\n', ' 0: xyz'), ('*** Failers', None)]]) +suite.append(['^abcdef', '', [('*** Failers', None)]]) +suite.append(['^a{2,4}\\d+z', '', [('*** Failers', None)]]) +suite.append(['^abcdef', '', []]) +suite.append(['(ab*(cd|ef))+X', '', []]) +suite.append(['the quick brown fox', '', [('the quick brown fox', ' 0: the quick brown fox'), ('The quick brown FOX', None), ('What do you know about the quick brown fox?', ' 0: the quick brown fox'), ('What do you know about THE QUICK BROWN FOX?', None)]]) +suite.append(['abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz', '', [('abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz', ' 0: abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz')]]) +suite.append(['a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz', '', [('abxyzpqrrrabbxyyyypqAzz', ' 0: abxyzpqrrrabbxyyyypqAzz'), ('abxyzpqrrrabbxyyyypqAzz', ' 0: abxyzpqrrrabbxyyyypqAzz'), ('aabxyzpqrrrabbxyyyypqAzz', ' 0: aabxyzpqrrrabbxyyyypqAzz'), ('aaabxyzpqrrrabbxyyyypqAzz', ' 0: aaabxyzpqrrrabbxyyyypqAzz'), ('aaaabxyzpqrrrabbxyyyypqAzz', ' 0: aaaabxyzpqrrrabbxyyyypqAzz'), ('abcxyzpqrrrabbxyyyypqAzz', ' 0: abcxyzpqrrrabbxyyyypqAzz'), ('aabcxyzpqrrrabbxyyyypqAzz', ' 0: aabcxyzpqrrrabbxyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypAzz', ' 0: aaabcxyzpqrrrabbxyyyypAzz'), ('aaabcxyzpqrrrabbxyyyypqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz'), ('aaaabcxyzpqrrrabbxyyyypqAzz', ' 0: aaaabcxyzpqrrrabbxyyyypqAzz'), ('abxyzzpqrrrabbxyyyypqAzz', ' 0: abxyzzpqrrrabbxyyyypqAzz'), ('aabxyzzzpqrrrabbxyyyypqAzz', ' 0: aabxyzzzpqrrrabbxyyyypqAzz'), ('aaabxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaabxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaaabxyzzzzpqrrrabbxyyyypqAzz'), ('abcxyzzpqrrrabbxyyyypqAzz', ' 0: abcxyzzpqrrrabbxyyyypqAzz'), ('aabcxyzzzpqrrrabbxyyyypqAzz', ' 0: aabcxyzzzpqrrrabbxyyyypqAzz'), ('aaabcxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaabcxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbbxyyyypqAzz', ' 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbbxyyyyypqAzz', ' 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypABzz', ' 0: aaabcxyzpqrrrabbxyyyypABzz'), ('aaabcxyzpqrrrabbxyyyypABBzz', ' 0: aaabcxyzpqrrrabbxyyyypABBzz'), ('>>>aaabxyzpqrrrabbxyyyypqAzz', ' 0: aaabxyzpqrrrabbxyyyypqAzz'), ('>aaaabxyzpqrrrabbxyyyypqAzz', ' 0: aaaabxyzpqrrrabbxyyyypqAzz'), ('>>>>abcxyzpqrrrabbxyyyypqAzz', ' 0: abcxyzpqrrrabbxyyyypqAzz'), ('*** Failers', None), ('abxyzpqrrabbxyyyypqAzz', None), ('abxyzpqrrrrabbxyyyypqAzz', None), ('abxyzpqrrrabxyyyypqAzz', None), ('aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz', None), ('aaaabcxyzzzzpqrrrabbbxyyypqAzz', None), ('aaabcxyzpqrrrabbxyyyypqqqqqqqAzz', None)]]) +suite.append(['^(abc){1,2}zz', '', [('abczz', ' 0: abczz'), ('abcabczz', ' 0: abcabczz'), ('*** Failers', None), ('zz', None), ('abcabcabczz', None), ('>>abczz', None)]]) +suite.append(['^(b+|a){1,2}c', '', [('bc', ' 0: bc'), ('bbc', ' 0: bbc'), ('bbbc', ' 0: bbbc'), ('bac', ' 0: bac'), ('bbac', ' 0: bbac'), ('aac', ' 0: aac'), ('abbbbbbbbbbbc', ' 0: abbbbbbbbbbbc'), ('bbbbbbbbbbbac', ' 0: bbbbbbbbbbbac'), ('*** Failers', None), ('aaac', None), ('abbbbbbbbbbbac', None)]]) +suite.append(['^\\ca\\cA\\c[\\c{\\c:', '', [('\x01\x01\x1b;z', ' 0: \x01\x01\x1b;z')]]) +suite.append(['^[ab\\]cde]', '', [('athing', ' 0: a'), ('bthing', ' 0: b'), (']thing', ' 0: ]'), ('cthing', ' 0: c'), ('dthing', ' 0: d'), ('ething', ' 0: e'), ('*** Failers', None), ('fthing', None), ('[thing', None), ('\\thing', None)]]) +suite.append(['^[]cde]', '', [(']thing', ' 0: ]'), ('cthing', ' 0: c'), ('dthing', ' 0: d'), ('ething', ' 0: e'), ('*** Failers', None), ('athing', None), ('fthing', None)]]) +suite.append(['^[^ab\\]cde]', '', [('fthing', ' 0: f'), ('[thing', ' 0: ['), ('\\thing', ' 0: \\'), ('*** Failers', ' 0: *'), ('athing', None), ('bthing', None), (']thing', None), ('cthing', None), ('dthing', None), ('ething', None)]]) +suite.append(['^[^]cde]', '', [('athing', ' 0: a'), ('fthing', ' 0: f'), ('*** Failers', ' 0: *'), (']thing', None), ('cthing', None), ('dthing', None), ('ething', None)]]) +suite.append(['^\\\x81', '', [('\x81', ' 0: \x81')]]) +suite.append(['^\xff', '', [('\xff', ' 0: \xff')]]) +suite.append(['^[0-9]+$', '', [('0', ' 0: 0'), ('1', ' 0: 1'), ('2', ' 0: 2'), ('3', ' 0: 3'), ('4', ' 0: 4'), ('5', ' 0: 5'), ('6', ' 0: 6'), ('7', ' 0: 7'), ('8', ' 0: 8'), ('9', ' 0: 9'), ('10', ' 0: 10'), ('100', ' 0: 100'), ('*** Failers', None), ('abc', None)]]) +suite.append(['^.*nter', '', [('enter', ' 0: enter'), ('inter', ' 0: inter'), ('uponter', ' 0: uponter')]]) +suite.append(['^xxx[0-9]+$', '', [('xxx0', ' 0: xxx0'), ('xxx1234', ' 0: xxx1234'), ('*** Failers', None), ('xxx', None)]]) +suite.append(['^.+[0-9][0-9][0-9]$', '', [('x123', ' 0: x123'), ('xx123', ' 0: xx123'), ('123456', ' 0: 123456'), ('*** Failers', None), ('123', None), ('x1234', ' 0: x1234')]]) +suite.append(['^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$', '', [('abc!pqr=apquxz.ixr.zzz.ac.uk', ' 0: abc!pqr=apquxz.ixr.zzz.ac.uk'), ('*** Failers', None), ('!pqr=apquxz.ixr.zzz.ac.uk', None), ('abc!=apquxz.ixr.zzz.ac.uk', None), ('abc!pqr=apquxz:ixr.zzz.ac.uk', None), ('abc!pqr=apquxz.ixr.zzz.ac.ukk', None)]]) +suite.append([':', '', [('Well, we need a colon: somewhere', ' 0: :'), ("*** Fail if we don't", None)]]) +suite.append(['^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$', '', [('.1.2.3', ' 0: .1.2.3'), ('A.12.123.0', ' 0: A.12.123.0'), ('*** Failers', None), ('.1.2.3333', None), ('1.2.3', None), ('1234.2.3', None)]]) +suite.append(['^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$', '', [('1 IN SOA non-sp1 non-sp2(', ' 0: 1 IN SOA non-sp1 non-sp2('), ('1 IN SOA non-sp1 non-sp2 (', ' 0: 1 IN SOA non-sp1 non-sp2 ('), ('*** Failers', None), ('1IN SOA non-sp1 non-sp2(', None)]]) +suite.append(['^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$', '', [('a.', ' 0: a.'), ('Z.', ' 0: Z.'), ('2.', ' 0: 2.'), ('ab-c.pq-r.', ' 0: ab-c.pq-r.'), ('sxk.zzz.ac.uk.', ' 0: sxk.zzz.ac.uk.'), ('x-.y-.', ' 0: x-.y-.'), ('*** Failers', None), ('-abc.peq.', None)]]) +suite.append(['^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$', '', [('*.a', ' 0: *.a'), ('*.b0-a', ' 0: *.b0-a'), ('*.c3-b.c', ' 0: *.c3-b.c'), ('*.c-a.b-c', ' 0: *.c-a.b-c'), ('*** Failers', None), ('*.0', None), ('*.a-', None), ('*.a-b.c-', None), ('*.c-a.0-c', None)]]) +suite.append(['^\\".*\\"\\s*(;.*)?$', '', [('"1234"', ' 0: "1234"'), ('"abcd" ;', ' 0: "abcd" ;'), ('"" ; rhubarb', ' 0: "" ; rhubarb'), ('*** Failers', None), ('"1234" : things', None)]]) +suite.append(['^$', '', [('', ' 0: '), ('*** Failers', None)]]) +suite.append(['^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$', '', [('abcdefhijklm', ' 0: abcdefhijklm')]]) +suite.append(['^a*\\w', '', [('z', ' 0: z'), ('az', ' 0: az'), ('aaaz', ' 0: aaaz'), ('a', ' 0: a'), ('aa', ' 0: aa'), ('aaaa', ' 0: aaaa'), ('a+', ' 0: a'), ('aa+', ' 0: aa')]]) +suite.append(['^a+\\w', '', [('az', ' 0: az'), ('aaaz', ' 0: aaaz'), ('aa', ' 0: aa'), ('aaaa', ' 0: aaaa'), ('aa+', ' 0: aa')]]) +suite.append(['^\\d{8}\\w{2,}', '', [('1234567890', ' 0: 1234567890'), ('12345678ab', ' 0: 12345678ab'), ('12345678__', ' 0: 12345678__'), ('*** Failers', None), ('1234567', None)]]) +suite.append(['^[aeiou\\d]{4,5}$', '', [('uoie', ' 0: uoie'), ('1234', ' 0: 1234'), ('12345', ' 0: 12345'), ('aaaaa', ' 0: aaaaa'), ('*** Failers', None), ('123456', None)]]) +suite.append(['^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]', '', [('From abcd Mon Sep 01 12:33:02 1997', ' 0: From abcd Mon Sep 01 12:33')]]) +suite.append(['^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d', '', [('From abcd Mon Sep 01 12:33:02 1997', ' 0: From abcd Mon Sep 01 12:33'), ('From abcd Mon Sep 1 12:33:02 1997', ' 0: From abcd Mon Sep 1 12:33'), ('*** Failers', None), ('From abcd Sep 01 12:33:02 1997', None)]]) +suite.append(['^[ab]{1,3}(ab*|b)', '', [('aabbbbb', ' 0: aabbbbb')]]) +suite.append(['abc\\0def\\00pqr\\000xyz\\0000AB', '', [('abc\x00def\x00pqr\x00xyz\x000AB', ' 0: abc\x00def\x00pqr\x00xyz\x000AB'), ('abc456 abc\x00def\x00pqr\x00xyz\x000ABCDE', ' 0: abc\x00def\x00pqr\x00xyz\x000AB')]]) +suite.append(['abc\\x0def\\x00pqr\\x000xyz\\x0000AB', '', [('abc\ref\x00pqr\x000xyz\x0000AB', ' 0: abc\ref\x00pqr\x000xyz\x0000AB'), ('abc456 abc\ref\x00pqr\x000xyz\x0000ABCDE', ' 0: abc\ref\x00pqr\x000xyz\x0000AB')]]) +suite.append(['^[\\000-\\037]', '', [('\x00A', ' 0: \x00'), ('\x01B', ' 0: \x01'), ('\x1fC', ' 0: \x1f')]]) +suite.append(['\\0*', '', [('\x00\x00\x00\x00', ' 0: \x00\x00\x00\x00')]]) +suite.append(['A\\x00{2,3}Z', '', [('The A\x00\x00Z', ' 0: A\x00\x00Z'), ('An A\x00\x00\x00Z', ' 0: A\x00\x00\x00Z'), ('*** Failers', None), ('A\x00Z', None), ('A\x00\x00\x00\x00Z', None)]]) +suite.append(['^\\s', '', [(' abc', ' 0: '), ('\x0cabc', ' 0: \x0c'), ('\nabc', ' 0: \n'), ('\rabc', ' 0: \r'), ('\tabc', ' 0: \t'), ('*** Failers', None), ('abc', None)]]) +suite.append(['ab{1,3}bc', '', [('abbbbc', ' 0: abbbbc'), ('abbbc', ' 0: abbbc'), ('abbc', ' 0: abbc'), ('*** Failers', None), ('abc', None), ('abbbbbc', None)]]) +suite.append(['([^.]*)\\.([^:]*):[T ]+(.*)', '', [('track1.title:TBlah blah blah', ' 0: track1.title:TBlah blah blah')]]) +suite.append(['^[W-c]+$', '', [('WXY_^abc', ' 0: WXY_^abc'), ('*** Failers', None), ('wxy', None)]]) +suite.append(['^abc$', '', [('abc', ' 0: abc'), ('*** Failers', None), ('qqq\nabc', None), ('abc\nzzz', None), ('qqq\nabc\nzzz', None)]]) +suite.append(['[-az]+', '', [('az-', ' 0: az-'), ('*** Failers', ' 0: a'), ('b', None)]]) +suite.append(['[az-]+', '', [('za-', ' 0: za-'), ('*** Failers', ' 0: a'), ('b', None)]]) +suite.append(['[a\\-z]+', '', [('a-z', ' 0: a-z'), ('*** Failers', ' 0: a'), ('b', None)]]) +suite.append(['[a-z]+', '', [('abcdxyz', ' 0: abcdxyz')]]) +suite.append(['[\\d-]+', '', [('12-34', ' 0: 12-34'), ('*** Failers', None), ('aaa', None)]]) +suite.append(['[\\d-z]+', '', [('12-34z', ' 0: 12-34z'), ('*** Failers', None), ('aaa', None)]]) +suite.append(['\\x5c', '', [('\\', ' 0: \\')]]) +suite.append(['\\x20Z', '', [('the Zoo', ' 0: Z'), ('*** Failers', None), ('Zulu', None)]]) +suite.append(['ab{3cd', '', [('ab{3cd', ' 0: ab{3cd')]]) +suite.append(['ab{3,cd', '', [('ab{3,cd', ' 0: ab{3,cd')]]) +suite.append(['ab{3,4a}cd', '', [('ab{3,4a}cd', ' 0: ab{3,4a}cd')]]) +suite.append(['{4,5a}bc', '', [('{4,5a}bc', ' 0: {4,5a}bc')]]) +suite.append(['abc$', '', [('abc', ' 0: abc'), ('abc\n', ' 0: abc'), ('*** Failers', None), ('abc\ndef', None)]]) +suite.append(['(abc)\\223', '', [('abc\x93', ' 0: abc\x93')]]) +suite.append(['(abc)\\323', '', [('abc\xd3', ' 0: abc\xd3')]]) +suite.append(['ab\\idef', '', [('abidef', ' 0: abidef')]]) +suite.append(['a{0}bc', '', [('bc', ' 0: bc')]]) +suite.append(['abc[\\10]de', '', [('abc\x08de', ' 0: abc\x08de')]]) +suite.append(['abc[\\1]de', '', [('abc\x01de', ' 0: abc\x01de')]]) +suite.append(['[^a]', '', [('Abc', ' 0: A')]]) +suite.append(['[^a]+', '', [('AAAaAbc', ' 0: AAA')]]) +suite.append(['[^a]+', '', [('bbb\nccc', ' 0: bbb\nccc')]]) +suite.append(['[^k]$', '', [('abc', ' 0: c'), ('*** Failers', ' 0: s'), ('abk', None)]]) +suite.append(['[^k]{2,3}$', '', [('abc', ' 0: abc'), ('kbc', ' 0: bc'), ('kabc', ' 0: abc'), ('*** Failers', ' 0: ers'), ('abk', None), ('akb', None), ('akk', None)]]) +suite.append(['^\\d{8,}\\@.+[^k]$', '', [('12345678 at a.b.c.d', ' 0: 12345678 at a.b.c.d'), ('123456789 at x.y.z', ' 0: 123456789 at x.y.z'), ('*** Failers', None), ('12345678 at x.y.uk', None), ('1234567 at a.b.c.d', None)]]) +suite.append(['[^a]', '', [('aaaabcd', ' 0: b'), ('aaAabcd', ' 0: A')]]) +suite.append(['[^az]', '', [('aaaabcd', ' 0: b'), ('aaAabcd', ' 0: A')]]) +suite.append(['\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377', '', [('\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', ' 0: \x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff')]]) +suite.append(['(\\.\\d\\d[1-9]?)\\d+', '', [('1.230003938', ' 0: .230003938'), ('1.875000282', ' 0: .875000282'), ('1.235', ' 0: .235')]]) +suite.append(['foo(.*)bar', '', [('The food is under the bar in the barn.', ' 0: food is under the bar in the bar')]]) +suite.append(['(.*)(\\d*)', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) +suite.append(['(.*)(\\d+)', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) +suite.append(['(.*)(\\d+)$', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) +suite.append(['(.*\\D)(\\d+)$', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) +suite.append(['^[W-]46]', '', [('W46]789', ' 0: W46]'), ('-46]789', ' 0: -46]'), ('*** Failers', None), ('Wall', None), ('Zebra', None), ('42', None), ('[abcd]', None), (']abcd[', None)]]) +suite.append(['^[W-\\]46]', '', [('W46]789', ' 0: W'), ('Wall', ' 0: W'), ('Zebra', ' 0: Z'), ('Xylophone', ' 0: X'), ('42', ' 0: 4'), ('[abcd]', ' 0: ['), (']abcd[', ' 0: ]'), ('\\backslash', ' 0: \\'), ('*** Failers', None), ('-46]789', None), ('well', None)]]) +suite.append(['\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d', '', [('01/01/2000', ' 0: 01/01/2000')]]) +suite.append(['^(a){0,0}', '', [('bcd', ' 0: '), ('abc', ' 0: '), ('aab', ' 0: ')]]) +suite.append(['^(a){0,1}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: a')]]) +suite.append(['^(a){0,2}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: aa')]]) +suite.append(['^(a){0,3}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa')]]) +suite.append(['^(a){0,}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa'), ('aaaaaaaa', ' 0: aaaaaaaa')]]) +suite.append(['^(a){1,1}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: a')]]) +suite.append(['^(a){1,2}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: aa')]]) +suite.append(['^(a){1,3}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa')]]) +suite.append(['^(a){1,}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa'), ('aaaaaaaa', ' 0: aaaaaaaa')]]) +suite.append(['.*\\.gif', '', [('borfle\nbib.gif\nno', ' 0: bib.gif')]]) +suite.append(['.{0,}\\.gif', '', [('borfle\nbib.gif\nno', ' 0: bib.gif')]]) +suite.append(['.*$', '', [('borfle\nbib.gif\nno', ' 0: no')]]) +suite.append(['.*$', '', [('borfle\nbib.gif\nno\n', ' 0: no')]]) +suite.append(['^.*B', '', [('**** Failers', None), ('abc\nB', None)]]) +suite.append(['^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]', '', [('123456654321', ' 0: 123456654321')]]) +suite.append(['^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d', '', [('123456654321', ' 0: 123456654321')]]) +suite.append(['^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]', '', [('123456654321', ' 0: 123456654321')]]) +suite.append(['^[abc]{12}', '', [('abcabcabcabc', ' 0: abcabcabcabc')]]) +suite.append(['^[a-c]{12}', '', [('abcabcabcabc', ' 0: abcabcabcabc')]]) +suite.append(['^(a|b|c){12}', '', [('abcabcabcabc', ' 0: abcabcabcabc')]]) +suite.append(['^[abcdefghijklmnopqrstuvwxy0123456789]', '', [('n', ' 0: n'), ('*** Failers', None), ('z', None)]]) +suite.append(['abcde{0,0}', '', [('abcd', ' 0: abcd'), ('*** Failers', None), ('abce', None)]]) +suite.append(['ab[cd]{0,0}e', '', [('abe', ' 0: abe'), ('*** Failers', None), ('abcde', None)]]) +suite.append(['ab(c){0,0}d', '', [('abd', ' 0: abd'), ('*** Failers', None), ('abcd', None)]]) +suite.append(['a(b*)', '', [('a', ' 0: a'), ('ab', ' 0: ab'), ('abbbb', ' 0: abbbb'), ('*** Failers', ' 0: a'), ('bbbbb', None)]]) +suite.append(['ab\\d{0}e', '', [('abe', ' 0: abe'), ('*** Failers', None), ('ab1e', None)]]) +suite.append(['"([^\\\\"]+|\\\\.)*"', '', [('the "quick" brown fox', ' 0: "quick"'), ('"the \\"quick\\" brown fox"', ' 0: "the \\"quick\\" brown fox"')]]) +suite.append(['a[^a]b', '', [('acb', ' 0: acb'), ('a\nb', ' 0: a\nb')]]) +suite.append(['a.b', '', [('acb', ' 0: acb'), ('*** Failers', None), ('a\nb', None)]]) +suite.append(['\\x00{ab}', '', [('\x00{ab}', ' 0: \x00{ab}')]]) +suite.append(['(A|B)*CD', '', [('CD', ' 0: CD')]]) +suite.append(['(\\d+)(\\w)', '', [('12345a', ' 0: 12345a'), ('12345+', ' 0: 12345')]]) +suite.append(['(a+|b+|c+)*c', '', [('aaabbbbccccd', ' 0: aaabbbbcccc')]]) +suite.append(['(abc|)+', '', [('abc', ' 0: abc'), ('abcabc', ' 0: abcabc'), ('abcabcabc', ' 0: abcabcabc'), ('xyz', ' 0: ')]]) +suite.append(['([a]*)*', '', [('a', ' 0: a'), ('aaaaa', ' 0: aaaaa')]]) +suite.append(['([ab]*)*', '', [('a', ' 0: a'), ('b', ' 0: b'), ('ababab', ' 0: ababab'), ('aaaabcde', ' 0: aaaab'), ('bbbb', ' 0: bbbb')]]) +suite.append(['([^a]*)*', '', [('b', ' 0: b'), ('bbbb', ' 0: bbbb'), ('aaa', ' 0: ')]]) +suite.append(['([^ab]*)*', '', [('cccc', ' 0: cccc'), ('abab', ' 0: ')]]) +suite.append(['The following tests are taken from the Perl 5.005 test suite; some of them', '', [("/are compatible with 5.004, but I'd rather not have to sort them out./", None)]]) +suite.append(['abc', '', [('abc', ' 0: abc'), ('xabcy', ' 0: abc'), ('ababc', ' 0: abc'), ('*** Failers', None), ('xbc', None), ('axc', None), ('abx', None)]]) +suite.append(['ab*c', '', [('abc', ' 0: abc')]]) +suite.append(['ab*bc', '', [('abc', ' 0: abc'), ('abbc', ' 0: abbc'), ('abbbbc', ' 0: abbbbc')]]) +suite.append(['.{1}', '', [('abbbbc', ' 0: a')]]) +suite.append(['.{3,4}', '', [('abbbbc', ' 0: abbb')]]) +suite.append(['ab{0,}bc', '', [('abbbbc', ' 0: abbbbc')]]) +suite.append(['ab+bc', '', [('abbc', ' 0: abbc'), ('*** Failers', None), ('abc', None), ('abq', None)]]) +suite.append(['ab{1,}bc', '', []]) +suite.append(['ab+bc', '', [('abbbbc', ' 0: abbbbc')]]) +suite.append(['ab{1,}bc', '', [('abbbbc', ' 0: abbbbc')]]) +suite.append(['ab{1,3}bc', '', [('abbbbc', ' 0: abbbbc')]]) +suite.append(['ab{3,4}bc', '', [('abbbbc', ' 0: abbbbc')]]) +suite.append(['ab{4,5}bc', '', [('*** Failers', None), ('abq', None), ('abbbbc', None)]]) +suite.append(['ab?bc', '', [('abbc', ' 0: abbc'), ('abc', ' 0: abc')]]) +suite.append(['ab{0,1}bc', '', [('abc', ' 0: abc')]]) +suite.append(['ab?bc', '', []]) +suite.append(['ab?c', '', [('abc', ' 0: abc')]]) +suite.append(['ab{0,1}c', '', [('abc', ' 0: abc')]]) +suite.append(['^abc$', '', [('abc', ' 0: abc'), ('*** Failers', None), ('abbbbc', None), ('abcc', None)]]) +suite.append(['^abc', '', [('abcc', ' 0: abc')]]) +suite.append(['^abc$', '', []]) +suite.append(['abc$', '', [('aabc', ' 0: abc'), ('*** Failers', None), ('aabc', ' 0: abc'), ('aabcd', None)]]) +suite.append(['^', '', [('abc', ' 0: ')]]) +suite.append(['$', '', [('abc', ' 0: ')]]) +suite.append(['a.c', '', [('abc', ' 0: abc'), ('axc', ' 0: axc')]]) +suite.append(['a.*c', '', [('axyzc', ' 0: axyzc')]]) +suite.append(['a[bc]d', '', [('abd', ' 0: abd'), ('*** Failers', None), ('axyzd', None), ('abc', None)]]) +suite.append(['a[b-d]e', '', [('ace', ' 0: ace')]]) +suite.append(['a[b-d]', '', [('aac', ' 0: ac')]]) +suite.append(['a[-b]', '', [('a-', ' 0: a-')]]) +suite.append(['a[b-]', '', [('a-', ' 0: a-')]]) +suite.append(['a]', '', [('a]', ' 0: a]')]]) +suite.append(['a[]]b', '', [('a]b', ' 0: a]b')]]) +suite.append(['a[^bc]d', '', [('aed', ' 0: aed'), ('*** Failers', None), ('abd', None), ('abd', None)]]) +suite.append(['a[^-b]c', '', [('adc', ' 0: adc')]]) +suite.append(['a[^]b]c', '', [('adc', ' 0: adc'), ('*** Failers', None), ('a-c', ' 0: a-c'), ('a]c', None)]]) +suite.append(['\\w', '', [('a', ' 0: a')]]) +suite.append(['\\W', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('a', None)]]) +suite.append(['a\\sb', '', [('a b', ' 0: a b')]]) +suite.append(['a\\Sb', '', [('a-b', ' 0: a-b'), ('*** Failers', None), ('a-b', ' 0: a-b'), ('a b', None)]]) +suite.append(['\\d', '', [('1', ' 0: 1')]]) +suite.append(['\\D', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('1', None)]]) +suite.append(['[\\w]', '', [('a', ' 0: a')]]) +suite.append(['[\\W]', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('a', None)]]) +suite.append(['a[\\s]b', '', [('a b', ' 0: a b')]]) +suite.append(['a[\\S]b', '', [('a-b', ' 0: a-b'), ('*** Failers', None), ('a-b', ' 0: a-b'), ('a b', None)]]) +suite.append(['[\\d]', '', [('1', ' 0: 1')]]) +suite.append(['[\\D]', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('1', None)]]) +suite.append(['ab|cd', '', [('abc', ' 0: ab'), ('abcd', ' 0: ab')]]) +suite.append(['()ef', '', [('def', ' 0: ef')]]) +suite.append(['$b', '', []]) +suite.append(['a\\(b', '', [('a(b', ' 0: a(b')]]) +suite.append(['a\\(*b', '', [('ab', ' 0: ab'), ('a((b', ' 0: a((b')]]) +suite.append(['a\\\\b', '', []]) +suite.append(['((a))', '', [('abc', ' 0: a')]]) +suite.append(['(a)b(c)', '', [('abc', ' 0: abc')]]) +suite.append(['a+b+c', '', [('aabbabc', ' 0: abc')]]) +suite.append(['a{1,}b{1,}c', '', [('aabbabc', ' 0: abc')]]) +suite.append(['(a+|b)*', '', [('ab', ' 0: ab')]]) +suite.append(['(a+|b){0,}', '', [('ab', ' 0: ab')]]) +suite.append(['(a+|b)+', '', [('ab', ' 0: ab')]]) +suite.append(['(a+|b){1,}', '', [('ab', ' 0: ab')]]) +suite.append(['(a+|b)?', '', [('ab', ' 0: a')]]) +suite.append(['(a+|b){0,1}', '', [('ab', ' 0: a')]]) +suite.append(['[^ab]*', '', [('cde', ' 0: cde')]]) +suite.append(['abc', '', [('*** Failers', None), ('b', None)]]) +suite.append(['a*', '', []]) +suite.append(['([abc])*d', '', [('abbbcd', ' 0: abbbcd')]]) +suite.append(['([abc])*bcd', '', [('abcd', ' 0: abcd')]]) +suite.append(['a|b|c|d|e', '', [('e', ' 0: e')]]) +suite.append(['(a|b|c|d|e)f', '', [('ef', ' 0: ef')]]) +suite.append(['abcd*efg', '', [('abcdefg', ' 0: abcdefg')]]) +suite.append(['ab*', '', [('xabyabbbz', ' 0: ab'), ('xayabbbz', ' 0: a')]]) +suite.append(['(ab|cd)e', '', [('abcde', ' 0: cde')]]) +suite.append(['[abhgefdc]ij', '', [('hij', ' 0: hij')]]) +suite.append(['^(ab|cd)e', '', []]) +suite.append(['(abc|)ef', '', [('abcdef', ' 0: ef')]]) +suite.append(['(a|b)c*d', '', [('abcd', ' 0: bcd')]]) +suite.append(['(ab|ab*)bc', '', [('abc', ' 0: abc')]]) +suite.append(['a([bc]*)c*', '', [('abc', ' 0: abc')]]) +suite.append(['a([bc]*)(c*d)', '', [('abcd', ' 0: abcd')]]) +suite.append(['a([bc]+)(c*d)', '', [('abcd', ' 0: abcd')]]) +suite.append(['a([bc]*)(c+d)', '', [('abcd', ' 0: abcd')]]) +suite.append(['a[bcd]*dcdcde', '', [('adcdcde', ' 0: adcdcde')]]) +suite.append(['a[bcd]+dcdcde', '', [('*** Failers', None), ('abcde', None), ('adcdcde', None)]]) +suite.append(['(ab|a)b*c', '', [('abc', ' 0: abc')]]) +suite.append(['((a)(b)c)(d)', '', [('abcd', ' 0: abcd')]]) +suite.append(['[a-zA-Z_][a-zA-Z0-9_]*', '', [('alpha', ' 0: alpha')]]) +suite.append(['^a(bc+|b[eh])g|.h$', '', [('abh', ' 0: bh')]]) +suite.append(['(bc+d$|ef*g.|h?i(j|k))', '', [('effgz', ' 0: effgz'), ('ij', ' 0: ij'), ('reffgz', ' 0: effgz'), ('*** Failers', None), ('effg', None), ('bcdd', None)]]) +suite.append(['((((((((((a))))))))))', '', [('a', ' 0: a')]]) +suite.append(['(((((((((a)))))))))', '', [('a', ' 0: a')]]) +suite.append(['multiple words of text', '', [('*** Failers', None), ('aa', None), ('uh-uh', None)]]) +suite.append(['multiple words', '', [('multiple words, yeah', ' 0: multiple words')]]) +suite.append(['(.*)c(.*)', '', [('abcde', ' 0: abcde')]]) +suite.append(['\\((.*), (.*)\\)', '', [('(a, b)', ' 0: (a, b)')]]) +suite.append(['[k]', '', []]) +suite.append(['abcd', '', [('abcd', ' 0: abcd')]]) +suite.append(['a(bc)d', '', [('abcd', ' 0: abcd')]]) +suite.append(['a[-]?c', '', [('ac', ' 0: ac')]]) +suite.append(['((foo)|(bar))*', '', [('foobar', ' 0: foobar')]]) +suite.append(['^(.+)?B', '', [('AB', ' 0: AB')]]) +suite.append(['^([^a-z])|(\\^)$', '', [('.', ' 0: .')]]) +suite.append(['^[<>]&', '', [('<&OUT', ' 0: <&')]]) +suite.append(['^(){3,5}', '', [('abc', ' 0: ')]]) +suite.append(['^(a+)*ax', '', [('aax', ' 0: aax')]]) +suite.append(['^((a|b)+)*ax', '', [('aax', ' 0: aax')]]) +suite.append(['^((a|bc)+)*ax', '', [('aax', ' 0: aax')]]) +suite.append(['(a|x)*ab', '', [('cab', ' 0: ab')]]) +suite.append(['(a)*ab', '', [('cab', ' 0: ab')]]) +suite.append(['foo\\w*\\d{4}baz', '', [('foobar1234baz', ' 0: foobar1234baz')]]) +suite.append(['^b', '', []]) +suite.append(['(\\w+:)+', '', [('one:', ' 0: one:')]]) +suite.append(['([\\w:]+::)?(\\w+)$', '', [('abcd', ' 0: abcd'), ('xy:z:::abcd', ' 0: xy:z:::abcd')]]) +suite.append(['^[^bcd]*(c+)', '', [('aexycd', ' 0: aexyc')]]) +suite.append(['(a*)b+', '', [('caab', ' 0: aab')]]) +suite.append(['([\\w:]+::)?(\\w+)$', '', [('abcd', ' 0: abcd'), ('xy:z:::abcd', ' 0: xy:z:::abcd'), ('*** Failers', ' 0: Failers'), ('abcd:', None), ('abcd:', None)]]) +suite.append(['^[^bcd]*(c+)', '', [('aexycd', ' 0: aexyc')]]) +suite.append(['(>a+)ab', '', []]) +suite.append(['([[:]+)', '', [('a:[b]:', ' 0: :[')]]) +suite.append(['([[=]+)', '', [('a=[b]=', ' 0: =[')]]) +suite.append(['([[.]+)', '', [('a.[b].', ' 0: .[')]]) +suite.append(['((Z)+|A)*', '', [('ZABCDEFG', ' 0: ZA')]]) +suite.append(['(Z()|A)*', '', [('ZABCDEFG', ' 0: ZA')]]) +suite.append(['(Z(())|A)*', '', [('ZABCDEFG', ' 0: ZA')]]) +suite.append(['^[a-\\d]', '', [('abcde', ' 0: a'), ('-things', ' 0: -'), ('0digit', ' 0: 0'), ('*** Failers', None), ('bcdef', None)]]) +suite.append(['^[\\d-a]', '', [('abcde', ' 0: a'), ('-things', ' 0: -'), ('0digit', ' 0: 0'), ('*** Failers', None), ('bcdef', None)]]) +suite.append(['[\\s]+', '', [('> \t\n\x0c\r\x0b<', ' 0: \t\n\x0c\r')]]) +suite.append(['\\s+', '', [('> \t\n\x0c\r\x0b<', ' 0: \t\n\x0c\r')]]) +suite.append(['\\M', '', [('M', ' 0: M')]]) +suite.append(['(a+)*b', '', [('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', None)]]) +suite.append(['\xc5\xe6\xe5\xe4[\xe0-\xff\xc0-\xdf]+', '', [('\xc5\xe6\xe5\xe4\xe0', ' 0: \xc5\xe6\xe5\xe4\xe0'), ('\xc5\xe6\xe5\xe4\xff', ' 0: \xc5\xe6\xe5\xe4\xff'), ('\xc5\xe6\xe5\xe4\xc0', ' 0: \xc5\xe6\xe5\xe4\xc0'), ('\xc5\xe6\xe5\xe4\xdf', ' 0: \xc5\xe6\xe5\xe4\xdf')]]) +suite.append(['line\\nbreak', '', [('this is a line\nbreak', ' 0: line\nbreak'), ('line one\nthis is a line\nbreak in the second line', ' 0: line\nbreak')]]) +suite.append(['1234', '', []]) +suite.append(['1234', '', []]) +suite.append(['Content-Type\\x3A[^\\r\\n]{6,}', '', [('Content-Type:xxxxxyyy', ' 0: Content-Type:xxxxxyyy')]]) +suite.append(['Content-Type\\x3A[^\\r\\n]{6,}z', '', [('Content-Type:xxxxxyyyz', ' 0: Content-Type:xxxxxyyyz')]]) +suite.append(['Content-Type\\x3A[^a]{6,}', '', [('Content-Type:xxxyyy', ' 0: Content-Type:xxxyyy')]]) +suite.append(['Content-Type\\x3A[^a]{6,}z', '', [('Content-Type:xxxyyyz', ' 0: Content-Type:xxxyyyz')]]) +suite.append(['^\\w+=.*(\\\\\\n.*)*', '', [('abc=xyz\\\npqr', ' 0: abc=xyz\\\npqr')]]) +suite.append(['^(a()*)*', '', [('aaaa', ' 0: aaaa')]]) +suite.append(['^(a()+)+', '', [('aaaa', ' 0: aaaa')]]) +suite.append(['(a|)*\\d', '', [('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', None), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4', ' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4')]]) +suite.append(['.+foo', '', [('afoo', ' 0: afoo'), ('** Failers', None), ('\r\nfoo', None), ('\nfoo', None)]]) +suite.append([' End of testinput7 ', '', []]) Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Fri Apr 4 23:43:51 2008 @@ -6,6 +6,7 @@ our matching on strings like "[ab]{1,3}(ab*|b)" against 'aabbbb'. """ +pcre_license = """ # The PCRE library is distributed under the BSD license. We have borrowed some # of the regression tests (the ones that fit under the DFA scope) in order to # exercise our regex implementation. Those tests are distributed under PCRE's @@ -77,6 +78,8 @@ # # End +""" + import py from pypy.rlib.parsing.regexparse import make_runner, unescape import string @@ -84,14 +87,43 @@ py.test.skip("Still in progress") -def create_pcre_pickle(file, picklefile): +class Dumper(object): + def __init__(self, file): + pass + def dump(self, tests): + pass + +class PickleDumper(Dumper): + import pickle + def __init__(self, fileobj): + self.file = fileobj + def dump(self, tests): + pickle.dump(suite, self.file) + def load(self): + suite = pickle.load(file) + return suite + +class PythonDumper(Dumper): + def __init__(self, fileobj): + self.file = fileobj + def dump(self, tests): + self.file.write('# Auto-generated file of regular expressions from PCRE library\n') + self.file.write(pcre_license) + self.file.write('suite = []\n') + for test in tests: + self.file.write('suite.append(%r)\n' % test) + def load(self): + d = {} + text = self.file.read() + exec text in d + return d['suite'] + +def create_pcre_pickle(file, dumper): """Create a filtered PCRE test file for the test. The pickle file was created by: create_pcre_pickle(open('testoutput1','r'), open('testoutput1.pickle','w')) """ - import pickle - lines = [line for line in file.readlines()] # Look for things to skip... @@ -139,11 +171,8 @@ regex += matches[0][-2] # Add the backslash, if we gotta flags = matches[0][-1] # Get the flags for the regex + # Gotta tolerate Perl's short hexes regex = expand_perl_hex.sub(lambda m: r'\x0'+m.group(1), regex) - if regex.startswith('\\A'): - regex = '^' + regex[2:] # We treat \A like ^ - if regex.startswith('\\Z'): - regex = regex[:-2] + '$' # We treat \Z like $ tests = [] if greedy_ops.search(regex) or back_refs.search(regex): @@ -191,6 +220,7 @@ match = lines.pop(0).rstrip('\r\n') match = re.sub(r'\\x([0-9a-fA-F]{2})', lambda m: chr(int(m.group(1),16)), match) if match.startswith('No match') or match.startswith('Error') or match.startswith('Partial'): + match = None break elif match.startswith(' 0:'): # Now we need to eat any further lines like: @@ -207,12 +237,7 @@ raise Exception("Lost sync in output.") if not disqualify_test: tests.append((test,match)) - pickle.dump(suite, picklefile) - -def get_pcre_pickle(file): - import pickle - suite = pickle.load(file) - return suite + dumper.dump(suite) def run_individual_test(regex, tests): regex_to_use = regex @@ -234,7 +259,6 @@ # Now run the test expressions against the Regex for test, match in tests: print "/%r/%r/"%(test, match) - expect_match = (match != 'No match') # Create possible subsequences that we should test if anchor_left: @@ -252,10 +276,10 @@ for start, end in subseq_gen: attempt = test[start:end] if runner.recognize(attempt): - assert expect_match and attempt==match[4:] + assert match and attempt==match[4:] break else: - assert not expect_match + assert not match def run_pcre_tests(suite): """Run PCRE tests as given in suite.""" @@ -264,13 +288,13 @@ yield run_individual_test, regex, tests def test_output7(): - suite = get_pcre_pickle(open('testoutput7.pickle','r')) + suite = PythonDumper(open('pcre_test_7.py','r')).load() for test in run_pcre_tests(suite): yield test def generate_output7(): """Create the testoutput1.pickle file from the PCRE file testoutput1""" - create_pcre_pickle(open('testoutput7','r'), open('testoutput7.pickle','w')) + create_pcre_pickle(open('testoutput7','r'), PythonDumper(open('pcre_test_7.py','w'))) if __name__=="__main__": for fcn, regex, tests in test_output7(): From fijal at codespeak.net Sat Apr 5 04:30:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 04:30:43 +0200 (CEST) Subject: [pypy-svn] r53369 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080405023043.E72E716AB7A@codespeak.net> Author: fijal Date: Sat Apr 5 04:30:41 2008 New Revision: 53369 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: Add a test for field access Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sat Apr 5 04:30:41 2008 @@ -2261,6 +2261,36 @@ res = fnptr(3.1, -3.2, 2) assert res == 2.3*3 + def test_fieldaccess(self): + def f(x, y, z): + s = lltype.malloc(S.TO) + if self.RGenOpPacked is None: + py.test.skip("requires RGenOpPacked") + T = lltype.GcStruct('T', ('x', lltype.Signed), + ('y', lltype.Float), + ('z', lltype.Signed)) + rgenop = self.RGenOpPacked() + ARGS = [lltype.Signed, lltype.Float, lltype.Signed] + FUNC = lltype.FuncType(ARGS, lltype.Float) + sigtoken = rgenop.sigToken(FUNC) + builder, gv_fn, [gv_x, gv_y, gv_z] = rgenop.newgraph(sigtoken, + "fieldaccess") + builder.start_writing() + gv_s = builder.genop_malloc_fixedsize(rgenop.allocToken(T)) + builder.genop_setfield(rgenop.fieldToken(T, 'x'), gv_s, gv_x) + builder.genop_setfield(rgenop.fieldToken(T, 'y'), gv_s, gv_y) + builder.genop_setfield(rgenop.fieldToken(T, 'z'), gv_s, gv_z) + gv_y1 = builder.genop_getfield(rgenop.fieldToken(T, 'y'), gv_s) + gv_z1 = builder.genop_getfield(rgenop.fieldToken(T, 'z'), gv_s) + gv_z2 = builder.genop1('cast_int_to_float', gv_z1) + gv_res = builder.genop2('float_add', gv_y1, gv_z2) + builder.finish_and_return(sigtoken, gv_res) + builder.end() + + fnptr = self.cast_whatever(gv_fn, ARGS, lltype.Float) + result = fnptr(1, 3.2, 3) + assert result == 3.2 + 3 + def test_interior_access(self): # for assembler backends, the 'interior' lloperations can be # simply expressed as a sequence of genop_getsubstruct and From fijal at codespeak.net Sat Apr 5 04:54:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 04:54:28 +0200 (CEST) Subject: [pypy-svn] r53370 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080405025428.F1E4D16AB8D@codespeak.net> Author: fijal Date: Sat Apr 5 04:54:27 2008 New Revision: 53370 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Some refactoring in order to be able to rather freely move around the same objects for accessing different types. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Sat Apr 5 04:54:27 2008 @@ -34,7 +34,7 @@ def operand(self, builder): raise NotImplementedError - def movetonewaddr(self, builder, arg): + def movetonewaddr(self, builder, addr): raise NotImplementedError def __repr__(self): @@ -53,8 +53,8 @@ def newvar(self, builder): return builder.returnintvar(self.operand(builder)) - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) + def movetonewaddr(self, builder, addr): + dstop = builder.mem_access(addr) builder.mc.MOV(eax, self.operand(builder)) builder.mc.MOV(dstop, eax) @@ -64,6 +64,10 @@ SIZE = 1 class BoolVar(Var): + ll_type = lltype.Bool + token = 'b' + SIZE = 1 + # represents a boolean as an integer which *must* be exactly 0 or 1 def operand(self, builder): return builder.stack_access(self.stackpos) @@ -71,15 +75,11 @@ def newvar(self, builder): return builder.returnboolvar(self.operand(builder)) - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) + def movetonewaddr(self, builder, addr): + dstop = builder.mem_access(addr) builder.mc.MOV(eax, self.operand(builder)) builder.mc.MOV(destop, al) - ll_type = lltype.Bool - token = 'b' - SIZE = 1 - class FloatVar(Var): def operand(self, builder): return builder.stack_access64(self.stackpos) @@ -88,9 +88,9 @@ raise NotImplementedError("This requires moving around float mem") return builder.returnfloatvar(self.operand(builder)) - def movetonewaddr(self, builder, arg): - dstop1 = builder.itemaddr(arg) - dstop2 = builder.itemaddr(arg, WORD) + def movetonewaddr(self, builder, addr): + dstop1 = builder.mem_access(addr) + dstop2 = builder.mem_access(addr, WORD) builder.mc.MOV(eax, builder.stack_access(self.stackpos)) builder.mc.MOV(dstop1, eax) builder.mc.MOV(eax, builder.stack_access(self.stackpos - 1)) @@ -186,8 +186,8 @@ def newvar(self, builder): return builder.returnintvar(self.operand(builder)) - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) + def movetonewaddr(self, builder, addr): + dstop = builder.mem_access(addr) builder.mc.MOV(dstop, self.operand(builder)) class FloatConst(Const): @@ -204,15 +204,15 @@ self.rawbuf[0] = floatval def newvar(self, builder): - return builder.newfloatfrommem(None, None, 0, - rffi.cast(rffi.INT, self.rawbuf)) + return builder.newfloatfrommem((None, None, 0, + rffi.cast(rffi.INT, self.rawbuf))) def operand(self, builder): return heap64(rffi.cast(rffi.INT, self.rawbuf)) - def movetonewaddr(self, builder, arg): - dstop1 = builder.itemaddr(arg) - dstop2 = builder.itemaddr(arg, WORD) + def movetonewaddr(self, builder, addr): + dstop1 = builder.mem_access(addr) + dstop2 = builder.mem_access(addr, WORD) builder.mc.MOV(dstop1, imm(rffi.cast(rffi.INTP, self.rawbuf)[0])) builder.mc.MOV(dstop2, imm(rffi.cast(rffi.INTP, self.rawbuf)[1])) @@ -230,8 +230,8 @@ def newvar(self, builder): return builder.returnboolvar(self.operand(builder)) - def movetonewaddr(self, builder, arg): - dstop = builder.itemaddr(arg) + def movetonewaddr(self, builder, addr): + dstop = builder.mem_access(addr) builder.mc.MOV(dstop, self.operand(builder)) ##class FnPtrConst(IntConst): Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sat Apr 5 04:54:27 2008 @@ -310,30 +310,34 @@ self.mc.LEA(eax, mem(edx, offset)) return self.returnintvar(eax) - def _compute_itemaddr(self, arg, addoffset=0): - base, arraytoken, gv_index = arg + def _compute_itemaddr(self, base, arraytoken, gv_index): lengthoffset, startoffset, itemoffset = arraytoken if isinstance(gv_index, IntConst): startoffset += itemoffset * gv_index.value - return (base, None, 0, startoffset + addoffset) + return (base, None, 0, startoffset) elif itemoffset in SIZE2SHIFT: self.mc.MOV(ecx, gv_index.operand(self)) - return (base, ecx, SIZE2SHIFT[itemoffset], startoffset + - addoffset) + return (base, ecx, SIZE2SHIFT[itemoffset], startoffset) else: self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - return (base, ecx, 0, startoffset + addoffset) + return (base, ecx, 0, startoffset) - def itemaddr(self, arg, addoffset=0): + def itemaddr(self, base, arraytoken, gv_index): # uses ecx - base, arraytoken, gv_index = arg lengthoffset, startoffset, itemoffset = arraytoken + addr = self._compute_itemaddr(base, arraytoken, gv_index) if itemoffset == 1: - memSIBx = memSIB8 + return self.mem_access8(addr) else: - memSIBx = memSIB - base, reg, shift, ofs = self._compute_itemaddr(arg, addoffset) - return memSIBx(base, reg, shift, ofs) + return self.mem_access(addr) + + def mem_access(self, addr, addofs=0): + base, reg, shift, ofs = addr + return memSIB(base, reg, shift, ofs + addofs) + + def mem_access8(self, addr, addofs=0): + base, reg, shift, ofs = addr + return memSIB8(base, reg, shift, ofs + addofs) def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) @@ -341,10 +345,10 @@ if itemsize > WORD: # XXX assert not different type than float, probably # need to sneak one in arraytoken - base, reg, shift, ofs = self._compute_itemaddr((edx, arraytoken, - gv_index)) - return self.newfloatfrommem(base, reg, shift, ofs) - op = self.itemaddr((edx, arraytoken, gv_index)) + addr = self._compute_itemaddr(edx, arraytoken, + gv_index) + return self.newfloatfrommem(addr) + op = self.itemaddr(edx, arraytoken, gv_index) if itemsize < WORD: self.mc.MOVZX(eax, op) op = eax @@ -352,7 +356,7 @@ def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) - op = self.itemaddr((edx, arraytoken, gv_index)) + op = self.itemaddr(edx, arraytoken, gv_index) self.mc.LEA(eax, op) return self.returnintvar(eax) @@ -364,8 +368,8 @@ def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): _, _, itemsize = arraytoken self.mc.MOV(edx, gv_ptr.operand(self)) - destaddr = self.itemaddr((edx, arraytoken, gv_index)) - gv_value.movetonewaddr(self, (edx, arraytoken, gv_index)) + destaddr = self._compute_itemaddr(edx, arraytoken, gv_index) + gv_value.movetonewaddr(self, destaddr) #if itemsize <= WORD: # self.mc.MOV(eax, gv_value.operand(self)) # if itemsize != WORD: @@ -374,6 +378,7 @@ # return # elif itemsize == 2: # self.mc.o16() # followed by the MOV below + # ^^^^^^^^^^^^^ [fijal] what's this for? # else: # raise NotImplementedError("setarrayitme for fieldsize == 3") # self.mc.MOV(destop, eax) @@ -389,7 +394,7 @@ 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)) + op_size = self.itemaddr(None, varsizealloctoken, gv_size) self.mc.LEA(edx, op_size) self.push(edx) self.mc.CALL(rel32(gc_malloc_fnaddr())) @@ -537,7 +542,7 @@ raise NotImplementedError("Return float var not on fp stack") return res - def newfloatfrommem(self, base, reg, shift, ofs): + def newfloatfrommem(self, (base, reg, shift, ofs)): res = FloatVar(self.stackdepth + 1) self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) self.mc.PUSH(memSIB(base, reg, shift, ofs)) From fijal at codespeak.net Sat Apr 5 05:07:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 05:07:05 +0200 (CEST) Subject: [pypy-svn] r53371 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080405030705.C1F2316AB8E@codespeak.net> Author: fijal Date: Sat Apr 5 05:07:04 2008 New Revision: 53371 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_operation.py Log: refactor arrayToken to produce kindToken as well Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sat Apr 5 05:07:04 2008 @@ -39,6 +39,13 @@ p = cast(c_void_p(addr), POINTER(c_int)) p[0] = value +def map_arg(arg): + # a small helper that provides correct type signature + if isinstance(arg, lltype.Ptr): + return llmemory.Address + if isinstance(arg, (lltype.Array, lltype.Struct)): + return lltype.Void + return arg class Label(GenLabel): @@ -311,7 +318,7 @@ return self.returnintvar(eax) def _compute_itemaddr(self, base, arraytoken, gv_index): - lengthoffset, startoffset, itemoffset = arraytoken + lengthoffset, startoffset, itemoffset, _ = arraytoken if isinstance(gv_index, IntConst): startoffset += itemoffset * gv_index.value return (base, None, 0, startoffset) @@ -324,7 +331,7 @@ def itemaddr(self, base, arraytoken, gv_index): # uses ecx - lengthoffset, startoffset, itemoffset = arraytoken + lengthoffset, startoffset, itemoffset, _ = arraytoken addr = self._compute_itemaddr(base, arraytoken, gv_index) if itemoffset == 1: return self.mem_access8(addr) @@ -341,7 +348,7 @@ def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) - _, _, itemsize = arraytoken + _, _, itemsize, kindtoken = arraytoken if itemsize > WORD: # XXX assert not different type than float, probably # need to sneak one in arraytoken @@ -361,12 +368,12 @@ return self.returnintvar(eax) def genop_getarraysize(self, arraytoken, gv_ptr): - lengthoffset, startoffset, itemoffset = arraytoken + lengthoffset, startoffset, itemoffset, _ = arraytoken self.mc.MOV(edx, gv_ptr.operand(self)) return self.returnintvar(mem(edx, lengthoffset)) def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): - _, _, itemsize = arraytoken + itemsize = arraytoken[2] self.mc.MOV(edx, gv_ptr.operand(self)) destaddr = self._compute_itemaddr(edx, arraytoken, gv_index) gv_value.movetonewaddr(self, destaddr) @@ -398,7 +405,7 @@ self.mc.LEA(edx, op_size) self.push(edx) self.mc.CALL(rel32(gc_malloc_fnaddr())) - lengthoffset, _, _ = varsizealloctoken + lengthoffset = varsizealloctoken[0] self.mc.MOV(ecx, gv_size.operand(self)) self.mc.MOV(mem(eax, lengthoffset), ecx) return self.returnintvar(eax) @@ -1262,26 +1269,24 @@ arrayfield = T._arrayfld ARRAYFIELD = getattr(T, arrayfield) arraytoken = RI386GenOp.arrayToken(ARRAYFIELD) - length_offset, items_offset, item_size = arraytoken + length_offset, items_offset, item_size, _ = arraytoken arrayfield_offset = llmemory.offsetof(T, arrayfield) return (arrayfield_offset+length_offset, arrayfield_offset+items_offset, - item_size) + item_size, + '?') @classmethod @specialize.memo() def arrayToken(cls, A): return (llmemory.ArrayLengthOffset(A), llmemory.ArrayItemsOffset(A), - llmemory.ItemOffset(A.OF)) + llmemory.ItemOffset(A.OF), + LL_TO_GENVAR[map_arg(A.OF)]) @staticmethod @specialize.memo() def sigToken(FUNCTYPE): - def map_arg(arg): - if isinstance(arg, lltype.Ptr): - return llmemory.Address - return arg return ([LL_TO_GENVAR[map_arg(arg)] for arg in FUNCTYPE.ARGS if arg is not lltype.Void], LL_TO_GENVAR[map_arg(FUNCTYPE.RESULT)]) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_operation.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_operation.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_operation.py Sat Apr 5 05:07:04 2008 @@ -7,7 +7,7 @@ from pypy.rpython.memory.lltypelayout import convert_offset_to_int def conv(n): - if not isinstance(n, int): + if not isinstance(n, (int, str)): if isinstance(n, tuple): n = tuple(map(conv, n)) else: From fijal at codespeak.net Sat Apr 5 05:14:38 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 05:14:38 +0200 (CEST) Subject: [pypy-svn] r53372 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080405031438.1DAFD16AB8E@codespeak.net> Author: fijal Date: Sat Apr 5 05:14:37 2008 New Revision: 53372 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Some refactoring in order to provide better memory access Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Sat Apr 5 05:14:37 2008 @@ -85,8 +85,10 @@ return builder.stack_access64(self.stackpos) def newvar(self, builder): - raise NotImplementedError("This requires moving around float mem") - return builder.returnfloatvar(self.operand(builder)) + # XXX not tested and not sure if ever needed + raise NotImplementedError("write test first") + ofs = (builder.stackdepth - self.stackpos - 1) * WORD + return builder.newfloatfrommem(esp, None, 0, ofs) def movetonewaddr(self, builder, addr): dstop1 = builder.mem_access(addr) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sat Apr 5 05:14:37 2008 @@ -349,17 +349,8 @@ def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) _, _, itemsize, kindtoken = arraytoken - if itemsize > WORD: - # XXX assert not different type than float, probably - # need to sneak one in arraytoken - addr = self._compute_itemaddr(edx, arraytoken, - gv_index) - return self.newfloatfrommem(addr) - op = self.itemaddr(edx, arraytoken, gv_index) - if itemsize < WORD: - self.mc.MOVZX(eax, op) - op = eax - return self.returnintvar(op) + addr = self._compute_itemaddr(edx, arraytoken, gv_index) + return self.newvarfromaddr(kindtoken, addr) def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) @@ -549,6 +540,19 @@ raise NotImplementedError("Return float var not on fp stack") return res + + def newvarfromaddr(self, kindtoken, addr): + # XXX probably we can still do something here with unrolling + # iterable, but let's not be too smart... + if kindtoken == 'i': + return self.returnintvar(self.mem_access(addr)) + elif kindtoken == 'b': + return self.returnboolvar(self.mem_access(addr)) + elif kindtoken == 'f': + return self.newfloatfrommem(addr) + else: + raise NotImplementedError("Return var of kind %s" % (kindtoken,)) + def newfloatfrommem(self, (base, reg, shift, ofs)): res = FloatVar(self.stackdepth + 1) self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) From fijal at codespeak.net Sat Apr 5 05:23:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 05:23:42 +0200 (CEST) Subject: [pypy-svn] r53373 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080405032342.C33CA16AB46@codespeak.net> Author: fijal Date: Sat Apr 5 05:23:41 2008 New Revision: 53373 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Support get/set field with different types. Actually this is few lines less than not supporting it, progress Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Sat Apr 5 05:23:41 2008 @@ -58,7 +58,7 @@ builder.mc.MOV(eax, self.operand(builder)) builder.mc.MOV(dstop, eax) -class AddressVar(IntVar): +class AddrVar(IntVar): ll_type = llmemory.Address token = 'a' SIZE = 1 @@ -105,7 +105,7 @@ LL_TO_GENVAR = {} TOKEN_TO_GENVAR = {} TOKEN_TO_SIZE = {} -for value in [IntVar, FloatVar, BoolVar, AddressVar]: +for value in [IntVar, FloatVar, BoolVar, AddrVar]: assert hasattr(value, 'll_type') LL_TO_GENVAR[value.ll_type] = value.token TOKEN_TO_GENVAR[value.token] = value Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sat Apr 5 05:23:41 2008 @@ -9,7 +9,7 @@ from pypy.rpython.annlowlevel import llhelper from pypy.jit.codegen.ia32.objmodel import IntVar, FloatVar, Var,\ BoolVar, IntConst, AddrConst, BoolConst, FloatConst,\ - LL_TO_GENVAR, TOKEN_TO_SIZE, token_to_genvar, WORD + LL_TO_GENVAR, TOKEN_TO_SIZE, token_to_genvar, WORD, AddrVar DEBUG_CALL_ALIGN = True if sys.platform == 'darwin': @@ -42,10 +42,10 @@ def map_arg(arg): # a small helper that provides correct type signature if isinstance(arg, lltype.Ptr): - return llmemory.Address + arg = llmemory.Address if isinstance(arg, (lltype.Array, lltype.Struct)): - return lltype.Void - return arg + arg = lltype.Void + return LL_TO_GENVAR[arg] class Label(GenLabel): @@ -275,8 +275,10 @@ genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) - def genop_getfield(self, (offset, fieldsize), gv_ptr): + def genop_getfield(self, (offset, fieldsize, kindtoken), gv_ptr): self.mc.MOV(edx, gv_ptr.operand(self)) + return self.newvarfromaddr(kindtoken, (edx, None, 0, offset)) + if fieldsize == WORD: op = mem(edx, offset) else: @@ -298,21 +300,11 @@ def get_frame_info(self, vars_gv): return vars_gv - def genop_setfield(self, (offset, fieldsize), gv_ptr, gv_value): - self.mc.MOV(eax, gv_value.operand(self)) + def genop_setfield(self, (offset, fieldsize, kt), gv_ptr, gv_value): self.mc.MOV(edx, gv_ptr.operand(self)) - if fieldsize == 1: - self.mc.MOV(mem8(edx, offset), al) - else: - if fieldsize == 2: - self.mc.o16() # followed by the MOV below - elif fieldsize == WORD: - pass - else: - raise NotImplementedError("fieldsize != 1,2,4") - self.mc.MOV(mem(edx, offset), eax) + gv_value.movetonewaddr(self, (edx, None, 0, offset)) - def genop_getsubstruct(self, (offset, fieldsize), gv_ptr): + def genop_getsubstruct(self, (offset, fieldsize, kt), gv_ptr): self.mc.MOV(edx, gv_ptr.operand(self)) self.mc.LEA(eax, mem(edx, offset)) return self.returnintvar(eax) @@ -521,6 +513,14 @@ self.push(op) return res + def returnaddrvar(self, op): + res = AddrVar(self.stackdepth) + if op is None: + self.push(imm(0)) + else: + self.push(op) + return res + def returnboolvar(self, op): if op is eax: pass @@ -546,6 +546,8 @@ # iterable, but let's not be too smart... if kindtoken == 'i': return self.returnintvar(self.mem_access(addr)) + elif kindtoken == 'a': + return self.returnaddrvar(self.mem_access(addr)) elif kindtoken == 'b': return self.returnboolvar(self.mem_access(addr)) elif kindtoken == 'f': @@ -1251,7 +1253,7 @@ fieldsize = 0 # not useful for getsubstruct else: fieldsize = llmemory.sizeof(FIELD) - return (llmemory.offsetof(T, name), fieldsize) + return (llmemory.offsetof(T, name), fieldsize, map_arg(FIELD)) @staticmethod @specialize.memo() @@ -1286,14 +1288,13 @@ return (llmemory.ArrayLengthOffset(A), llmemory.ArrayItemsOffset(A), llmemory.ItemOffset(A.OF), - LL_TO_GENVAR[map_arg(A.OF)]) + map_arg(A.OF)) @staticmethod @specialize.memo() def sigToken(FUNCTYPE): - return ([LL_TO_GENVAR[map_arg(arg)] for arg in FUNCTYPE.ARGS if arg - is not lltype.Void], - LL_TO_GENVAR[map_arg(FUNCTYPE.RESULT)]) + return ([map_arg(arg) for arg in FUNCTYPE.ARGS if arg + is not lltype.Void], map_arg(FUNCTYPE.RESULT)) @staticmethod def erasedType(T): From fijal at codespeak.net Sat Apr 5 05:36:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 05:36:06 +0200 (CEST) Subject: [pypy-svn] r53374 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080405033606.E75F016AAFD@codespeak.net> Author: fijal Date: Sat Apr 5 05:36:06 2008 New Revision: 53374 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: add a new test for interior access of float stuff Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sat Apr 5 05:36:06 2008 @@ -2330,6 +2330,43 @@ result = fnptr(42) assert result == 47 + def test_interior_access_float(self): + if self.RGenOpPacked is None: + py.test.skip("requires RGenOpPacked") + T = lltype.Struct('T', ('x', lltype.Float)) + A = lltype.Array(T) + S = lltype.GcStruct('S', ('a', A)) + rgenop = self.RGenOpPacked() + FUNC = lltype.FuncType([lltype.Float], lltype.Float) + sigtoken = rgenop.sigToken(FUNC) + builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, + "interior_access_float") + builder.start_writing() + gv_s = builder.genop_malloc_varsize(rgenop.varsizeAllocToken(S), + rgenop.genconst(5)) + # generate an expanded 'setinteriorfield' + gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s) + gv_t1 = builder.genop_getarraysubstruct(rgenop.arrayToken(A), + gv_a1, rgenop.genconst(3)) + builder.genop_setfield(rgenop.fieldToken(T, 'x'), gv_t1, gv_x) + # generate an expanded 'getinteriorfield' + gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s) + gv_t1 = builder.genop_getarraysubstruct(rgenop.arrayToken(A), + gv_a1, rgenop.genconst(3)) + gv_y = builder.genop_getfield(rgenop.fieldToken(T, 'x'), gv_t1) + # generate an expanded 'getinteriorarraysize' + gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s) + gv_z = builder.genop_getarraysize(rgenop.arrayToken(A), gv_a1) + # return + gv_z1 = builder.genop1('cast_int_to_float', gv_z) + gv_result = builder.genop2("float_add", gv_y, gv_z1) + builder.finish_and_return(sigtoken, gv_result) + builder.end() + + fnptr = self.cast_whatever(gv_fn, [lltype.Float], lltype.Float) + result = fnptr(42.3) + assert result == 42.3 + 5 + def test_void_return(self): # XXX minimal test only rgenop = self.RGenOp() From arigo at codespeak.net Sat Apr 5 09:36:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 5 Apr 2008 09:36:47 +0200 (CEST) Subject: [pypy-svn] r53375 - pypy/branch/jit-hotpath/pypy/translator Message-ID: <20080405073647.E182616AB85@codespeak.net> Author: arigo Date: Sat Apr 5 09:36:46 2008 New Revision: 53375 Modified: pypy/branch/jit-hotpath/pypy/translator/driver.py Log: Need to mention the ia32 backend here. Modified: pypy/branch/jit-hotpath/pypy/translator/driver.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/driver.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/driver.py Sat Apr 5 09:36:46 2008 @@ -422,6 +422,9 @@ if cpu == 'i386': from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp RGenOp.MC_SIZE = 32 * 1024 * 1024 + elif cpu == 'ia32': + from pypy.jit.codegen.ia32.rgenop import RI386GenOp as RGenOp + RGenOp.MC_SIZE = 32 * 1024 * 1024 elif cpu == 'ppc': from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp RGenOp.MC_SIZE = 32 * 1024 * 1024 From arigo at codespeak.net Sat Apr 5 10:13:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 5 Apr 2008 10:13:56 +0200 (CEST) Subject: [pypy-svn] r53376 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080405081356.A8B5616ABA8@codespeak.net> Author: arigo Date: Sat Apr 5 10:13:55 2008 New Revision: 53376 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: * Make a fast path version of load_int(). * Add a test that needs more than 127 (actually more than 255) variables, to check the load_int() logic. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py Sat Apr 5 10:13:55 2008 @@ -6,7 +6,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.jit.timeshifter import rvalue, rcontainer from pypy.jit.timeshifter.greenkey import empty_key, GreenKey -from pypy.jit.rainbow.interpreter import SIGN_EXTEND2, arguments +from pypy.jit.rainbow.interpreter import arguments class FallStoreBackMemo(object): @@ -205,14 +205,21 @@ def load_byte(self): pc = self.pc - assert pc >= 0 result = ord(self.bytecode.code[pc]) self.pc = pc + 1 return result def load_int(self): - result = 0 - shift = 0 + pc = self.pc + result = ord(self.bytecode.code[pc]) + self.pc = pc + 1 + if result > 0x7F: + result = self._load_larger_int(result) + return result + + def _load_larger_int(self, result): # slow path + result = result & 0x7F + shift = 7 pc = self.pc while 1: byte = ord(self.bytecode.code[pc]) @@ -223,10 +230,10 @@ break self.pc = pc return intmask(result) + _load_larger_int._dont_inline_ = True def load_4byte(self): pc = self.pc - assert pc >= 0 result = ((ord(self.bytecode.code[pc + 0]) << 24) | (ord(self.bytecode.code[pc + 1]) << 16) | (ord(self.bytecode.code[pc + 2]) << 8) | Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Sat Apr 5 10:13:55 2008 @@ -1,4 +1,4 @@ -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.objectmodel import we_are_translated, CDefinedIntSymbolic, noop from pypy.rlib.debug import debug_print @@ -75,8 +75,6 @@ dump.dump_bytecode(self, file=file) print >> file -SIGN_EXTEND2 = 1 << 15 - class STOP(object): pass STOP = STOP() @@ -255,7 +253,7 @@ self.queue = rtimeshift.DispatchQueue(bytecode.num_mergepoints) rtimeshift.enter_frame(self.jitstate, self.queue) self.frame = self.jitstate.frame - self.frame.pc = 0 + self.frame.pc = r_uint(0) self.frame.bytecode = bytecode self.frame.local_boxes = redargs self.frame.local_green = greenargs @@ -362,8 +360,16 @@ return self.frame.bytecode def load_int(self): - result = 0 - shift = 0 + pc = self.frame.pc + result = ord(self.frame.bytecode.code[pc]) + self.frame.pc = pc + 1 + if result > 0x7F: + result = self._load_larger_int(result) + return result + + def _load_larger_int(self, result): # slow path + result = result & 0x7F + shift = 7 pc = self.frame.pc while 1: byte = ord(self.frame.bytecode.code[pc]) @@ -374,20 +380,19 @@ break self.frame.pc = pc return intmask(result) + _load_larger_int._dont_inline_ = True def load_4byte(self): pc = self.frame.pc - assert pc >= 0 - result = ((ord(self.frame.bytecode.code[pc + 0]) << 24) | - (ord(self.frame.bytecode.code[pc + 1]) << 16) | - (ord(self.frame.bytecode.code[pc + 2]) << 8) | - (ord(self.frame.bytecode.code[pc + 3]) << 0)) + result = ((r_uint(ord(self.frame.bytecode.code[pc + 0])) << 24) | + (r_uint(ord(self.frame.bytecode.code[pc + 1])) << 16) | + (r_uint(ord(self.frame.bytecode.code[pc + 2])) << 8) | + (r_uint(ord(self.frame.bytecode.code[pc + 3])) << 0)) self.frame.pc = pc + 4 - return intmask(result) + return result def load_bool(self): pc = self.frame.pc - assert pc >= 0 result = ord(self.frame.bytecode.code[pc]) self.frame.pc = pc + 1 return bool(result) @@ -899,7 +904,7 @@ def hp_direct_call(self, greenargs, redargs, targetbytecode): frame = rtimeshift.VirtualFrame(self.frame, None) self.frame = self.jitstate.frame = frame - frame.pc = 0 + frame.pc = r_uint(0) frame.bytecode = targetbytecode frame.local_boxes = redargs frame.local_green = greenargs Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Sat Apr 5 10:13:55 2008 @@ -1934,6 +1934,97 @@ res = self.interpret(main2, [5, 6], policy=StopAtXPolicy(g)) assert res == 11 + + def test_manymanyvars(self): + + def h(i00, i01, i02, i03, i04, i05, i06, i07, i08, i09, + i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, + i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, + i30, i31, i32, i33, i34, i35, i36, i37, i38, i39, + i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, + i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, + i60, i61, i62, i63, i64, i65, i66, i67, i68, i69, + i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, + i80, i81, i82, i83, i84, i85, i86, i87, i88, i89, + i90, i91, i92, i93, i94, i95, i96, i97, i98, i99, + j00, j01, j02, j03, j04, j05, j06, j07, j08, j09, + j10, j11, j12, j13, j14, j15, j16, j17, j18, j19, + j20, j21, j22, j23, j24, j25, j26, j27, j28, j29, + j30, j31, j32, j33, j34, j35, j36, j37, j38, j39, + j40, j41, j42, j43, j44, j45, j46, j47, j48, j49, + j50, j51, j52, j53, j54, j55, j56, j57, j58, j59, + j60, j61, j62, j63, j64, j65, j66, j67, j68, j69, + j70, j71, j72, j73, j74, j75, j76, j77, j78, j79, + j80, j81, j82, j83, j84, j85, j86, j87, j88, j89, + j90, j91, j92, j93, j94, j95, j96, j97, j98, j99): + return (i00*0 + i01*1 + i02*2 + i03*3 + i04*4 + + i05*5 + i06*6 + i07*7 + i08*8 + i09*9 + + i10*10 + i11*11 + i12*12 + i13*13 + i14*14 + + i15*15 + i16*16 + i17*17 + i18*18 + i19*19 + + i20*20 + i21*21 + i22*22 + i23*23 + i24*24 + + i25*25 + i26*26 + i27*27 + i28*28 + i29*29 + + i30*30 + i31*31 + i32*32 + i33*33 + i34*34 + + i35*35 + i36*36 + i37*37 + i38*38 + i39*39 + + i40*40 + i41*41 + i42*42 + i43*43 + i44*44 + + i45*45 + i46*46 + i47*47 + i48*48 + i49*49 + + i50*50 + i51*51 + i52*52 + i53*53 + i54*54 + + i55*55 + i56*56 + i57*57 + i58*58 + i59*59 + + i60*60 + i61*61 + i62*62 + i63*63 + i64*64 + + i65*65 + i66*66 + i67*67 + i68*68 + i69*69 + + i70*70 + i71*71 + i72*72 + i73*73 + i74*74 + + i75*75 + i76*76 + i77*77 + i78*78 + i79*79 + + i80*80 + i81*81 + i82*82 + i83*83 + i84*84 + + i85*85 + i86*86 + i87*87 + i88*88 + i89*89 + + i90*90 + i91*91 + i92*92 + i93*93 + i94*94 + + i95*95 + i96*96 + i97*97 + i98*98 + i99*99 + + j00*0 + j01*1 + j02*2 + j03*3 + j04*4 + + j05*5 + j06*6 + j07*7 + j08*8 + j09*9 + + j10*10 + j11*11 + j12*12 + j13*13 + j14*14 + + j15*15 + j16*16 + j17*17 + j18*18 + j19*19 + + j20*20 + j21*21 + j22*22 + j23*23 + j24*24 + + j25*25 + j26*26 + j27*27 + j28*28 + j29*29 + + j30*30 + j31*31 + j32*32 + j33*33 + j34*34 + + j35*35 + j36*36 + j37*37 + j38*38 + j39*39 + + j40*40 + j41*41 + j42*42 + j43*43 + j44*44 + + j45*45 + j46*46 + j47*47 + j48*48 + j49*49 + + j50*50 + j51*51 + j52*52 + j53*53 + j54*54 + + j55*55 + j56*56 + j57*57 + j58*58 + j59*59 + + j60*60 + j61*61 + j62*62 + j63*63 + j64*64 + + j65*65 + j66*66 + j67*67 + j68*68 + j69*69 + + j70*70 + j71*71 + j72*72 + j73*73 + j74*74 + + j75*75 + j76*76 + j77*77 + j78*78 + j79*79 + + j80*80 + j81*81 + j82*82 + j83*83 + j84*84 + + j85*85 + j86*86 + j87*87 + j88*88 + j89*89 + + j90*90 + j91*91 + j92*92 + j93*93 + j94*94 + + j95*95 + j96*96 + j97*97 + j98*98 + j99*99) + + def f(n): + return h( + n+0, n+1, n+2, n+3, n+4, n+5, n+6, n+7, n+8, n+9, + n+10, n+11, n+12, n+13, n+14, n+15, n+16, n+17, n+18, n+19, + n+20, n+21, n+22, n+23, n+24, n+25, n+26, n+27, n+28, n+29, + n+30, n+31, n+32, n+33, n+34, n+35, n+36, n+37, n+38, n+39, + n+40, n+41, n+42, n+43, n+44, n+45, n+46, n+47, n+48, n+49, + n+50, n+51, n+52, n+53, n+54, n+55, n+56, n+57, n+58, n+59, + n+60, n+61, n+62, n+63, n+64, n+65, n+66, n+67, n+68, n+69, + n+70, n+71, n+72, n+73, n+74, n+75, n+76, n+77, n+78, n+79, + n+80, n+81, n+82, n+83, n+84, n+85, n+86, n+87, n+88, n+89, + n+90, n+91, n+92, n+93, n+94, n+95, n+96, n+97, n+98, n+99, + n-0, n-1, n-2, n-3, n-4, n-5, n-6, n-7, n-8, n-9, + n-10, n-11, n-12, n-13, n-14, n-15, n-16, n-17, n-18, n-19, + n-20, n-21, n-22, n-23, n-24, n-25, n-26, n-27, n-28, n-29, + n-30, n-31, n-32, n-33, n-34, n-35, n-36, n-37, n-38, n-39, + n-40, n-41, n-42, n-43, n-44, n-45, n-46, n-47, n-48, n-49, + n-50, n-51, n-52, n-53, n-54, n-55, n-56, n-57, n-58, n-59, + n-60, n-61, n-62, n-63, n-64, n-65, n-66, n-67, n-68, n-69, + n-70, n-71, n-72, n-73, n-74, n-75, n-76, n-77, n-78, n-79, + n-80, n-81, n-82, n-83, n-84, n-85, n-86, n-87, n-88, n-89, + n-90, n-91, n-92, n-93, n-94, n-95, n-96, n-97, n-98, n-99) + + res = self.interpret(f, [42]) + assert res == f(42) + + class TestLLType(SimpleTests): type_system = "lltype" From antocuni at codespeak.net Sat Apr 5 10:33:19 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 5 Apr 2008 10:33:19 +0200 (CEST) Subject: [pypy-svn] r53377 - in pypy/branch/less-meta-instances/pypy: rpython/lltypesystem translator/backendopt Message-ID: <20080405083319.96B8F16AB54@codespeak.net> Author: antocuni Date: Sat Apr 5 10:33:18 2008 New Revision: 53377 Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py Log: fix inline.py to use the new interface for getruntime(); relax a bit the assert in getruntime to allow also a subtype of CLASSTYPE Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py Sat Apr 5 10:33:18 2008 @@ -168,7 +168,7 @@ return vtable def getruntime(self, expected_type): - assert expected_type == CLASSTYPE + assert lltype.castable(CLASSTYPE, expected_type) >= 0 return self.getvtable() def setup_vtable(self, vtable, rsubcls): Modified: pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py (original) +++ pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py Sat Apr 5 10:33:18 2008 @@ -388,7 +388,7 @@ classdef = self.lltype_to_classdef[VALUE] rtyper = self.translator.rtyper classrepr = rclass.getclassrepr(rtyper, classdef) - vtable = classrepr.getruntime() + vtable = classrepr.getruntime(classrepr.lowleveltype) var_etype = copiedlink.args[0] var_evalue = copiedlink.args[1] for exceptionlink in afterblock.exits[1:]: From arigo at codespeak.net Sat Apr 5 10:54:25 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 5 Apr 2008 10:54:25 +0200 (CEST) Subject: [pypy-svn] r53378 - in pypy/branch/less-meta-instances/pypy: rpython/lltypesystem translator/backendopt Message-ID: <20080405085425.553D516AB7A@codespeak.net> Author: arigo Date: Sat Apr 5 10:54:24 2008 New Revision: 53378 Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py Log: Refix inline.py to pass to getruntime() exactly the type that it expects. Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rclass.py Sat Apr 5 10:54:24 2008 @@ -168,7 +168,7 @@ return vtable def getruntime(self, expected_type): - assert lltype.castable(CLASSTYPE, expected_type) >= 0 + assert expected_type == CLASSTYPE return self.getvtable() def setup_vtable(self, vtable, rsubcls): Modified: pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py (original) +++ pypy/branch/less-meta-instances/pypy/translator/backendopt/inline.py Sat Apr 5 10:54:24 2008 @@ -378,7 +378,8 @@ # this rewiring does not always succeed. in the cases where it doesn't # there will be generic code inserted rclass = self.translator.rtyper.type_system.rclass - exc_match = self.translator.rtyper.getexceptiondata().fn_exception_match + excdata = self.translator.rtyper.getexceptiondata() + exc_match = excdata.fn_exception_match for link in self.entrymap[self.graph_to_inline.exceptblock]: copiedblock = self.copy_block(link.prevblock) VALUE, copiedlink = _find_exception_type(copiedblock) @@ -388,7 +389,7 @@ classdef = self.lltype_to_classdef[VALUE] rtyper = self.translator.rtyper classrepr = rclass.getclassrepr(rtyper, classdef) - vtable = classrepr.getruntime(classrepr.lowleveltype) + vtable = classrepr.getruntime(excdata.lltype_of_exception_type) var_etype = copiedlink.args[0] var_evalue = copiedlink.args[1] for exceptionlink in afterblock.exits[1:]: From antocuni at codespeak.net Sat Apr 5 11:31:33 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 5 Apr 2008 11:31:33 +0200 (CEST) Subject: [pypy-svn] r53379 - in pypy/branch/less-meta-instances/pypy: annotation translator/cli Message-ID: <20080405093133.2FB8516AB9D@codespeak.net> Author: antocuni Date: Sat Apr 5 11:31:31 2008 New Revision: 53379 Modified: pypy/branch/less-meta-instances/pypy/annotation/model.py pypy/branch/less-meta-instances/pypy/translator/cli/function.py pypy/branch/less-meta-instances/pypy/translator/cli/opcodes.py Log: fix gencli Modified: pypy/branch/less-meta-instances/pypy/annotation/model.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/annotation/model.py (original) +++ pypy/branch/less-meta-instances/pypy/annotation/model.py Sat Apr 5 11:31:31 2008 @@ -591,6 +591,8 @@ return s_val.ootype if isinstance(s_val, SomeOOStaticMeth): return s_val.method + if isinstance(s_val, SomeOOClass): + return ootype.Class if isinstance(s_val, SomeInteriorPtr): p = s_val.ll_ptrtype if 0 in p.offsets: Modified: pypy/branch/less-meta-instances/pypy/translator/cli/function.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/translator/cli/function.py (original) +++ pypy/branch/less-meta-instances/pypy/translator/cli/function.py Sat Apr 5 11:31:31 2008 @@ -39,7 +39,7 @@ 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 + ll_exc = ll_meta_exc._INSTANCE NATIVE_INSTANCE = ll_exc._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE is None: OOFunction.record_ll_meta_exc(self, ll_meta_exc) @@ -107,7 +107,7 @@ def begin_catch(self, llexitcase): ll_meta_exc = llexitcase - ll_exc = ll_meta_exc._inst.class_._INSTANCE + ll_exc = ll_meta_exc._INSTANCE cts_exc = self.cts.lltype_to_cts(ll_exc) self.ilasm.begin_catch(cts_exc.classname()) @@ -129,10 +129,10 @@ 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.ilasm.opcode('dup') self.store(link.last_exc_value) - self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) - self.store(link.last_exception) + #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) Modified: pypy/branch/less-meta-instances/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/less-meta-instances/pypy/translator/cli/opcodes.py Sat Apr 5 11:31:31 2008 @@ -49,6 +49,7 @@ 'cli_fieldinfo_for_const': [FieldInfoForConst], 'oois': 'ceq', 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not, + 'classof': [PushAllArgs, 'callvirt instance [mscorlib]System.Type object::GetType()'], 'instanceof': [CastTo, 'ldnull', 'cgt.un'], 'subclassof': [PushAllArgs, 'call bool [pypylib]pypy.runtime.Utils::SubclassOf(class [mscorlib]System.Type, class[mscorlib]System.Type)'], 'ooidentityhash': [PushAllArgs, 'callvirt instance int32 object::GetHashCode()'], From cfbolz at codespeak.net Sat Apr 5 12:55:00 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 12:55:00 +0200 (CEST) Subject: [pypy-svn] r53381 - pypy/branch/jit-float-support Message-ID: <20080405105500.29AD616AB9A@codespeak.net> Author: cfbolz Date: Sat Apr 5 12:54:58 2008 New Revision: 53381 Removed: pypy/branch/jit-float-support/ Log: kill unused branch From cfbolz at codespeak.net Sat Apr 5 13:36:25 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 13:36:25 +0200 (CEST) Subject: [pypy-svn] r53382 - pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter Message-ID: <20080405113625.2D19C16A5C8@codespeak.net> Author: cfbolz Date: Sat Apr 5 13:36:18 2008 New Revision: 53382 Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py Log: cleanups Modified: pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py (original) +++ pypy/branch/jit-hotpath/pypy/lang/prolog/interpreter/engine.py Sat Apr 5 13:36:18 2008 @@ -39,6 +39,7 @@ return self.continuation.call(engine, choice_point=False) class TrailChunk(object): + _immutable_ = True def __init__(self, prev=None): self.trail = [] self.prev = prev @@ -290,13 +291,11 @@ continuation) raise else: - inline = rule.body is None # inline facts try: # for the last rule (rulechain is None), this will always # return, because choice_point is False result = self.try_rule(rule, query, continuation, - choice_point=choice_point, - inline=inline) + choice_point=choice_point) self.discard(oldstate) return result except UnificationFailed: @@ -305,8 +304,7 @@ rule = rulechain.rule rulechain = rulechain.next - def try_rule(self, rule, query, continuation=DONOTHING, choice_point=True, - inline=False): + def try_rule(self, rule, query, continuation=DONOTHING, choice_point=True): if not choice_point: return (TRY_RULE, query, continuation, rule) return self.main_loop(TRY_RULE, query, continuation, rule) From cfbolz at codespeak.net Sat Apr 5 13:50:34 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 13:50:34 +0200 (CEST) Subject: [pypy-svn] r53383 - in pypy/branch/jit-hotpath/pypy/jit/hintannotator: . test Message-ID: <20080405115034.09D1116AB0F@codespeak.net> Author: cfbolz Date: Sat Apr 5 13:50:33 2008 New Revision: 53383 Modified: pypy/branch/jit-hotpath/pypy/jit/hintannotator/model.py pypy/branch/jit-hotpath/pypy/jit/hintannotator/test/test_annotator.py Log: add float operations to the hintannotator Modified: pypy/branch/jit-hotpath/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/hintannotator/model.py Sat Apr 5 13:50:33 2008 @@ -12,12 +12,16 @@ indirect_call int_is_true int_neg int_abs int_invert bool_not int_neg_ovf int_abs_ovf + float_is_true uint_is_true cast_int_to_char + cast_int_to_float + cast_float_to_int cast_int_to_uint cast_uint_to_int cast_char_to_int cast_bool_to_int + cast_bool_to_float cast_ptr_to_int ptr_nonzero ptr_iszero @@ -43,9 +47,12 @@ int_floordiv_ovf int_lshift_ovf int_add_nonneg_ovf uint_add uint_sub uint_mul uint_mod uint_and uint_lshift uint_rshift uint_floordiv + float_add float_sub float_mul float_truediv char_gt char_lt char_le char_ge char_eq char_ne int_gt int_lt int_le int_ge int_eq int_ne uint_gt uint_lt uint_le uint_ge uint_eq uint_ne + + float_gt float_lt float_le float_ge float_eq float_ne getarrayitem setarrayitem getarraysubstruct ptr_eq ptr_ne""".split() Modified: pypy/branch/jit-hotpath/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/hintannotator/test/test_annotator.py Sat Apr 5 13:50:33 2008 @@ -117,6 +117,21 @@ assert len(hs.origins) == 4 assert hs.concretetype == lltype.Signed + def test_simple_float(self): + def ll_function(x, y): + if x: + z = x+y * y + else: + z = x-y / y + if int(x): + z += x > y + x < y + z == y + z != y + else: + z += x >= y + x <= y + return z + hs = self.hannotate(ll_function, [float, float]) + assert isinstance(hs, SomeLLAbstractConstant) + assert hs.concretetype == lltype.Float + def test_simple_hint_result(self): def ll_function(cond, x,y): if cond: From cfbolz at codespeak.net Sat Apr 5 14:02:00 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 14:02:00 +0200 (CEST) Subject: [pypy-svn] r53384 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080405120200.854AF16AB57@codespeak.net> Author: cfbolz Date: Sat Apr 5 14:01:59 2008 New Revision: 53384 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Log: useful (commented out) pdb lines for debugging Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Sat Apr 5 14:01:59 2008 @@ -346,6 +346,8 @@ try: match = frozen.exactmatch(jitstate, outgoingvarboxes, memo) except rvalue.DontMerge: + #import sys, pdb + #pdb.post_mortem(sys.exc_info()[2]) continue if match: linkargs = [] From cfbolz at codespeak.net Sat Apr 5 14:03:33 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 14:03:33 +0200 (CEST) Subject: [pypy-svn] r53385 - in pypy/branch/jit-hotpath/pypy/jit: rainbow/test timeshifter timeshifter/test Message-ID: <20080405120333.1A38B16AB77@codespeak.net> Author: cfbolz Date: Sat Apr 5 14:03:32 2008 New Revision: 53385 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_rcontainer.py Log: ripping out access info again Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hotpath.py Sat Apr 5 14:03:32 2008 @@ -562,6 +562,7 @@ # self.check_insns_in_loops(malloc=2) I would like this, but fails right now def test_loop_with_more_and_more_structs(self): + py.test.skip("I want this to pass") myjitdriver = JitDriver(greens = [], reds = ['n1', 'res']) Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py Sat Apr 5 14:03:32 2008 @@ -240,22 +240,6 @@ return result -class AccessInfo(object): - def __init__(self): - self.read_fields = 0 - self.write_fields = 0 - # XXX what else is needed? - - def __repr__(self): - return "" % ( - self.read_fields, self.write_fields) - - def copy(self): - result = AccessInfo() - result.read_fields = self.read_fields - result.write_fields = self.write_fields - - class AbstractPtrRedBox(RedBox): """ Base class for PtrRedBox (lltype) and InstanceRedBox (ootype) @@ -268,7 +252,6 @@ if genvar is not None and genvar.is_const: known_nonzero = bool(self._revealconst(genvar)) self.known_nonzero = known_nonzero - self.access_info = AccessInfo() def setgenvar(self, newgenvar): RedBox.setgenvar(self, newgenvar) @@ -313,8 +296,6 @@ boxmemo[self] = result if self.content: result.content = self.content.copy(memo) - # XXX is this correct? - result.access_info = self.access_info assert isinstance(result, AbstractPtrRedBox) return result @@ -355,7 +336,6 @@ boxmemo[self] = result result.fz_partialcontent = content.partialfreeze(memo) return result - result.fz_access_info = self.access_info.copy() boxmemo[self] = result return result @@ -395,7 +375,6 @@ self.content.enter_block(incoming, memo) def op_getfield(self, jitstate, fielddesc): - self.access_info.read_fields += 1 self.learn_nonzeroness(jitstate, True) if self.content is not None: box = self.content.op_getfield(jitstate, fielddesc) @@ -408,7 +387,6 @@ return box def op_setfield(self, jitstate, fielddesc, valuebox): - self.access_info.write_fields += 1 self.learn_nonzeroness(jitstate, True) gv_ptr = self.genvar if gv_ptr: @@ -613,10 +591,6 @@ match = False if not memo.force_merge: if isinstance(box.content, VirtualContainer): - # heuristic: if a virtual is neither written to, nor read from - # it might not be "important enough" to keep it virtual - if not box.access_info.read_fields: - return match raise DontMerge # XXX recursive data structures? return match @@ -649,12 +623,8 @@ exact = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo) match = exact and partialdatamatch if not memo.force_merge and not match: - # heuristic: if a virtual is neither written to, nor read from - # it might not be "important enough" to keep it virtual from pypy.jit.timeshifter.rcontainer import VirtualContainer if isinstance(box.content, VirtualContainer): - if not box.access_info.read_fields: - return match raise DontMerge # XXX recursive data structures? return match @@ -664,7 +634,6 @@ def exactmatch(self, box, outgoingvarboxes, memo): assert isinstance(box, AbstractPtrRedBox) if box.genvar: - # XXX should we consider self.access_info here too? raise DontMerge else: assert box.content is not None Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_rcontainer.py Sat Apr 5 14:03:32 2008 @@ -110,7 +110,6 @@ # do a getfield to prevent a merge box2 = oldbox.op_getfield(jitstate, self.fielddesc) assert box2 is constbox20 - assert oldbox.access_info.read_fields == 1 frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that ptrbox does not match the frozen virtual struct ever py.test.raises(DontMerge, self.match, frozenbox, ptrbox, [ptrbox]) @@ -119,22 +118,6 @@ frozenptrbox = ptrbox.freeze(rvalue.freeze_memo()) py.test.raises(DontMerge, self.match, frozenptrbox, oldbox, [oldbox]) - def test_merge_with_ptrvar_virtual_never_read(self): - DontMerge = rvalue.DontMerge - V0 = FakeGenVar() - ptrbox = rvalue.PtrRedBox(V0) - jitstate = FakeJITState() - S = self.STRUCT - constbox20 = makebox(20) - oldbox = vmalloc(S, constbox20) - - frozenptrbox = ptrbox.freeze(rvalue.freeze_memo()) - assert self.match(frozenptrbox, oldbox, [oldbox]) - - # try it the other way round - # XXX what should happen here? - #frozenbox = oldbox.freeze(rvalue.freeze_memo()) - #self.match(frozenbox, ptrbox, [ptrbox]) def test_nested_structure_no_vars(self): NESTED = self.NESTEDSTRUCT From antocuni at codespeak.net Sat Apr 5 14:08:21 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 5 Apr 2008 14:08:21 +0200 (CEST) Subject: [pypy-svn] r53386 - in pypy/branch/less-meta-instances/pypy: rpython/ootypesystem translator/cli translator/cli/test Message-ID: <20080405120821.6E4FB16AB96@codespeak.net> Author: antocuni Date: Sat Apr 5 14:08:20 2008 New Revision: 53386 Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/ootype.py pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rootype.py pypy/branch/less-meta-instances/pypy/translator/cli/database.py pypy/branch/less-meta-instances/pypy/translator/cli/test/runtest.py Log: fix the exceptiontransformer for ootype and cli Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/ootype.py Sat Apr 5 14:08:20 2008 @@ -47,7 +47,10 @@ def _defl(self): return nullruntimeclass - + + def _example(self): + return _class(ROOT) + Class = Class() class Instance(OOType): @@ -780,6 +783,7 @@ self._INSTANCE = INSTANCE nullruntimeclass = _class(None) +Class._null = nullruntimeclass class _instance(object): Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rootype.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rootype.py (original) +++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rootype.py Sat Apr 5 14:08:20 2008 @@ -32,6 +32,11 @@ class OOClassRepr(Repr): lowleveltype = Class + + def rtype_is_true(self, hop): + vlist = hop.inputargs(self) + return hop.genop('oononnull', vlist, resulttype=ootype.Bool) + ooclass_repr = OOClassRepr() class OOInstanceRepr(Repr): Modified: pypy/branch/less-meta-instances/pypy/translator/cli/database.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/translator/cli/database.py (original) +++ pypy/branch/less-meta-instances/pypy/translator/cli/database.py Sat Apr 5 14:08:20 2008 @@ -7,9 +7,9 @@ from pypy.translator.cli.comparer import EqualityComparer from pypy.translator.cli.node import Node from pypy.translator.cli.support import string_literal, Counter +from pypy.translator.cli.cts import types from pypy.rpython.ootypesystem import ootype from pypy.rpython.ootypesystem.module import ll_os -from pypy.translator.cli.opcodes import opcodes from pypy.translator.cli import dotnet from pypy.rlib.objectmodel import CDefinedIntSymbolic from pypy.translator.oosupport.database import Database as OODatabase @@ -130,6 +130,8 @@ return name def class_name(self, INSTANCE): + if INSTANCE is ootype.ROOT: + return types.object.classname() try: NATIVE_INSTANCE = INSTANCE._hints['NATIVE_INSTANCE'] return NATIVE_INSTANCE._name Modified: pypy/branch/less-meta-instances/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/branch/less-meta-instances/pypy/translator/cli/test/runtest.py (original) +++ pypy/branch/less-meta-instances/pypy/translator/cli/test/runtest.py Sat Apr 5 14:08:20 2008 @@ -100,7 +100,7 @@ if hasattr(self.db, 'exceptiontransformer'): ilasm.opcode('call', 'bool rpyexc_occured()') ilasm.opcode('brfalse', 'print_result') # no exceptions - ilasm.opcode('call', 'Object rpyexc_fetch_value()') + ilasm.opcode('call', '[mscorlib]System.Object rpyexc_fetch_value()') ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') ilasm.opcode('br', 'return') From cfbolz at codespeak.net Sat Apr 5 15:44:04 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 15:44:04 +0200 (CEST) Subject: [pypy-svn] r53389 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080405134404.8519F16A944@codespeak.net> Author: cfbolz Date: Sat Apr 5 15:44:03 2008 New Revision: 53389 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: puh, that took way too long: a test for a bug with red bool vars Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Sat Apr 5 15:44:03 2008 @@ -1832,6 +1832,44 @@ assert res == 7 self.check_insns(int_add=2) + def test_freeze_booleffects_correctly(self): + py.test.skip("shows bug in BoolRedVars") + class B(object): + def __init__(self, data, last=None): + self.data = data + self.last = last + class A(object): + pass + def g(a): + result = None + for i in range(a): + result = B(i, result) + return result + def f(x, y): + hint(None, global_merge_point=True) + a = A() + a.b = g(x) + + cond = a.b is None + if y: + result = y + else: + cond = bool(x) + result = 50 + if cond: + result -= 5 + else: + result += a.b.data + if a.b is not None: + result -= 4 + else: + result -= 5 + return result + res = self.interpret(f, [0, 0], policy=StopAtXPolicy(g)) + assert res == f(0, 0) + self.check_insns(int_add=2) + + def test_ptrequality(self): class A(object): _immutable_ = True From cfbolz at codespeak.net Sat Apr 5 17:56:40 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 17:56:40 +0200 (CEST) Subject: [pypy-svn] r53393 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080405155640.7B98016A875@codespeak.net> Author: cfbolz Date: Sat Apr 5 17:56:39 2008 New Revision: 53393 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: _really_ write a failing test Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Sat Apr 5 17:56:39 2008 @@ -1833,8 +1833,9 @@ self.check_insns(int_add=2) def test_freeze_booleffects_correctly(self): - py.test.skip("shows bug in BoolRedVars") + py.test.skip("fix this!") class B(object): + _immutable_ = True def __init__(self, data, last=None): self.data = data self.last = last @@ -1845,29 +1846,30 @@ for i in range(a): result = B(i, result) return result + def h(cond): + return not cond + globalb = B(4) def f(x, y): hint(None, global_merge_point=True) + b = g(x) a = A() - a.b = g(x) + a.b = b - cond = a.b is None + cond = a.b is globalb if y: result = y else: - cond = bool(x) result = 50 - if cond: - result -= 5 - else: + cond = h(cond) + if not cond: result += a.b.data - if a.b is not None: - result -= 4 else: - result -= 5 + result -= a.b.data return result - res = self.interpret(f, [0, 0], policy=StopAtXPolicy(g)) - assert res == f(0, 0) - self.check_insns(int_add=2) + res_normal = f(10, 0) + res = self.interpret(f, [10, 0], policy=StopAtXPolicy(g, h)) + assert res == res_normal + self.check_insns(getfield=5) def test_ptrequality(self): From cfbolz at codespeak.net Sat Apr 5 18:00:11 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 18:00:11 +0200 (CEST) Subject: [pypy-svn] r53394 - in pypy/branch/jit-hotpath/pypy/jit: rainbow/test timeshifter Message-ID: <20080405160011.591DC16AA6C@codespeak.net> Author: cfbolz Date: Sat Apr 5 18:00:10 2008 New Revision: 53394 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/booleffect.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py Log: fix the test by forgetting all the bool effects when doing an exactmatch. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Sat Apr 5 18:00:10 2008 @@ -1833,7 +1833,6 @@ self.check_insns(int_add=2) def test_freeze_booleffects_correctly(self): - py.test.skip("fix this!") class B(object): _immutable_ = True def __init__(self, data, last=None): Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/booleffect.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/booleffect.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/booleffect.py Sat Apr 5 18:00:10 2008 @@ -1,8 +1,11 @@ from pypy.jit.timeshifter import rvalue class Effect(object): + def __init__(self, reverse): + self.reverse = reverse + def learn_boolvalue(self, jitstate, boolval): - if boolval: + if boolval ^ self.reverse: return self._apply(jitstate) else: return self._apply_reverse(jitstate) @@ -15,9 +18,9 @@ class PtrIsNonZeroEffect(Effect): def __init__(self, ptrbox, reverse=False): + Effect.__init__(self, reverse) assert isinstance(ptrbox, rvalue.AbstractPtrRedBox) self.ptrbox = ptrbox - self.reverse = reverse def learn_boolvalue(self, jitstate, boolval): return self.ptrbox.learn_nonzeroness(jitstate, boolval ^ self.reverse) @@ -27,11 +30,11 @@ class PtrEqualEffect(Effect): def __init__(self, ptrbox1, ptrbox2, reverse=False): + Effect.__init__(self, reverse) assert isinstance(ptrbox1, rvalue.AbstractPtrRedBox) assert isinstance(ptrbox2, rvalue.AbstractPtrRedBox) self.ptrbox1 = ptrbox1 self.ptrbox2 = ptrbox2 - self.reverse = reverse def _apply(self, jitstate): # the pointers _are_ equal @@ -44,7 +47,6 @@ # XXX can do more? return True - def copy(self, memo): return PtrEqualEffect(self.ptrbox1.copy(memo), self.ptrbox2.copy(memo), self.reverse) Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Sat Apr 5 18:00:10 2008 @@ -306,7 +306,7 @@ outgoingvarboxes = [] res = frozen.exactmatch(jitstate, outgoingvarboxes, memo) assert res, "exactmatch() failed" - cleanup_partial_data(memo.partialdatamatch) + cleanup_partial_data(memo) newblock = enter_next_block(jitstate, outgoingvarboxes) if index < 0: states_dic[key].append((frozen, newblock)) @@ -359,7 +359,7 @@ # We need a more general block. Do it by generalizing all the # redboxes from outgoingvarboxes, by making them variables. # Then we make a new block based on this new state. - cleanup_partial_data(memo.partialdatamatch) + cleanup_partial_data(memo) forget_nonzeroness = memo.forget_nonzeroness replace_memo = rvalue.copy_memo() for box in outgoingvarboxes: @@ -375,13 +375,17 @@ start_new_block(states_dic, jitstate, key, global_resumer) return False -def cleanup_partial_data(partialdatamatch): +def cleanup_partial_data(memo): # remove entries from PartialDataStruct unless they matched # their frozen equivalent - for box, keep in partialdatamatch.iteritems(): + for box, keep in memo.partialdatamatch.iteritems(): content = box.content if isinstance(content, rcontainer.PartialDataStruct): box.content = content.cleanup_partial_data(keep) + # XXX could do better by freezing booleffects. not sure if it's worth it + for box in memo.forgetbooleffects.iterkeys(): + assert isinstance(box, rvalue.BoolRedBox) + box.iftrue = [] def merge_generalized(jitstate): resuming = jitstate.get_resuming() Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py Sat Apr 5 18:00:10 2008 @@ -17,6 +17,7 @@ def exactmatch_memo(force_merge=False): memo = Memo() memo.partialdatamatch = {} + memo.forgetbooleffects = {} memo.forget_nonzeroness = {} memo.force_merge=force_merge return memo @@ -512,6 +513,11 @@ else: return memo[self] + def exactmatch(self, box, outgoingvarboxes, memo): + memo.forgetbooleffects[box] = True + return FrozenVar.exactmatch(self, box, outgoingvarboxes, memo) + + class FrozenDoubleConst(FrozenConst): def __init__(self, gv_const): From fijal at codespeak.net Sat Apr 5 18:48:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Apr 2008 18:48:56 +0200 (CEST) Subject: [pypy-svn] r53395 - in pypy/branch/jit-hotpath/pypy/jit/codegen: . ia32 test Message-ID: <20080405164856.951BF16AA73@codespeak.net> Author: fijal Date: Sat Apr 5 18:48:55 2008 New Revision: 53395 Added: pypy/branch/jit-hotpath/pypy/jit/codegen/support.py (contents, props changed) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: Grrrr, didn't check that in yesterday. support for frame reading + tests Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Sat Apr 5 18:48:55 2008 @@ -76,7 +76,7 @@ return builder.returnboolvar(self.operand(builder)) def movetonewaddr(self, builder, addr): - dstop = builder.mem_access(addr) + destop = builder.mem_access(addr) builder.mc.MOV(eax, self.operand(builder)) builder.mc.MOV(destop, al) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sat Apr 5 18:48:55 2008 @@ -10,6 +10,8 @@ from pypy.jit.codegen.ia32.objmodel import IntVar, FloatVar, Var,\ BoolVar, IntConst, AddrConst, BoolConst, FloatConst,\ LL_TO_GENVAR, TOKEN_TO_SIZE, token_to_genvar, WORD, AddrVar +from pypy.jit.codegen.support import ctypes_mapping +from ctypes import cast, c_void_p, POINTER DEBUG_CALL_ALIGN = True if sys.platform == 'darwin': @@ -17,15 +19,21 @@ else: CALL_ALIGN = 1 -def peek_word_at(addr): + at specialize.arg(0) +def peek_value_at(T, addr): # now the Very Obscure Bit: when translated, 'addr' is an # address. When not, it's an integer. It just happens to # make the test pass, but that's probably going to change. if objectmodel.we_are_translated(): - return addr.signed[0] + if T is lltype.Signed: + return addr.signed[0] + elif T is lltype.Float: + return addr.float[0] + else: + raise NotImplementedError("Not implemented types " + str(T)) else: - from ctypes import cast, c_void_p, c_int, POINTER - p = cast(c_void_p(addr), POINTER(c_int)) + tp = ctypes_mapping[T] + p = cast(c_void_p(addr), POINTER(tp)) return p[0] def poke_word_into(addr, value): @@ -394,6 +402,7 @@ return self.returnintvar(eax) def genop_call(self, sigtoken, gv_fnptr, args_gv): + # WUAAA, this does not support floats numargs = len(sigtoken[0]) MASK = CALL_ALIGN-1 if MASK: @@ -1316,9 +1325,8 @@ @staticmethod @specialize.arg(0) def read_frame_var(T, base, info, index): - assert T is lltype.Signed v = info[index] - value = peek_word_at(base - v.stackpos * WORD) + value = peek_value_at(T, base - v.stackpos * WORD) return value @staticmethod @@ -1327,7 +1335,7 @@ v = info[index] if isinstance(v, GenConst): return v - return IntConst(peek_word_at(base - v.stackpos * WORD)) + return IntConst(peek_value_at(lltype.Signed, base - v.stackpos * WORD)) @staticmethod @specialize.arg(0) @@ -1339,7 +1347,7 @@ @specialize.arg(0) def read_frame_place(T, base, place): assert T is lltype.Signed - return peek_word_at(base - place.stackpos * WORD) + return peek_value_at(T, base - place.stackpos * WORD) global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst Added: pypy/branch/jit-hotpath/pypy/jit/codegen/support.py ============================================================================== --- (empty file) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/support.py Sat Apr 5 18:48:55 2008 @@ -0,0 +1,7 @@ + +from ctypes import cast, c_void_p, c_int, c_double, POINTER +from pypy.rpython.lltypesystem import lltype, llmemory + +# XXX I'm sure we've got 1000 such mappings... +ctypes_mapping = {lltype.Signed: c_int, lltype.Float:c_double, + llmemory.Address: c_int, lltype.Void:None} Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sat Apr 5 18:48:55 2008 @@ -5,6 +5,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.translator.c.test import test_boehm from ctypes import c_void_p, cast, CFUNCTYPE, c_int +from pypy.jit.codegen.support import ctypes_mapping class PseudoAnnhelper(object): rtyper = None @@ -667,32 +668,41 @@ return gv_callable -class FrameVarReader: - FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Signed)) - def __init__(self, RGenOp, via_genconst): - def reader(base): - if via_genconst: - gv = RGenOp.genconst_from_frame_var( - RGenOp.kindToken(lltype.Signed), - base, self.frameinfo, 0) - return gv.revealconst(lltype.Signed) - else: - return RGenOp.read_frame_var(lltype.Signed, base, - self.frameinfo, 0) - self.reader = reader - def get_reader(self, info): - self.frameinfo = info - return llhelper(self.FUNC, self.reader) +def get_frame_reader(tp): + class FrameVarReader: + FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address], tp)) + def __init__(self, RGenOp, via_genconst): + def reader(base): + if via_genconst: + gv = RGenOp.genconst_from_frame_var( + RGenOp.kindToken(tp), + base, self.frameinfo, 0) + return gv.revealconst(tp) + else: + return RGenOp.read_frame_var(tp, base, + self.frameinfo, 0) + self.reader = reader + def get_reader(self, info): + self.frameinfo = info + return llhelper(self.FUNC, self.reader) + return FrameVarReader -def make_read_frame_var(rgenop, get_reader): - signed_kind = rgenop.kindToken(lltype.Signed) +FrameVarReader = get_frame_reader(lltype.Signed) +FrameVarFloatReader = get_frame_reader(lltype.Float) + +def make_read_frame_var(rgenop, get_reader, reader, FUNC): sigtoken = rgenop.sigToken(FUNC) - readertoken = rgenop.sigToken(FrameVarReader.FUNC.TO) + readertoken = rgenop.sigToken(reader.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") builder.start_writing() - gv_y = builder.genop2("int_mul", gv_x, rgenop.genconst(2)) + if FUNC.RESULT is lltype.Signed: + gv_y = builder.genop2("int_mul", gv_x, rgenop.genconst(2)) + elif FUNC.RESULT is lltype.Float: + gv_y = builder.genop2("float_mul", gv_x, rgenop.genconst(2.0)) + else: + gv_y = None gv_base = builder.genop_get_frame_base() info = builder.get_frame_info([gv_y]) gv_reader = rgenop.constPrebuiltGlobal(get_reader(info)) @@ -706,12 +716,13 @@ return gv_f -def get_read_frame_var_runner(RGenOp, via_genconst): - fvr = FrameVarReader(RGenOp, via_genconst) +def get_read_frame_var_runner(RGenOp, via_genconst, reader, FUNC): + fvr = reader(RGenOp, via_genconst) def read_frame_var_runner(x): rgenop = RGenOp() - gv_f = make_read_frame_var(rgenop, fvr.get_reader) + gv_f = make_read_frame_var(rgenop, fvr.get_reader, + reader, FUNC) fn = gv_f.revealconst(lltype.Ptr(FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive @@ -1032,13 +1043,15 @@ assert res == 8 def test_read_frame_var_compile(self): - runner = get_read_frame_var_runner(self.RGenOp, via_genconst=False) + runner = get_read_frame_var_runner(self.RGenOp, False, + FrameVarReader, FUNC) fn = self.compile(runner, [int]) res = fn(30) assert res == 60 def test_genconst_from_frame_var_compile(self): - runner = get_read_frame_var_runner(self.RGenOp, via_genconst=True) + runner = get_read_frame_var_runner(self.RGenOp, True, + FrameVarReader, FUNC) fn = self.compile(runner, [int]) res = fn(30) assert res == 60 @@ -1067,8 +1080,8 @@ def directtesthelper(self, FUNCTYPE, func): # for machine code backends: build a ctypes function pointer # (with a real physical address) that will call back our 'func' - nb_args = len(FUNCTYPE.TO.ARGS) - callback = CFUNCTYPE(c_int, *[c_int]*nb_args)(func) + args = tuple([ctypes_mapping[i] for i in FUNCTYPE.TO.ARGS]) + callback = CFUNCTYPE(ctypes_mapping[FUNCTYPE.TO.RESULT], *args)(func) keepalive = self.__dict__.setdefault('_keepalive', []) keepalive.append((callback, func)) return intmask(cast(callback, c_void_p).value) @@ -1518,11 +1531,26 @@ return reader_ptr rgenop = self.RGenOp() - gv_callable = make_read_frame_var(rgenop, get_reader) + gv_callable = make_read_frame_var(rgenop, get_reader, FrameVarReader, + FUNC) fnptr = self.cast(gv_callable, 1) res = fnptr(20) assert res == 40 + def test_read_frame_var_float_direct(self): + def get_reader(info): + fvr = FrameVarFloatReader(self.RGenOp, via_genconst=False) + fvr.frameinfo = info + reader_ptr = self.directtesthelper(fvr.FUNC, fvr.reader) + return reader_ptr + + rgenop = self.RGenOp() + gv_callable = make_read_frame_var(rgenop, get_reader, + FrameVarFloatReader, FLOATFUNC) + fnptr = self.cast_float(gv_callable, 1) + res = fnptr(3.2) + assert res == 6.4 + def test_genconst_from_frame_var_direct(self): def get_reader(info): fvr = FrameVarReader(self.RGenOp, via_genconst=True) @@ -1531,7 +1559,8 @@ return reader_ptr rgenop = self.RGenOp() - gv_callable = make_read_frame_var(rgenop, get_reader) + gv_callable = make_read_frame_var(rgenop, get_reader, FrameVarReader, + FUNC) fnptr = self.cast(gv_callable, 1) res = fnptr(20) assert res == 40 From cfbolz at codespeak.net Sat Apr 5 18:52:26 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 5 Apr 2008 18:52:26 +0200 (CEST) Subject: [pypy-svn] r53397 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080405165226.3CB4D16A702@codespeak.net> Author: cfbolz Date: Sat Apr 5 18:52:25 2008 New Revision: 53397 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Log: a comment and an assert Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Sat Apr 5 18:52:25 2008 @@ -400,9 +400,12 @@ oop_list_nonzero.couldfold = True def oop_list_method_resize(jitstate, oopspecdesc, deepfrozen, selfbox, lengthbox): + # only used by ootypesystem content = selfbox.content if isinstance(content, VirtualList): item_boxes = content.item_boxes + # I think this is always true, better to assert it + assert lengthbox.is_constant() length = rvalue.ll_getvalue(lengthbox, lltype.Signed) if len(item_boxes) < length: diff = length - len(item_boxes) From jared.grubb at codespeak.net Sat Apr 5 19:37:40 2008 From: jared.grubb at codespeak.net (jared.grubb at codespeak.net) Date: Sat, 5 Apr 2008 19:37:40 +0200 (CEST) Subject: [pypy-svn] r53398 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080405173740.8D02516A8BB@codespeak.net> Author: jared.grubb Date: Sat Apr 5 19:37:39 2008 New Revision: 53398 Modified: pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Log: PCRE tests: Minor clean up, made the pcre_test_7.py a bit easier to read by humans Modified: pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py (original) +++ pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py Sat Apr 5 19:37:39 2008 @@ -72,314 +72,299 @@ # End suite = [] -suite.append(['abc', '', [('abc', ' 0: abc')]]) -suite.append(['ab*c', '', [('abc', ' 0: abc'), ('abbbbc', ' 0: abbbbc'), ('ac', ' 0: ac')]]) -suite.append(['ab+c', '', [('abc', ' 0: abc'), ('abbbbbbc', ' 0: abbbbbbc'), ('*** Failers', None), ('ac', None), ('ab', None)]]) -suite.append(['a*', '', [('a', ' 0: a'), ('aaaaaaaaaaaaaaaaa', ' 0: aaaaaaaaaaaaaaaaa'), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', ' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')]]) -suite.append(['(a|abcd|african)', '', [('a', ' 0: a'), ('abcd', ' 0: abcd'), ('african', ' 0: african')]]) -suite.append(['^abc', '', [('abcdef', ' 0: abc'), ('*** Failers', None), ('xyzabc', None), ('xyz\nabc', None)]]) -suite.append(['x\\dy\\Dz', '', [('x9yzz', ' 0: x9yzz'), ('x0y+z', ' 0: x0y+z'), ('*** Failers', None), ('xyz', None), ('xxy0z', None)]]) -suite.append(['x\\sy\\Sz', '', [('x yzz', ' 0: x yzz'), ('x y+z', ' 0: x y+z'), ('*** Failers', None), ('xyz', None), ('xxyyz', None)]]) -suite.append(['x\\wy\\Wz', '', [('xxy+z', ' 0: xxy+z'), ('*** Failers', None), ('xxy0z', None), ('x+y+z', None)]]) -suite.append(['x.y', '', [('x+y', ' 0: x+y'), ('x-y', ' 0: x-y'), ('*** Failers', None), ('x\ny', None)]]) -suite.append(['a\\d$', '', [('ba0', ' 0: a0'), ('ba0\n', ' 0: a0'), ('*** Failers', None), ('ba0\ncd', None)]]) -suite.append(['[^a]', '', [('abcd', ' 0: b')]]) -suite.append(['ab?\\w', '', [('abz', ' 0: abz'), ('abbz', ' 0: abb'), ('azz', ' 0: az')]]) -suite.append(['x{0,3}yz', '', [('ayzq', ' 0: yz'), ('axyzq', ' 0: xyz'), ('axxyz', ' 0: xxyz'), ('axxxyzq', ' 0: xxxyz'), ('axxxxyzq', ' 0: xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None)]]) -suite.append(['x{3}yz', '', [('axxxyzq', ' 0: xxxyz'), ('axxxxyzq', ' 0: xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None), ('ayzq', None), ('axyzq', None), ('axxyz', None)]]) -suite.append(['x{2,3}yz', '', [('axxyz', ' 0: xxyz'), ('axxxyzq', ' 0: xxxyz'), ('axxxxyzq', ' 0: xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None), ('ayzq', None), ('axyzq', None)]]) -suite.append(['[^a]+', '', [('bac', ' 0: b'), ('bcdefax', ' 0: bcdef'), ('*** Failers', ' 0: *** F'), ('aaaaa', None)]]) -suite.append(['[^a]*', '', [('bac', ' 0: b'), ('bcdefax', ' 0: bcdef'), ('*** Failers', ' 0: *** F'), ('aaaaa', ' 0: ')]]) -suite.append(['[^a]{3,5}', '', [('xyz', ' 0: xyz'), ('awxyza', ' 0: wxyz'), ('abcdefa', ' 0: bcdef'), ('abcdefghijk', ' 0: bcdef'), ('*** Failers', ' 0: *** F'), ('axya', None), ('axa', None), ('aaaaa', None)]]) -suite.append(['\\d*', '', [('1234b567', ' 0: 1234'), ('xyz', ' 0: ')]]) -suite.append(['\\D*', '', [('a1234b567', ' 0: a'), ('xyz', ' 0: xyz')]]) -suite.append(['\\d+', '', [('ab1234c56', ' 0: 1234'), ('*** Failers', None), ('xyz', None)]]) -suite.append(['\\D+', '', [('ab123c56', ' 0: ab'), ('*** Failers', ' 0: *** Failers'), ('789', None)]]) -suite.append(['\\d?A', '', [('045ABC', ' 0: 5A'), ('ABC', ' 0: A'), ('*** Failers', None), ('XYZ', None)]]) -suite.append(['\\D?A', '', [('ABC', ' 0: A'), ('BAC', ' 0: BA'), ('9ABC', ' 0: A'), ('*** Failers', None)]]) -suite.append(['a+', '', [('aaaa', ' 0: aaaa')]]) -suite.append(['^.*xyz', '', [('xyz', ' 0: xyz'), ('ggggggggxyz', ' 0: ggggggggxyz')]]) -suite.append(['^.+xyz', '', [('abcdxyz', ' 0: abcdxyz'), ('axyz', ' 0: axyz'), ('*** Failers', None), ('xyz', None)]]) -suite.append(['^.?xyz', '', [('xyz', ' 0: xyz'), ('cxyz', ' 0: cxyz')]]) -suite.append(['^\\d{2,3}X', '', [('12X', ' 0: 12X'), ('123X', ' 0: 123X'), ('*** Failers', None), ('X', None), ('1X', None), ('1234X', None)]]) -suite.append(['^[abcd]\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('*** Failers', None), ('e45', None), ('abcd', None), ('abcd1234', None), ('1234', None)]]) -suite.append(['^[abcd]*\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('abcd1234', ' 0: abcd1'), ('1234', ' 0: 1'), ('*** Failers', None), ('e45', None), ('abcd', None)]]) -suite.append(['^[abcd]+\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('abcd1234', ' 0: abcd1'), ('*** Failers', None), ('1234', None), ('e45', None), ('abcd', None)]]) -suite.append(['^a+X', '', [('aX', ' 0: aX'), ('aaX', ' 0: aaX')]]) -suite.append(['^[abcd]?\\d', '', [('a45', ' 0: a4'), ('b93', ' 0: b9'), ('c99z', ' 0: c9'), ('d04', ' 0: d0'), ('1234', ' 0: 1'), ('*** Failers', None), ('abcd1234', None), ('e45', None)]]) -suite.append(['^[abcd]{2,3}\\d', '', [('ab45', ' 0: ab4'), ('bcd93', ' 0: bcd9'), ('*** Failers', None), ('1234', None), ('a36', None), ('abcd1234', None), ('ee45', None)]]) -suite.append(['^(abc)*\\d', '', [('abc45', ' 0: abc4'), ('abcabcabc45', ' 0: abcabcabc4'), ('42xyz', ' 0: 4'), ('*** Failers', None)]]) -suite.append(['^(abc)+\\d', '', [('abc45', ' 0: abc4'), ('abcabcabc45', ' 0: abcabcabc4'), ('*** Failers', None), ('42xyz', None)]]) -suite.append(['^(abc)?\\d', '', [('abc45', ' 0: abc4'), ('42xyz', ' 0: 4'), ('*** Failers', None), ('abcabcabc45', None)]]) -suite.append(['^(abc){2,3}\\d', '', [('abcabc45', ' 0: abcabc4'), ('abcabcabc45', ' 0: abcabcabc4'), ('*** Failers', None), ('abcabcabcabc45', None), ('abc45', None), ('42xyz', None)]]) -suite.append(['^(a*\\w|ab)=(a*\\w|ab)', '', [('ab=ab', ' 0: ab=ab')]]) -suite.append(['^abc', '', [('abcdef', ' 0: abc'), ('*** Failers', None)]]) -suite.append(['^(a*|xyz)', '', [('bcd', ' 0: '), ('aaabcd', ' 0: aaa'), ('xyz', ' 0: xyz'), ('*** Failers', ' 0: ')]]) -suite.append(['xyz$', '', [('xyz', ' 0: xyz'), ('xyz\n', ' 0: xyz'), ('*** Failers', None)]]) +suite.append(['abc', '', [('abc', 'abc')]]) +suite.append(['ab*c', '', [('abc', 'abc'), ('abbbbc', 'abbbbc'), ('ac', 'ac')]]) +suite.append(['ab+c', '', [('abc', 'abc'), ('abbbbbbc', 'abbbbbbc'), ('*** Failers', None), ('ac', None), ('ab', None)]]) +suite.append(['a*', '', [('a', 'a'), ('aaaaaaaaaaaaaaaaa', 'aaaaaaaaaaaaaaaaa'), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')]]) +suite.append(['(a|abcd|african)', '', [('a', 'a'), ('abcd', 'abcd'), ('african', 'african')]]) +suite.append(['^abc', '', [('abcdef', 'abc'), ('*** Failers', None), ('xyzabc', None), ('xyz\nabc', None)]]) +suite.append(['x\\dy\\Dz', '', [('x9yzz', 'x9yzz'), ('x0y+z', 'x0y+z'), ('*** Failers', None), ('xyz', None), ('xxy0z', None)]]) +suite.append(['x\\sy\\Sz', '', [('x yzz', 'x yzz'), ('x y+z', 'x y+z'), ('*** Failers', None), ('xyz', None), ('xxyyz', None)]]) +suite.append(['x\\wy\\Wz', '', [('xxy+z', 'xxy+z'), ('*** Failers', None), ('xxy0z', None), ('x+y+z', None)]]) +suite.append(['x.y', '', [('x+y', 'x+y'), ('x-y', 'x-y'), ('*** Failers', None), ('x\ny', None)]]) +suite.append(['a\\d$', '', [('ba0', 'a0'), ('ba0\n', 'a0'), ('*** Failers', None), ('ba0\ncd', None)]]) +suite.append(['[^a]', '', [('abcd', 'b')]]) +suite.append(['ab?\\w', '', [('abz', 'abz'), ('abbz', 'abb'), ('azz', 'az')]]) +suite.append(['x{0,3}yz', '', [('ayzq', 'yz'), ('axyzq', 'xyz'), ('axxyz', 'xxyz'), ('axxxyzq', 'xxxyz'), ('axxxxyzq', 'xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None)]]) +suite.append(['x{3}yz', '', [('axxxyzq', 'xxxyz'), ('axxxxyzq', 'xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None), ('ayzq', None), ('axyzq', None), ('axxyz', None)]]) +suite.append(['x{2,3}yz', '', [('axxyz', 'xxyz'), ('axxxyzq', 'xxxyz'), ('axxxxyzq', 'xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None), ('ayzq', None), ('axyzq', None)]]) +suite.append(['[^a]+', '', [('bac', 'b'), ('bcdefax', 'bcdef'), ('*** Failers', '*** F'), ('aaaaa', None)]]) +suite.append(['[^a]*', '', [('bac', 'b'), ('bcdefax', 'bcdef'), ('*** Failers', '*** F'), ('aaaaa', '')]]) +suite.append(['[^a]{3,5}', '', [('xyz', 'xyz'), ('awxyza', 'wxyz'), ('abcdefa', 'bcdef'), ('abcdefghijk', 'bcdef'), ('*** Failers', '*** F'), ('axya', None), ('axa', None), ('aaaaa', None)]]) +suite.append(['\\d*', '', [('1234b567', '1234'), ('xyz', '')]]) +suite.append(['\\D*', '', [('a1234b567', 'a'), ('xyz', 'xyz')]]) +suite.append(['\\d+', '', [('ab1234c56', '1234'), ('*** Failers', None), ('xyz', None)]]) +suite.append(['\\D+', '', [('ab123c56', 'ab'), ('*** Failers', '*** Failers'), ('789', None)]]) +suite.append(['\\d?A', '', [('045ABC', '5A'), ('ABC', 'A'), ('*** Failers', None), ('XYZ', None)]]) +suite.append(['\\D?A', '', [('ABC', 'A'), ('BAC', 'BA'), ('9ABC', 'A'), ('*** Failers', None)]]) +suite.append(['a+', '', [('aaaa', 'aaaa')]]) +suite.append(['^.*xyz', '', [('xyz', 'xyz'), ('ggggggggxyz', 'ggggggggxyz')]]) +suite.append(['^.+xyz', '', [('abcdxyz', 'abcdxyz'), ('axyz', 'axyz'), ('*** Failers', None), ('xyz', None)]]) +suite.append(['^.?xyz', '', [('xyz', 'xyz'), ('cxyz', 'cxyz')]]) +suite.append(['^\\d{2,3}X', '', [('12X', '12X'), ('123X', '123X'), ('*** Failers', None), ('X', None), ('1X', None), ('1234X', None)]]) +suite.append(['^[abcd]\\d', '', [('a45', 'a4'), ('b93', 'b9'), ('c99z', 'c9'), ('d04', 'd0'), ('*** Failers', None), ('e45', None), ('abcd', None), ('abcd1234', None), ('1234', None)]]) +suite.append(['^[abcd]*\\d', '', [('a45', 'a4'), ('b93', 'b9'), ('c99z', 'c9'), ('d04', 'd0'), ('abcd1234', 'abcd1'), ('1234', '1'), ('*** Failers', None), ('e45', None), ('abcd', None)]]) +suite.append(['^[abcd]+\\d', '', [('a45', 'a4'), ('b93', 'b9'), ('c99z', 'c9'), ('d04', 'd0'), ('abcd1234', 'abcd1'), ('*** Failers', None), ('1234', None), ('e45', None), ('abcd', None)]]) +suite.append(['^a+X', '', [('aX', 'aX'), ('aaX', 'aaX')]]) +suite.append(['^[abcd]?\\d', '', [('a45', 'a4'), ('b93', 'b9'), ('c99z', 'c9'), ('d04', 'd0'), ('1234', '1'), ('*** Failers', None), ('abcd1234', None), ('e45', None)]]) +suite.append(['^[abcd]{2,3}\\d', '', [('ab45', 'ab4'), ('bcd93', 'bcd9'), ('*** Failers', None), ('1234', None), ('a36', None), ('abcd1234', None), ('ee45', None)]]) +suite.append(['^(abc)*\\d', '', [('abc45', 'abc4'), ('abcabcabc45', 'abcabcabc4'), ('42xyz', '4'), ('*** Failers', None)]]) +suite.append(['^(abc)+\\d', '', [('abc45', 'abc4'), ('abcabcabc45', 'abcabcabc4'), ('*** Failers', None), ('42xyz', None)]]) +suite.append(['^(abc)?\\d', '', [('abc45', 'abc4'), ('42xyz', '4'), ('*** Failers', None), ('abcabcabc45', None)]]) +suite.append(['^(abc){2,3}\\d', '', [('abcabc45', 'abcabc4'), ('abcabcabc45', 'abcabcabc4'), ('*** Failers', None), ('abcabcabcabc45', None), ('abc45', None), ('42xyz', None)]]) +suite.append(['^(a*\\w|ab)=(a*\\w|ab)', '', [('ab=ab', 'ab=ab')]]) +suite.append(['^abc', '', [('abcdef', 'abc'), ('*** Failers', None)]]) +suite.append(['^(a*|xyz)', '', [('bcd', ''), ('aaabcd', 'aaa'), ('xyz', 'xyz'), ('*** Failers', '')]]) +suite.append(['xyz$', '', [('xyz', 'xyz'), ('xyz\n', 'xyz'), ('*** Failers', None)]]) suite.append(['^abcdef', '', [('*** Failers', None)]]) suite.append(['^a{2,4}\\d+z', '', [('*** Failers', None)]]) -suite.append(['^abcdef', '', []]) -suite.append(['(ab*(cd|ef))+X', '', []]) -suite.append(['the quick brown fox', '', [('the quick brown fox', ' 0: the quick brown fox'), ('The quick brown FOX', None), ('What do you know about the quick brown fox?', ' 0: the quick brown fox'), ('What do you know about THE QUICK BROWN FOX?', None)]]) -suite.append(['abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz', '', [('abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz', ' 0: abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz')]]) -suite.append(['a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz', '', [('abxyzpqrrrabbxyyyypqAzz', ' 0: abxyzpqrrrabbxyyyypqAzz'), ('abxyzpqrrrabbxyyyypqAzz', ' 0: abxyzpqrrrabbxyyyypqAzz'), ('aabxyzpqrrrabbxyyyypqAzz', ' 0: aabxyzpqrrrabbxyyyypqAzz'), ('aaabxyzpqrrrabbxyyyypqAzz', ' 0: aaabxyzpqrrrabbxyyyypqAzz'), ('aaaabxyzpqrrrabbxyyyypqAzz', ' 0: aaaabxyzpqrrrabbxyyyypqAzz'), ('abcxyzpqrrrabbxyyyypqAzz', ' 0: abcxyzpqrrrabbxyyyypqAzz'), ('aabcxyzpqrrrabbxyyyypqAzz', ' 0: aabcxyzpqrrrabbxyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypAzz', ' 0: aaabcxyzpqrrrabbxyyyypAzz'), ('aaabcxyzpqrrrabbxyyyypqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqqqAzz', ' 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz'), ('aaaabcxyzpqrrrabbxyyyypqAzz', ' 0: aaaabcxyzpqrrrabbxyyyypqAzz'), ('abxyzzpqrrrabbxyyyypqAzz', ' 0: abxyzzpqrrrabbxyyyypqAzz'), ('aabxyzzzpqrrrabbxyyyypqAzz', ' 0: aabxyzzzpqrrrabbxyyyypqAzz'), ('aaabxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaabxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaaabxyzzzzpqrrrabbxyyyypqAzz'), ('abcxyzzpqrrrabbxyyyypqAzz', ' 0: abcxyzzpqrrrabbxyyyypqAzz'), ('aabcxyzzzpqrrrabbxyyyypqAzz', ' 0: aabcxyzzzpqrrrabbxyyyypqAzz'), ('aaabcxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaabcxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbxyyyypqAzz', ' 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbbxyyyypqAzz', ' 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbbxyyyyypqAzz', ' 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypABzz', ' 0: aaabcxyzpqrrrabbxyyyypABzz'), ('aaabcxyzpqrrrabbxyyyypABBzz', ' 0: aaabcxyzpqrrrabbxyyyypABBzz'), ('>>>aaabxyzpqrrrabbxyyyypqAzz', ' 0: aaabxyzpqrrrabbxyyyypqAzz'), ('>aaaabxyzpqrrrabbxyyyypqAzz', ' 0: aaaabxyzpqrrrabbxyyyypqAzz'), ('>>>>abcxyzpqrrrabbxyyyypqAzz', ' 0: abcxyzpqrrrabbxyyyypqAzz'), ('*** Failers', None), ('abxyzpqrrabbxyyyypqAzz', None), ('abxyzpqrrrrabbxyyyypqAzz', None), ('abxyzpqrrrabxyyyypqAzz', None), ('aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz', None), ('aaaabcxyzzzzpqrrrabbbxyyypqAzz', None), ('aaabcxyzpqrrrabbxyyyypqqqqqqqAzz', None)]]) -suite.append(['^(abc){1,2}zz', '', [('abczz', ' 0: abczz'), ('abcabczz', ' 0: abcabczz'), ('*** Failers', None), ('zz', None), ('abcabcabczz', None), ('>>abczz', None)]]) -suite.append(['^(b+|a){1,2}c', '', [('bc', ' 0: bc'), ('bbc', ' 0: bbc'), ('bbbc', ' 0: bbbc'), ('bac', ' 0: bac'), ('bbac', ' 0: bbac'), ('aac', ' 0: aac'), ('abbbbbbbbbbbc', ' 0: abbbbbbbbbbbc'), ('bbbbbbbbbbbac', ' 0: bbbbbbbbbbbac'), ('*** Failers', None), ('aaac', None), ('abbbbbbbbbbbac', None)]]) -suite.append(['^\\ca\\cA\\c[\\c{\\c:', '', [('\x01\x01\x1b;z', ' 0: \x01\x01\x1b;z')]]) -suite.append(['^[ab\\]cde]', '', [('athing', ' 0: a'), ('bthing', ' 0: b'), (']thing', ' 0: ]'), ('cthing', ' 0: c'), ('dthing', ' 0: d'), ('ething', ' 0: e'), ('*** Failers', None), ('fthing', None), ('[thing', None), ('\\thing', None)]]) -suite.append(['^[]cde]', '', [(']thing', ' 0: ]'), ('cthing', ' 0: c'), ('dthing', ' 0: d'), ('ething', ' 0: e'), ('*** Failers', None), ('athing', None), ('fthing', None)]]) -suite.append(['^[^ab\\]cde]', '', [('fthing', ' 0: f'), ('[thing', ' 0: ['), ('\\thing', ' 0: \\'), ('*** Failers', ' 0: *'), ('athing', None), ('bthing', None), (']thing', None), ('cthing', None), ('dthing', None), ('ething', None)]]) -suite.append(['^[^]cde]', '', [('athing', ' 0: a'), ('fthing', ' 0: f'), ('*** Failers', ' 0: *'), (']thing', None), ('cthing', None), ('dthing', None), ('ething', None)]]) -suite.append(['^\\\x81', '', [('\x81', ' 0: \x81')]]) -suite.append(['^\xff', '', [('\xff', ' 0: \xff')]]) -suite.append(['^[0-9]+$', '', [('0', ' 0: 0'), ('1', ' 0: 1'), ('2', ' 0: 2'), ('3', ' 0: 3'), ('4', ' 0: 4'), ('5', ' 0: 5'), ('6', ' 0: 6'), ('7', ' 0: 7'), ('8', ' 0: 8'), ('9', ' 0: 9'), ('10', ' 0: 10'), ('100', ' 0: 100'), ('*** Failers', None), ('abc', None)]]) -suite.append(['^.*nter', '', [('enter', ' 0: enter'), ('inter', ' 0: inter'), ('uponter', ' 0: uponter')]]) -suite.append(['^xxx[0-9]+$', '', [('xxx0', ' 0: xxx0'), ('xxx1234', ' 0: xxx1234'), ('*** Failers', None), ('xxx', None)]]) -suite.append(['^.+[0-9][0-9][0-9]$', '', [('x123', ' 0: x123'), ('xx123', ' 0: xx123'), ('123456', ' 0: 123456'), ('*** Failers', None), ('123', None), ('x1234', ' 0: x1234')]]) -suite.append(['^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$', '', [('abc!pqr=apquxz.ixr.zzz.ac.uk', ' 0: abc!pqr=apquxz.ixr.zzz.ac.uk'), ('*** Failers', None), ('!pqr=apquxz.ixr.zzz.ac.uk', None), ('abc!=apquxz.ixr.zzz.ac.uk', None), ('abc!pqr=apquxz:ixr.zzz.ac.uk', None), ('abc!pqr=apquxz.ixr.zzz.ac.ukk', None)]]) -suite.append([':', '', [('Well, we need a colon: somewhere', ' 0: :'), ("*** Fail if we don't", None)]]) -suite.append(['^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$', '', [('.1.2.3', ' 0: .1.2.3'), ('A.12.123.0', ' 0: A.12.123.0'), ('*** Failers', None), ('.1.2.3333', None), ('1.2.3', None), ('1234.2.3', None)]]) -suite.append(['^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$', '', [('1 IN SOA non-sp1 non-sp2(', ' 0: 1 IN SOA non-sp1 non-sp2('), ('1 IN SOA non-sp1 non-sp2 (', ' 0: 1 IN SOA non-sp1 non-sp2 ('), ('*** Failers', None), ('1IN SOA non-sp1 non-sp2(', None)]]) -suite.append(['^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$', '', [('a.', ' 0: a.'), ('Z.', ' 0: Z.'), ('2.', ' 0: 2.'), ('ab-c.pq-r.', ' 0: ab-c.pq-r.'), ('sxk.zzz.ac.uk.', ' 0: sxk.zzz.ac.uk.'), ('x-.y-.', ' 0: x-.y-.'), ('*** Failers', None), ('-abc.peq.', None)]]) -suite.append(['^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$', '', [('*.a', ' 0: *.a'), ('*.b0-a', ' 0: *.b0-a'), ('*.c3-b.c', ' 0: *.c3-b.c'), ('*.c-a.b-c', ' 0: *.c-a.b-c'), ('*** Failers', None), ('*.0', None), ('*.a-', None), ('*.a-b.c-', None), ('*.c-a.0-c', None)]]) -suite.append(['^\\".*\\"\\s*(;.*)?$', '', [('"1234"', ' 0: "1234"'), ('"abcd" ;', ' 0: "abcd" ;'), ('"" ; rhubarb', ' 0: "" ; rhubarb'), ('*** Failers', None), ('"1234" : things', None)]]) -suite.append(['^$', '', [('', ' 0: '), ('*** Failers', None)]]) -suite.append(['^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$', '', [('abcdefhijklm', ' 0: abcdefhijklm')]]) -suite.append(['^a*\\w', '', [('z', ' 0: z'), ('az', ' 0: az'), ('aaaz', ' 0: aaaz'), ('a', ' 0: a'), ('aa', ' 0: aa'), ('aaaa', ' 0: aaaa'), ('a+', ' 0: a'), ('aa+', ' 0: aa')]]) -suite.append(['^a+\\w', '', [('az', ' 0: az'), ('aaaz', ' 0: aaaz'), ('aa', ' 0: aa'), ('aaaa', ' 0: aaaa'), ('aa+', ' 0: aa')]]) -suite.append(['^\\d{8}\\w{2,}', '', [('1234567890', ' 0: 1234567890'), ('12345678ab', ' 0: 12345678ab'), ('12345678__', ' 0: 12345678__'), ('*** Failers', None), ('1234567', None)]]) -suite.append(['^[aeiou\\d]{4,5}$', '', [('uoie', ' 0: uoie'), ('1234', ' 0: 1234'), ('12345', ' 0: 12345'), ('aaaaa', ' 0: aaaaa'), ('*** Failers', None), ('123456', None)]]) -suite.append(['^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]', '', [('From abcd Mon Sep 01 12:33:02 1997', ' 0: From abcd Mon Sep 01 12:33')]]) -suite.append(['^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d', '', [('From abcd Mon Sep 01 12:33:02 1997', ' 0: From abcd Mon Sep 01 12:33'), ('From abcd Mon Sep 1 12:33:02 1997', ' 0: From abcd Mon Sep 1 12:33'), ('*** Failers', None), ('From abcd Sep 01 12:33:02 1997', None)]]) -suite.append(['^[ab]{1,3}(ab*|b)', '', [('aabbbbb', ' 0: aabbbbb')]]) -suite.append(['abc\\0def\\00pqr\\000xyz\\0000AB', '', [('abc\x00def\x00pqr\x00xyz\x000AB', ' 0: abc\x00def\x00pqr\x00xyz\x000AB'), ('abc456 abc\x00def\x00pqr\x00xyz\x000ABCDE', ' 0: abc\x00def\x00pqr\x00xyz\x000AB')]]) -suite.append(['abc\\x0def\\x00pqr\\x000xyz\\x0000AB', '', [('abc\ref\x00pqr\x000xyz\x0000AB', ' 0: abc\ref\x00pqr\x000xyz\x0000AB'), ('abc456 abc\ref\x00pqr\x000xyz\x0000ABCDE', ' 0: abc\ref\x00pqr\x000xyz\x0000AB')]]) -suite.append(['^[\\000-\\037]', '', [('\x00A', ' 0: \x00'), ('\x01B', ' 0: \x01'), ('\x1fC', ' 0: \x1f')]]) -suite.append(['\\0*', '', [('\x00\x00\x00\x00', ' 0: \x00\x00\x00\x00')]]) -suite.append(['A\\x00{2,3}Z', '', [('The A\x00\x00Z', ' 0: A\x00\x00Z'), ('An A\x00\x00\x00Z', ' 0: A\x00\x00\x00Z'), ('*** Failers', None), ('A\x00Z', None), ('A\x00\x00\x00\x00Z', None)]]) -suite.append(['^\\s', '', [(' abc', ' 0: '), ('\x0cabc', ' 0: \x0c'), ('\nabc', ' 0: \n'), ('\rabc', ' 0: \r'), ('\tabc', ' 0: \t'), ('*** Failers', None), ('abc', None)]]) -suite.append(['ab{1,3}bc', '', [('abbbbc', ' 0: abbbbc'), ('abbbc', ' 0: abbbc'), ('abbc', ' 0: abbc'), ('*** Failers', None), ('abc', None), ('abbbbbc', None)]]) -suite.append(['([^.]*)\\.([^:]*):[T ]+(.*)', '', [('track1.title:TBlah blah blah', ' 0: track1.title:TBlah blah blah')]]) -suite.append(['^[W-c]+$', '', [('WXY_^abc', ' 0: WXY_^abc'), ('*** Failers', None), ('wxy', None)]]) -suite.append(['^abc$', '', [('abc', ' 0: abc'), ('*** Failers', None), ('qqq\nabc', None), ('abc\nzzz', None), ('qqq\nabc\nzzz', None)]]) -suite.append(['[-az]+', '', [('az-', ' 0: az-'), ('*** Failers', ' 0: a'), ('b', None)]]) -suite.append(['[az-]+', '', [('za-', ' 0: za-'), ('*** Failers', ' 0: a'), ('b', None)]]) -suite.append(['[a\\-z]+', '', [('a-z', ' 0: a-z'), ('*** Failers', ' 0: a'), ('b', None)]]) -suite.append(['[a-z]+', '', [('abcdxyz', ' 0: abcdxyz')]]) -suite.append(['[\\d-]+', '', [('12-34', ' 0: 12-34'), ('*** Failers', None), ('aaa', None)]]) -suite.append(['[\\d-z]+', '', [('12-34z', ' 0: 12-34z'), ('*** Failers', None), ('aaa', None)]]) -suite.append(['\\x5c', '', [('\\', ' 0: \\')]]) -suite.append(['\\x20Z', '', [('the Zoo', ' 0: Z'), ('*** Failers', None), ('Zulu', None)]]) -suite.append(['ab{3cd', '', [('ab{3cd', ' 0: ab{3cd')]]) -suite.append(['ab{3,cd', '', [('ab{3,cd', ' 0: ab{3,cd')]]) -suite.append(['ab{3,4a}cd', '', [('ab{3,4a}cd', ' 0: ab{3,4a}cd')]]) -suite.append(['{4,5a}bc', '', [('{4,5a}bc', ' 0: {4,5a}bc')]]) -suite.append(['abc$', '', [('abc', ' 0: abc'), ('abc\n', ' 0: abc'), ('*** Failers', None), ('abc\ndef', None)]]) -suite.append(['(abc)\\223', '', [('abc\x93', ' 0: abc\x93')]]) -suite.append(['(abc)\\323', '', [('abc\xd3', ' 0: abc\xd3')]]) -suite.append(['ab\\idef', '', [('abidef', ' 0: abidef')]]) -suite.append(['a{0}bc', '', [('bc', ' 0: bc')]]) -suite.append(['abc[\\10]de', '', [('abc\x08de', ' 0: abc\x08de')]]) -suite.append(['abc[\\1]de', '', [('abc\x01de', ' 0: abc\x01de')]]) -suite.append(['[^a]', '', [('Abc', ' 0: A')]]) -suite.append(['[^a]+', '', [('AAAaAbc', ' 0: AAA')]]) -suite.append(['[^a]+', '', [('bbb\nccc', ' 0: bbb\nccc')]]) -suite.append(['[^k]$', '', [('abc', ' 0: c'), ('*** Failers', ' 0: s'), ('abk', None)]]) -suite.append(['[^k]{2,3}$', '', [('abc', ' 0: abc'), ('kbc', ' 0: bc'), ('kabc', ' 0: abc'), ('*** Failers', ' 0: ers'), ('abk', None), ('akb', None), ('akk', None)]]) -suite.append(['^\\d{8,}\\@.+[^k]$', '', [('12345678 at a.b.c.d', ' 0: 12345678 at a.b.c.d'), ('123456789 at x.y.z', ' 0: 123456789 at x.y.z'), ('*** Failers', None), ('12345678 at x.y.uk', None), ('1234567 at a.b.c.d', None)]]) -suite.append(['[^a]', '', [('aaaabcd', ' 0: b'), ('aaAabcd', ' 0: A')]]) -suite.append(['[^az]', '', [('aaaabcd', ' 0: b'), ('aaAabcd', ' 0: A')]]) -suite.append(['\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377', '', [('\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', ' 0: \x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff')]]) -suite.append(['(\\.\\d\\d[1-9]?)\\d+', '', [('1.230003938', ' 0: .230003938'), ('1.875000282', ' 0: .875000282'), ('1.235', ' 0: .235')]]) -suite.append(['foo(.*)bar', '', [('The food is under the bar in the barn.', ' 0: food is under the bar in the bar')]]) -suite.append(['(.*)(\\d*)', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) -suite.append(['(.*)(\\d+)', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) -suite.append(['(.*)(\\d+)$', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) -suite.append(['(.*\\D)(\\d+)$', '', [('I have 2 numbers: 53147', ' 0: I have 2 numbers: 53147')]]) -suite.append(['^[W-]46]', '', [('W46]789', ' 0: W46]'), ('-46]789', ' 0: -46]'), ('*** Failers', None), ('Wall', None), ('Zebra', None), ('42', None), ('[abcd]', None), (']abcd[', None)]]) -suite.append(['^[W-\\]46]', '', [('W46]789', ' 0: W'), ('Wall', ' 0: W'), ('Zebra', ' 0: Z'), ('Xylophone', ' 0: X'), ('42', ' 0: 4'), ('[abcd]', ' 0: ['), (']abcd[', ' 0: ]'), ('\\backslash', ' 0: \\'), ('*** Failers', None), ('-46]789', None), ('well', None)]]) -suite.append(['\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d', '', [('01/01/2000', ' 0: 01/01/2000')]]) -suite.append(['^(a){0,0}', '', [('bcd', ' 0: '), ('abc', ' 0: '), ('aab', ' 0: ')]]) -suite.append(['^(a){0,1}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: a')]]) -suite.append(['^(a){0,2}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: aa')]]) -suite.append(['^(a){0,3}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa')]]) -suite.append(['^(a){0,}', '', [('bcd', ' 0: '), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa'), ('aaaaaaaa', ' 0: aaaaaaaa')]]) -suite.append(['^(a){1,1}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: a')]]) -suite.append(['^(a){1,2}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: aa')]]) -suite.append(['^(a){1,3}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa')]]) -suite.append(['^(a){1,}', '', [('bcd', None), ('abc', ' 0: a'), ('aab', ' 0: aa'), ('aaa', ' 0: aaa'), ('aaaaaaaa', ' 0: aaaaaaaa')]]) -suite.append(['.*\\.gif', '', [('borfle\nbib.gif\nno', ' 0: bib.gif')]]) -suite.append(['.{0,}\\.gif', '', [('borfle\nbib.gif\nno', ' 0: bib.gif')]]) -suite.append(['.*$', '', [('borfle\nbib.gif\nno', ' 0: no')]]) -suite.append(['.*$', '', [('borfle\nbib.gif\nno\n', ' 0: no')]]) +suite.append(['the quick brown fox', '', [('the quick brown fox', 'the quick brown fox'), ('The quick brown FOX', None), ('What do you know about the quick brown fox?', 'the quick brown fox'), ('What do you know about THE QUICK BROWN FOX?', None)]]) +suite.append(['abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz', '', [('abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz', 'abcd\t\n\r\x0c\x07\x1b9;$\\?caxyz')]]) +suite.append(['a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz', '', [('abxyzpqrrrabbxyyyypqAzz', 'abxyzpqrrrabbxyyyypqAzz'), ('abxyzpqrrrabbxyyyypqAzz', 'abxyzpqrrrabbxyyyypqAzz'), ('aabxyzpqrrrabbxyyyypqAzz', 'aabxyzpqrrrabbxyyyypqAzz'), ('aaabxyzpqrrrabbxyyyypqAzz', 'aaabxyzpqrrrabbxyyyypqAzz'), ('aaaabxyzpqrrrabbxyyyypqAzz', 'aaaabxyzpqrrrabbxyyyypqAzz'), ('abcxyzpqrrrabbxyyyypqAzz', 'abcxyzpqrrrabbxyyyypqAzz'), ('aabcxyzpqrrrabbxyyyypqAzz', 'aabcxyzpqrrrabbxyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypAzz', 'aaabcxyzpqrrrabbxyyyypAzz'), ('aaabcxyzpqrrrabbxyyyypqAzz', 'aaabcxyzpqrrrabbxyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypqqAzz', 'aaabcxyzpqrrrabbxyyyypqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqAzz', 'aaabcxyzpqrrrabbxyyyypqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqAzz', 'aaabcxyzpqrrrabbxyyyypqqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqqAzz', 'aaabcxyzpqrrrabbxyyyypqqqqqAzz'), ('aaabcxyzpqrrrabbxyyyypqqqqqqAzz', 'aaabcxyzpqrrrabbxyyyypqqqqqqAzz'), ('aaaabcxyzpqrrrabbxyyyypqAzz', 'aaaabcxyzpqrrrabbxyyyypqAzz'), ('abxyzzpqrrrabbxyyyypqAzz', 'abxyzzpqrrrabbxyyyypqAzz'), ('aabxyzzzpqrrrabbxyyyypqAzz', 'aabxyzzzpqrrrabbxyyyypqAzz'), ('aaabxyzzzzpqrrrabbxyyyypqAzz', 'aaabxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabxyzzzzpqrrrabbxyyyypqAzz', 'aaaabxyzzzzpqrrrabbxyyyypqAzz'), ('abcxyzzpqrrrabbxyyyypqAzz', 'abcxyzzpqrrrabbxyyyypqAzz'), ('aabcxyzzzpqrrrabbxyyyypqAzz', 'aabcxyzzzpqrrrabbxyyyypqAzz'), ('aaabcxyzzzzpqrrrabbxyyyypqAzz', 'aaabcxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbxyyyypqAzz', 'aaaabcxyzzzzpqrrrabbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbbxyyyypqAzz', 'aaaabcxyzzzzpqrrrabbbxyyyypqAzz'), ('aaaabcxyzzzzpqrrrabbbxyyyyypqAzz', 'aaaabcxyzzzzpqrrrabbbxyyyyypqAzz'), ('aaabcxyzpqrrrabbxyyyypABzz', 'aaabcxyzpqrrrabbxyyyypABzz'), ('aaabcxyzpqrrrabbxyyyypABBzz', 'aaabcxyzpqrrrabbxyyyypABBzz'), ('>>>aaabxyzpqrrrabbxyyyypqAzz', 'aaabxyzpqrrrabbxyyyypqAzz'), ('>aaaabxyzpqrrrabbxyyyypqAzz', 'aaaabxyzpqrrrabbxyyyypqAzz'), ('>>>>abcxyzpqrrrabbxyyyypqAzz', 'abcxyzpqrrrabbxyyyypqAzz'), ('*** Failers', None), ('abxyzpqrrabbxyyyypqAzz', None), ('abxyzpqrrrrabbxyyyypqAzz', None), ('abxyzpqrrrabxyyyypqAzz', None), ('aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz', None), ('aaaabcxyzzzzpqrrrabbbxyyypqAzz', None), ('aaabcxyzpqrrrabbxyyyypqqqqqqqAzz', None)]]) +suite.append(['^(abc){1,2}zz', '', [('abczz', 'abczz'), ('abcabczz', 'abcabczz'), ('*** Failers', None), ('zz', None), ('abcabcabczz', None), ('>>abczz', None)]]) +suite.append(['^(b+|a){1,2}c', '', [('bc', 'bc'), ('bbc', 'bbc'), ('bbbc', 'bbbc'), ('bac', 'bac'), ('bbac', 'bbac'), ('aac', 'aac'), ('abbbbbbbbbbbc', 'abbbbbbbbbbbc'), ('bbbbbbbbbbbac', 'bbbbbbbbbbbac'), ('*** Failers', None), ('aaac', None), ('abbbbbbbbbbbac', None)]]) +suite.append(['^\\ca\\cA\\c[\\c{\\c:', '', [('\x01\x01\x1b;z', '\x01\x01\x1b;z')]]) +suite.append(['^[ab\\]cde]', '', [('athing', 'a'), ('bthing', 'b'), (']thing', ']'), ('cthing', 'c'), ('dthing', 'd'), ('ething', 'e'), ('*** Failers', None), ('fthing', None), ('[thing', None), ('\\thing', None)]]) +suite.append(['^[]cde]', '', [(']thing', ']'), ('cthing', 'c'), ('dthing', 'd'), ('ething', 'e'), ('*** Failers', None), ('athing', None), ('fthing', None)]]) +suite.append(['^[^ab\\]cde]', '', [('fthing', 'f'), ('[thing', '['), ('\\thing', '\\'), ('*** Failers', '*'), ('athing', None), ('bthing', None), (']thing', None), ('cthing', None), ('dthing', None), ('ething', None)]]) +suite.append(['^[^]cde]', '', [('athing', 'a'), ('fthing', 'f'), ('*** Failers', '*'), (']thing', None), ('cthing', None), ('dthing', None), ('ething', None)]]) +suite.append(['^\\\x81', '', [('\x81', '\x81')]]) +suite.append(['^\xff', '', [('\xff', '\xff')]]) +suite.append(['^[0-9]+$', '', [('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10'), ('100', '100'), ('*** Failers', None), ('abc', None)]]) +suite.append(['^.*nter', '', [('enter', 'enter'), ('inter', 'inter'), ('uponter', 'uponter')]]) +suite.append(['^xxx[0-9]+$', '', [('xxx0', 'xxx0'), ('xxx1234', 'xxx1234'), ('*** Failers', None), ('xxx', None)]]) +suite.append(['^.+[0-9][0-9][0-9]$', '', [('x123', 'x123'), ('xx123', 'xx123'), ('123456', '123456'), ('*** Failers', None), ('123', None), ('x1234', 'x1234')]]) +suite.append(['^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$', '', [('abc!pqr=apquxz.ixr.zzz.ac.uk', 'abc!pqr=apquxz.ixr.zzz.ac.uk'), ('*** Failers', None), ('!pqr=apquxz.ixr.zzz.ac.uk', None), ('abc!=apquxz.ixr.zzz.ac.uk', None), ('abc!pqr=apquxz:ixr.zzz.ac.uk', None), ('abc!pqr=apquxz.ixr.zzz.ac.ukk', None)]]) +suite.append([':', '', [('Well, we need a colon: somewhere', ':'), ("*** Fail if we don't", None)]]) +suite.append(['^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$', '', [('.1.2.3', '.1.2.3'), ('A.12.123.0', 'A.12.123.0'), ('*** Failers', None), ('.1.2.3333', None), ('1.2.3', None), ('1234.2.3', None)]]) +suite.append(['^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$', '', [('1 IN SOA non-sp1 non-sp2(', '1 IN SOA non-sp1 non-sp2('), ('1 IN SOA non-sp1 non-sp2 (', '1 IN SOA non-sp1 non-sp2 ('), ('*** Failers', None), ('1IN SOA non-sp1 non-sp2(', None)]]) +suite.append(['^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$', '', [('a.', 'a.'), ('Z.', 'Z.'), ('2.', '2.'), ('ab-c.pq-r.', 'ab-c.pq-r.'), ('sxk.zzz.ac.uk.', 'sxk.zzz.ac.uk.'), ('x-.y-.', 'x-.y-.'), ('*** Failers', None), ('-abc.peq.', None)]]) +suite.append(['^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$', '', [('*.a', '*.a'), ('*.b0-a', '*.b0-a'), ('*.c3-b.c', '*.c3-b.c'), ('*.c-a.b-c', '*.c-a.b-c'), ('*** Failers', None), ('*.0', None), ('*.a-', None), ('*.a-b.c-', None), ('*.c-a.0-c', None)]]) +suite.append(['^\\".*\\"\\s*(;.*)?$', '', [('"1234"', '"1234"'), ('"abcd" ;', '"abcd" ;'), ('"" ; rhubarb', '"" ; rhubarb'), ('*** Failers', None), ('"1234" : things', None)]]) +suite.append(['^$', '', [('', ''), ('*** Failers', None)]]) +suite.append(['^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$', '', [('abcdefhijklm', 'abcdefhijklm')]]) +suite.append(['^a*\\w', '', [('z', 'z'), ('az', 'az'), ('aaaz', 'aaaz'), ('a', 'a'), ('aa', 'aa'), ('aaaa', 'aaaa'), ('a+', 'a'), ('aa+', 'aa')]]) +suite.append(['^a+\\w', '', [('az', 'az'), ('aaaz', 'aaaz'), ('aa', 'aa'), ('aaaa', 'aaaa'), ('aa+', 'aa')]]) +suite.append(['^\\d{8}\\w{2,}', '', [('1234567890', '1234567890'), ('12345678ab', '12345678ab'), ('12345678__', '12345678__'), ('*** Failers', None), ('1234567', None)]]) +suite.append(['^[aeiou\\d]{4,5}$', '', [('uoie', 'uoie'), ('1234', '1234'), ('12345', '12345'), ('aaaaa', 'aaaaa'), ('*** Failers', None), ('123456', None)]]) +suite.append(['^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]', '', [('From abcd Mon Sep 01 12:33:02 1997', 'From abcd Mon Sep 01 12:33')]]) +suite.append(['^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d', '', [('From abcd Mon Sep 01 12:33:02 1997', 'From abcd Mon Sep 01 12:33'), ('From abcd Mon Sep 1 12:33:02 1997', 'From abcd Mon Sep 1 12:33'), ('*** Failers', None), ('From abcd Sep 01 12:33:02 1997', None)]]) +suite.append(['^[ab]{1,3}(ab*|b)', '', [('aabbbbb', 'aabbbbb')]]) +suite.append(['abc\\0def\\00pqr\\000xyz\\0000AB', '', [('abc\x00def\x00pqr\x00xyz\x000AB', 'abc\x00def\x00pqr\x00xyz\x000AB'), ('abc456 abc\x00def\x00pqr\x00xyz\x000ABCDE', 'abc\x00def\x00pqr\x00xyz\x000AB')]]) +suite.append(['abc\\x0def\\x00pqr\\x000xyz\\x0000AB', '', [('abc\ref\x00pqr\x000xyz\x0000AB', 'abc\ref\x00pqr\x000xyz\x0000AB'), ('abc456 abc\ref\x00pqr\x000xyz\x0000ABCDE', 'abc\ref\x00pqr\x000xyz\x0000AB')]]) +suite.append(['^[\\000-\\037]', '', [('\x00A', '\x00'), ('\x01B', '\x01'), ('\x1fC', '\x1f')]]) +suite.append(['\\0*', '', [('\x00\x00\x00\x00', '\x00\x00\x00\x00')]]) +suite.append(['A\\x00{2,3}Z', '', [('The A\x00\x00Z', 'A\x00\x00Z'), ('An A\x00\x00\x00Z', 'A\x00\x00\x00Z'), ('*** Failers', None), ('A\x00Z', None), ('A\x00\x00\x00\x00Z', None)]]) +suite.append(['^\\s', '', [(' abc', ' '), ('\x0cabc', '\x0c'), ('\nabc', '\n'), ('\rabc', '\r'), ('\tabc', '\t'), ('*** Failers', None), ('abc', None)]]) +suite.append(['ab{1,3}bc', '', [('abbbbc', 'abbbbc'), ('abbbc', 'abbbc'), ('abbc', 'abbc'), ('*** Failers', None), ('abc', None), ('abbbbbc', None)]]) +suite.append(['([^.]*)\\.([^:]*):[T ]+(.*)', '', [('track1.title:TBlah blah blah', 'track1.title:TBlah blah blah')]]) +suite.append(['^[W-c]+$', '', [('WXY_^abc', 'WXY_^abc'), ('*** Failers', None), ('wxy', None)]]) +suite.append(['^abc$', '', [('abc', 'abc'), ('*** Failers', None), ('qqq\nabc', None), ('abc\nzzz', None), ('qqq\nabc\nzzz', None)]]) +suite.append(['[-az]+', '', [('az-', 'az-'), ('*** Failers', 'a'), ('b', None)]]) +suite.append(['[az-]+', '', [('za-', 'za-'), ('*** Failers', 'a'), ('b', None)]]) +suite.append(['[a\\-z]+', '', [('a-z', 'a-z'), ('*** Failers', 'a'), ('b', None)]]) +suite.append(['[a-z]+', '', [('abcdxyz', 'abcdxyz')]]) +suite.append(['[\\d-]+', '', [('12-34', '12-34'), ('*** Failers', None), ('aaa', None)]]) +suite.append(['[\\d-z]+', '', [('12-34z', '12-34z'), ('*** Failers', None), ('aaa', None)]]) +suite.append(['\\x5c', '', [('\\', '\\')]]) +suite.append(['\\x20Z', '', [('the Zoo', ' Z'), ('*** Failers', None), ('Zulu', None)]]) +suite.append(['ab{3cd', '', [('ab{3cd', 'ab{3cd')]]) +suite.append(['ab{3,cd', '', [('ab{3,cd', 'ab{3,cd')]]) +suite.append(['ab{3,4a}cd', '', [('ab{3,4a}cd', 'ab{3,4a}cd')]]) +suite.append(['{4,5a}bc', '', [('{4,5a}bc', '{4,5a}bc')]]) +suite.append(['abc$', '', [('abc', 'abc'), ('abc\n', 'abc'), ('*** Failers', None), ('abc\ndef', None)]]) +suite.append(['(abc)\\223', '', [('abc\x93', 'abc\x93')]]) +suite.append(['(abc)\\323', '', [('abc\xd3', 'abc\xd3')]]) +suite.append(['ab\\idef', '', [('abidef', 'abidef')]]) +suite.append(['a{0}bc', '', [('bc', 'bc')]]) +suite.append(['abc[\\10]de', '', [('abc\x08de', 'abc\x08de')]]) +suite.append(['abc[\\1]de', '', [('abc\x01de', 'abc\x01de')]]) +suite.append(['[^a]', '', [('Abc', 'A')]]) +suite.append(['[^a]+', '', [('AAAaAbc', 'AAA')]]) +suite.append(['[^a]+', '', [('bbb\nccc', 'bbb\nccc')]]) +suite.append(['[^k]$', '', [('abc', 'c'), ('*** Failers', 's'), ('abk', None)]]) +suite.append(['[^k]{2,3}$', '', [('abc', 'abc'), ('kbc', 'bc'), ('kabc', 'abc'), ('*** Failers', 'ers'), ('abk', None), ('akb', None), ('akk', None)]]) +suite.append(['^\\d{8,}\\@.+[^k]$', '', [('12345678 at a.b.c.d', '12345678 at a.b.c.d'), ('123456789 at x.y.z', '123456789 at x.y.z'), ('*** Failers', None), ('12345678 at x.y.uk', None), ('1234567 at a.b.c.d', None)]]) +suite.append(['[^a]', '', [('aaaabcd', 'b'), ('aaAabcd', 'A')]]) +suite.append(['[^az]', '', [('aaaabcd', 'b'), ('aaAabcd', 'A')]]) +suite.append(['\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377', '', [('\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff')]]) +suite.append(['(\\.\\d\\d[1-9]?)\\d+', '', [('1.230003938', '.230003938'), ('1.875000282', '.875000282'), ('1.235', '.235')]]) +suite.append(['foo(.*)bar', '', [('The food is under the bar in the barn.', 'food is under the bar in the bar')]]) +suite.append(['(.*)(\\d*)', '', [('I have 2 numbers: 53147', 'I have 2 numbers: 53147')]]) +suite.append(['(.*)(\\d+)', '', [('I have 2 numbers: 53147', 'I have 2 numbers: 53147')]]) +suite.append(['(.*)(\\d+)$', '', [('I have 2 numbers: 53147', 'I have 2 numbers: 53147')]]) +suite.append(['(.*\\D)(\\d+)$', '', [('I have 2 numbers: 53147', 'I have 2 numbers: 53147')]]) +suite.append(['^[W-]46]', '', [('W46]789', 'W46]'), ('-46]789', '-46]'), ('*** Failers', None), ('Wall', None), ('Zebra', None), ('42', None), ('[abcd]', None), (']abcd[', None)]]) +suite.append(['^[W-\\]46]', '', [('W46]789', 'W'), ('Wall', 'W'), ('Zebra', 'Z'), ('Xylophone', 'X'), ('42', '4'), ('[abcd]', '['), (']abcd[', ']'), ('\\backslash', '\\'), ('*** Failers', None), ('-46]789', None), ('well', None)]]) +suite.append(['\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d', '', [('01/01/2000', '01/01/2000')]]) +suite.append(['^(a){0,0}', '', [('bcd', ''), ('abc', ''), ('aab', '')]]) +suite.append(['^(a){0,1}', '', [('bcd', ''), ('abc', 'a'), ('aab', 'a')]]) +suite.append(['^(a){0,2}', '', [('bcd', ''), ('abc', 'a'), ('aab', 'aa')]]) +suite.append(['^(a){0,3}', '', [('bcd', ''), ('abc', 'a'), ('aab', 'aa'), ('aaa', 'aaa')]]) +suite.append(['^(a){0,}', '', [('bcd', ''), ('abc', 'a'), ('aab', 'aa'), ('aaa', 'aaa'), ('aaaaaaaa', 'aaaaaaaa')]]) +suite.append(['^(a){1,1}', '', [('bcd', None), ('abc', 'a'), ('aab', 'a')]]) +suite.append(['^(a){1,2}', '', [('bcd', None), ('abc', 'a'), ('aab', 'aa')]]) +suite.append(['^(a){1,3}', '', [('bcd', None), ('abc', 'a'), ('aab', 'aa'), ('aaa', 'aaa')]]) +suite.append(['^(a){1,}', '', [('bcd', None), ('abc', 'a'), ('aab', 'aa'), ('aaa', 'aaa'), ('aaaaaaaa', 'aaaaaaaa')]]) +suite.append(['.*\\.gif', '', [('borfle\nbib.gif\nno', 'bib.gif')]]) +suite.append(['.{0,}\\.gif', '', [('borfle\nbib.gif\nno', 'bib.gif')]]) +suite.append(['.*$', '', [('borfle\nbib.gif\nno', 'no')]]) +suite.append(['.*$', '', [('borfle\nbib.gif\nno\n', 'no')]]) suite.append(['^.*B', '', [('**** Failers', None), ('abc\nB', None)]]) -suite.append(['^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]', '', [('123456654321', ' 0: 123456654321')]]) -suite.append(['^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d', '', [('123456654321', ' 0: 123456654321')]]) -suite.append(['^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]', '', [('123456654321', ' 0: 123456654321')]]) -suite.append(['^[abc]{12}', '', [('abcabcabcabc', ' 0: abcabcabcabc')]]) -suite.append(['^[a-c]{12}', '', [('abcabcabcabc', ' 0: abcabcabcabc')]]) -suite.append(['^(a|b|c){12}', '', [('abcabcabcabc', ' 0: abcabcabcabc')]]) -suite.append(['^[abcdefghijklmnopqrstuvwxy0123456789]', '', [('n', ' 0: n'), ('*** Failers', None), ('z', None)]]) -suite.append(['abcde{0,0}', '', [('abcd', ' 0: abcd'), ('*** Failers', None), ('abce', None)]]) -suite.append(['ab[cd]{0,0}e', '', [('abe', ' 0: abe'), ('*** Failers', None), ('abcde', None)]]) -suite.append(['ab(c){0,0}d', '', [('abd', ' 0: abd'), ('*** Failers', None), ('abcd', None)]]) -suite.append(['a(b*)', '', [('a', ' 0: a'), ('ab', ' 0: ab'), ('abbbb', ' 0: abbbb'), ('*** Failers', ' 0: a'), ('bbbbb', None)]]) -suite.append(['ab\\d{0}e', '', [('abe', ' 0: abe'), ('*** Failers', None), ('ab1e', None)]]) -suite.append(['"([^\\\\"]+|\\\\.)*"', '', [('the "quick" brown fox', ' 0: "quick"'), ('"the \\"quick\\" brown fox"', ' 0: "the \\"quick\\" brown fox"')]]) -suite.append(['a[^a]b', '', [('acb', ' 0: acb'), ('a\nb', ' 0: a\nb')]]) -suite.append(['a.b', '', [('acb', ' 0: acb'), ('*** Failers', None), ('a\nb', None)]]) -suite.append(['\\x00{ab}', '', [('\x00{ab}', ' 0: \x00{ab}')]]) -suite.append(['(A|B)*CD', '', [('CD', ' 0: CD')]]) -suite.append(['(\\d+)(\\w)', '', [('12345a', ' 0: 12345a'), ('12345+', ' 0: 12345')]]) -suite.append(['(a+|b+|c+)*c', '', [('aaabbbbccccd', ' 0: aaabbbbcccc')]]) -suite.append(['(abc|)+', '', [('abc', ' 0: abc'), ('abcabc', ' 0: abcabc'), ('abcabcabc', ' 0: abcabcabc'), ('xyz', ' 0: ')]]) -suite.append(['([a]*)*', '', [('a', ' 0: a'), ('aaaaa', ' 0: aaaaa')]]) -suite.append(['([ab]*)*', '', [('a', ' 0: a'), ('b', ' 0: b'), ('ababab', ' 0: ababab'), ('aaaabcde', ' 0: aaaab'), ('bbbb', ' 0: bbbb')]]) -suite.append(['([^a]*)*', '', [('b', ' 0: b'), ('bbbb', ' 0: bbbb'), ('aaa', ' 0: ')]]) -suite.append(['([^ab]*)*', '', [('cccc', ' 0: cccc'), ('abab', ' 0: ')]]) +suite.append(['^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]', '', [('123456654321', '123456654321')]]) +suite.append(['^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d', '', [('123456654321', '123456654321')]]) +suite.append(['^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]', '', [('123456654321', '123456654321')]]) +suite.append(['^[abc]{12}', '', [('abcabcabcabc', 'abcabcabcabc')]]) +suite.append(['^[a-c]{12}', '', [('abcabcabcabc', 'abcabcabcabc')]]) +suite.append(['^(a|b|c){12}', '', [('abcabcabcabc', 'abcabcabcabc')]]) +suite.append(['^[abcdefghijklmnopqrstuvwxy0123456789]', '', [('n', 'n'), ('*** Failers', None), ('z', None)]]) +suite.append(['abcde{0,0}', '', [('abcd', 'abcd'), ('*** Failers', None), ('abce', None)]]) +suite.append(['ab[cd]{0,0}e', '', [('abe', 'abe'), ('*** Failers', None), ('abcde', None)]]) +suite.append(['ab(c){0,0}d', '', [('abd', 'abd'), ('*** Failers', None), ('abcd', None)]]) +suite.append(['a(b*)', '', [('a', 'a'), ('ab', 'ab'), ('abbbb', 'abbbb'), ('*** Failers', 'a'), ('bbbbb', None)]]) +suite.append(['ab\\d{0}e', '', [('abe', 'abe'), ('*** Failers', None), ('ab1e', None)]]) +suite.append(['"([^\\\\"]+|\\\\.)*"', '', [('the "quick" brown fox', '"quick"'), ('"the \\"quick\\" brown fox"', '"the \\"quick\\" brown fox"')]]) +suite.append(['a[^a]b', '', [('acb', 'acb'), ('a\nb', 'a\nb')]]) +suite.append(['a.b', '', [('acb', 'acb'), ('*** Failers', None), ('a\nb', None)]]) +suite.append(['\\x00{ab}', '', [('\x00{ab}', '\x00{ab}')]]) +suite.append(['(A|B)*CD', '', [('CD', 'CD')]]) +suite.append(['(\\d+)(\\w)', '', [('12345a', '12345a'), ('12345+', '12345')]]) +suite.append(['(a+|b+|c+)*c', '', [('aaabbbbccccd', 'aaabbbbcccc')]]) +suite.append(['(abc|)+', '', [('abc', 'abc'), ('abcabc', 'abcabc'), ('abcabcabc', 'abcabcabc'), ('xyz', '')]]) +suite.append(['([a]*)*', '', [('a', 'a'), ('aaaaa', 'aaaaa')]]) +suite.append(['([ab]*)*', '', [('a', 'a'), ('b', 'b'), ('ababab', 'ababab'), ('aaaabcde', 'aaaab'), ('bbbb', 'bbbb')]]) +suite.append(['([^a]*)*', '', [('b', 'b'), ('bbbb', 'bbbb'), ('aaa', '')]]) +suite.append(['([^ab]*)*', '', [('cccc', 'cccc'), ('abab', '')]]) suite.append(['The following tests are taken from the Perl 5.005 test suite; some of them', '', [("/are compatible with 5.004, but I'd rather not have to sort them out./", None)]]) -suite.append(['abc', '', [('abc', ' 0: abc'), ('xabcy', ' 0: abc'), ('ababc', ' 0: abc'), ('*** Failers', None), ('xbc', None), ('axc', None), ('abx', None)]]) -suite.append(['ab*c', '', [('abc', ' 0: abc')]]) -suite.append(['ab*bc', '', [('abc', ' 0: abc'), ('abbc', ' 0: abbc'), ('abbbbc', ' 0: abbbbc')]]) -suite.append(['.{1}', '', [('abbbbc', ' 0: a')]]) -suite.append(['.{3,4}', '', [('abbbbc', ' 0: abbb')]]) -suite.append(['ab{0,}bc', '', [('abbbbc', ' 0: abbbbc')]]) -suite.append(['ab+bc', '', [('abbc', ' 0: abbc'), ('*** Failers', None), ('abc', None), ('abq', None)]]) -suite.append(['ab{1,}bc', '', []]) -suite.append(['ab+bc', '', [('abbbbc', ' 0: abbbbc')]]) -suite.append(['ab{1,}bc', '', [('abbbbc', ' 0: abbbbc')]]) -suite.append(['ab{1,3}bc', '', [('abbbbc', ' 0: abbbbc')]]) -suite.append(['ab{3,4}bc', '', [('abbbbc', ' 0: abbbbc')]]) +suite.append(['abc', '', [('abc', 'abc'), ('xabcy', 'abc'), ('ababc', 'abc'), ('*** Failers', None), ('xbc', None), ('axc', None), ('abx', None)]]) +suite.append(['ab*c', '', [('abc', 'abc')]]) +suite.append(['ab*bc', '', [('abc', 'abc'), ('abbc', 'abbc'), ('abbbbc', 'abbbbc')]]) +suite.append(['.{1}', '', [('abbbbc', 'a')]]) +suite.append(['.{3,4}', '', [('abbbbc', 'abbb')]]) +suite.append(['ab{0,}bc', '', [('abbbbc', 'abbbbc')]]) +suite.append(['ab+bc', '', [('abbc', 'abbc'), ('*** Failers', None), ('abc', None), ('abq', None)]]) +suite.append(['ab+bc', '', [('abbbbc', 'abbbbc')]]) +suite.append(['ab{1,}bc', '', [('abbbbc', 'abbbbc')]]) +suite.append(['ab{1,3}bc', '', [('abbbbc', 'abbbbc')]]) +suite.append(['ab{3,4}bc', '', [('abbbbc', 'abbbbc')]]) suite.append(['ab{4,5}bc', '', [('*** Failers', None), ('abq', None), ('abbbbc', None)]]) -suite.append(['ab?bc', '', [('abbc', ' 0: abbc'), ('abc', ' 0: abc')]]) -suite.append(['ab{0,1}bc', '', [('abc', ' 0: abc')]]) -suite.append(['ab?bc', '', []]) -suite.append(['ab?c', '', [('abc', ' 0: abc')]]) -suite.append(['ab{0,1}c', '', [('abc', ' 0: abc')]]) -suite.append(['^abc$', '', [('abc', ' 0: abc'), ('*** Failers', None), ('abbbbc', None), ('abcc', None)]]) -suite.append(['^abc', '', [('abcc', ' 0: abc')]]) -suite.append(['^abc$', '', []]) -suite.append(['abc$', '', [('aabc', ' 0: abc'), ('*** Failers', None), ('aabc', ' 0: abc'), ('aabcd', None)]]) -suite.append(['^', '', [('abc', ' 0: ')]]) -suite.append(['$', '', [('abc', ' 0: ')]]) -suite.append(['a.c', '', [('abc', ' 0: abc'), ('axc', ' 0: axc')]]) -suite.append(['a.*c', '', [('axyzc', ' 0: axyzc')]]) -suite.append(['a[bc]d', '', [('abd', ' 0: abd'), ('*** Failers', None), ('axyzd', None), ('abc', None)]]) -suite.append(['a[b-d]e', '', [('ace', ' 0: ace')]]) -suite.append(['a[b-d]', '', [('aac', ' 0: ac')]]) -suite.append(['a[-b]', '', [('a-', ' 0: a-')]]) -suite.append(['a[b-]', '', [('a-', ' 0: a-')]]) -suite.append(['a]', '', [('a]', ' 0: a]')]]) -suite.append(['a[]]b', '', [('a]b', ' 0: a]b')]]) -suite.append(['a[^bc]d', '', [('aed', ' 0: aed'), ('*** Failers', None), ('abd', None), ('abd', None)]]) -suite.append(['a[^-b]c', '', [('adc', ' 0: adc')]]) -suite.append(['a[^]b]c', '', [('adc', ' 0: adc'), ('*** Failers', None), ('a-c', ' 0: a-c'), ('a]c', None)]]) -suite.append(['\\w', '', [('a', ' 0: a')]]) -suite.append(['\\W', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('a', None)]]) -suite.append(['a\\sb', '', [('a b', ' 0: a b')]]) -suite.append(['a\\Sb', '', [('a-b', ' 0: a-b'), ('*** Failers', None), ('a-b', ' 0: a-b'), ('a b', None)]]) -suite.append(['\\d', '', [('1', ' 0: 1')]]) -suite.append(['\\D', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('1', None)]]) -suite.append(['[\\w]', '', [('a', ' 0: a')]]) -suite.append(['[\\W]', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('a', None)]]) -suite.append(['a[\\s]b', '', [('a b', ' 0: a b')]]) -suite.append(['a[\\S]b', '', [('a-b', ' 0: a-b'), ('*** Failers', None), ('a-b', ' 0: a-b'), ('a b', None)]]) -suite.append(['[\\d]', '', [('1', ' 0: 1')]]) -suite.append(['[\\D]', '', [('-', ' 0: -'), ('*** Failers', ' 0: *'), ('-', ' 0: -'), ('1', None)]]) -suite.append(['ab|cd', '', [('abc', ' 0: ab'), ('abcd', ' 0: ab')]]) -suite.append(['()ef', '', [('def', ' 0: ef')]]) -suite.append(['$b', '', []]) -suite.append(['a\\(b', '', [('a(b', ' 0: a(b')]]) -suite.append(['a\\(*b', '', [('ab', ' 0: ab'), ('a((b', ' 0: a((b')]]) -suite.append(['a\\\\b', '', []]) -suite.append(['((a))', '', [('abc', ' 0: a')]]) -suite.append(['(a)b(c)', '', [('abc', ' 0: abc')]]) -suite.append(['a+b+c', '', [('aabbabc', ' 0: abc')]]) -suite.append(['a{1,}b{1,}c', '', [('aabbabc', ' 0: abc')]]) -suite.append(['(a+|b)*', '', [('ab', ' 0: ab')]]) -suite.append(['(a+|b){0,}', '', [('ab', ' 0: ab')]]) -suite.append(['(a+|b)+', '', [('ab', ' 0: ab')]]) -suite.append(['(a+|b){1,}', '', [('ab', ' 0: ab')]]) -suite.append(['(a+|b)?', '', [('ab', ' 0: a')]]) -suite.append(['(a+|b){0,1}', '', [('ab', ' 0: a')]]) -suite.append(['[^ab]*', '', [('cde', ' 0: cde')]]) +suite.append(['ab?bc', '', [('abbc', 'abbc'), ('abc', 'abc')]]) +suite.append(['ab{0,1}bc', '', [('abc', 'abc')]]) +suite.append(['ab?c', '', [('abc', 'abc')]]) +suite.append(['ab{0,1}c', '', [('abc', 'abc')]]) +suite.append(['^abc$', '', [('abc', 'abc'), ('*** Failers', None), ('abbbbc', None), ('abcc', None)]]) +suite.append(['^abc', '', [('abcc', 'abc')]]) +suite.append(['abc$', '', [('aabc', 'abc'), ('*** Failers', None), ('aabc', 'abc'), ('aabcd', None)]]) +suite.append(['^', '', [('abc', '')]]) +suite.append(['$', '', [('abc', '')]]) +suite.append(['a.c', '', [('abc', 'abc'), ('axc', 'axc')]]) +suite.append(['a.*c', '', [('axyzc', 'axyzc')]]) +suite.append(['a[bc]d', '', [('abd', 'abd'), ('*** Failers', None), ('axyzd', None), ('abc', None)]]) +suite.append(['a[b-d]e', '', [('ace', 'ace')]]) +suite.append(['a[b-d]', '', [('aac', 'ac')]]) +suite.append(['a[-b]', '', [('a-', 'a-')]]) +suite.append(['a[b-]', '', [('a-', 'a-')]]) +suite.append(['a]', '', [('a]', 'a]')]]) +suite.append(['a[]]b', '', [('a]b', 'a]b')]]) +suite.append(['a[^bc]d', '', [('aed', 'aed'), ('*** Failers', None), ('abd', None), ('abd', None)]]) +suite.append(['a[^-b]c', '', [('adc', 'adc')]]) +suite.append(['a[^]b]c', '', [('adc', 'adc'), ('*** Failers', None), ('a-c', 'a-c'), ('a]c', None)]]) +suite.append(['\\w', '', [('a', 'a')]]) +suite.append(['\\W', '', [('-', '-'), ('*** Failers', '*'), ('-', '-'), ('a', None)]]) +suite.append(['a\\sb', '', [('a b', 'a b')]]) +suite.append(['a\\Sb', '', [('a-b', 'a-b'), ('*** Failers', None), ('a-b', 'a-b'), ('a b', None)]]) +suite.append(['\\d', '', [('1', '1')]]) +suite.append(['\\D', '', [('-', '-'), ('*** Failers', '*'), ('-', '-'), ('1', None)]]) +suite.append(['[\\w]', '', [('a', 'a')]]) +suite.append(['[\\W]', '', [('-', '-'), ('*** Failers', '*'), ('-', '-'), ('a', None)]]) +suite.append(['a[\\s]b', '', [('a b', 'a b')]]) +suite.append(['a[\\S]b', '', [('a-b', 'a-b'), ('*** Failers', None), ('a-b', 'a-b'), ('a b', None)]]) +suite.append(['[\\d]', '', [('1', '1')]]) +suite.append(['[\\D]', '', [('-', '-'), ('*** Failers', '*'), ('-', '-'), ('1', None)]]) +suite.append(['ab|cd', '', [('abc', 'ab'), ('abcd', 'ab')]]) +suite.append(['()ef', '', [('def', 'ef')]]) +suite.append(['a\\(b', '', [('a(b', 'a(b')]]) +suite.append(['a\\(*b', '', [('ab', 'ab'), ('a((b', 'a((b')]]) +suite.append(['((a))', '', [('abc', 'a')]]) +suite.append(['(a)b(c)', '', [('abc', 'abc')]]) +suite.append(['a+b+c', '', [('aabbabc', 'abc')]]) +suite.append(['a{1,}b{1,}c', '', [('aabbabc', 'abc')]]) +suite.append(['(a+|b)*', '', [('ab', 'ab')]]) +suite.append(['(a+|b){0,}', '', [('ab', 'ab')]]) +suite.append(['(a+|b)+', '', [('ab', 'ab')]]) +suite.append(['(a+|b){1,}', '', [('ab', 'ab')]]) +suite.append(['(a+|b)?', '', [('ab', 'a')]]) +suite.append(['(a+|b){0,1}', '', [('ab', 'a')]]) +suite.append(['[^ab]*', '', [('cde', 'cde')]]) suite.append(['abc', '', [('*** Failers', None), ('b', None)]]) -suite.append(['a*', '', []]) -suite.append(['([abc])*d', '', [('abbbcd', ' 0: abbbcd')]]) -suite.append(['([abc])*bcd', '', [('abcd', ' 0: abcd')]]) -suite.append(['a|b|c|d|e', '', [('e', ' 0: e')]]) -suite.append(['(a|b|c|d|e)f', '', [('ef', ' 0: ef')]]) -suite.append(['abcd*efg', '', [('abcdefg', ' 0: abcdefg')]]) -suite.append(['ab*', '', [('xabyabbbz', ' 0: ab'), ('xayabbbz', ' 0: a')]]) -suite.append(['(ab|cd)e', '', [('abcde', ' 0: cde')]]) -suite.append(['[abhgefdc]ij', '', [('hij', ' 0: hij')]]) -suite.append(['^(ab|cd)e', '', []]) -suite.append(['(abc|)ef', '', [('abcdef', ' 0: ef')]]) -suite.append(['(a|b)c*d', '', [('abcd', ' 0: bcd')]]) -suite.append(['(ab|ab*)bc', '', [('abc', ' 0: abc')]]) -suite.append(['a([bc]*)c*', '', [('abc', ' 0: abc')]]) -suite.append(['a([bc]*)(c*d)', '', [('abcd', ' 0: abcd')]]) -suite.append(['a([bc]+)(c*d)', '', [('abcd', ' 0: abcd')]]) -suite.append(['a([bc]*)(c+d)', '', [('abcd', ' 0: abcd')]]) -suite.append(['a[bcd]*dcdcde', '', [('adcdcde', ' 0: adcdcde')]]) +suite.append(['([abc])*d', '', [('abbbcd', 'abbbcd')]]) +suite.append(['([abc])*bcd', '', [('abcd', 'abcd')]]) +suite.append(['a|b|c|d|e', '', [('e', 'e')]]) +suite.append(['(a|b|c|d|e)f', '', [('ef', 'ef')]]) +suite.append(['abcd*efg', '', [('abcdefg', 'abcdefg')]]) +suite.append(['ab*', '', [('xabyabbbz', 'ab'), ('xayabbbz', 'a')]]) +suite.append(['(ab|cd)e', '', [('abcde', 'cde')]]) +suite.append(['[abhgefdc]ij', '', [('hij', 'hij')]]) +suite.append(['(abc|)ef', '', [('abcdef', 'ef')]]) +suite.append(['(a|b)c*d', '', [('abcd', 'bcd')]]) +suite.append(['(ab|ab*)bc', '', [('abc', 'abc')]]) +suite.append(['a([bc]*)c*', '', [('abc', 'abc')]]) +suite.append(['a([bc]*)(c*d)', '', [('abcd', 'abcd')]]) +suite.append(['a([bc]+)(c*d)', '', [('abcd', 'abcd')]]) +suite.append(['a([bc]*)(c+d)', '', [('abcd', 'abcd')]]) +suite.append(['a[bcd]*dcdcde', '', [('adcdcde', 'adcdcde')]]) suite.append(['a[bcd]+dcdcde', '', [('*** Failers', None), ('abcde', None), ('adcdcde', None)]]) -suite.append(['(ab|a)b*c', '', [('abc', ' 0: abc')]]) -suite.append(['((a)(b)c)(d)', '', [('abcd', ' 0: abcd')]]) -suite.append(['[a-zA-Z_][a-zA-Z0-9_]*', '', [('alpha', ' 0: alpha')]]) -suite.append(['^a(bc+|b[eh])g|.h$', '', [('abh', ' 0: bh')]]) -suite.append(['(bc+d$|ef*g.|h?i(j|k))', '', [('effgz', ' 0: effgz'), ('ij', ' 0: ij'), ('reffgz', ' 0: effgz'), ('*** Failers', None), ('effg', None), ('bcdd', None)]]) -suite.append(['((((((((((a))))))))))', '', [('a', ' 0: a')]]) -suite.append(['(((((((((a)))))))))', '', [('a', ' 0: a')]]) +suite.append(['(ab|a)b*c', '', [('abc', 'abc')]]) +suite.append(['((a)(b)c)(d)', '', [('abcd', 'abcd')]]) +suite.append(['[a-zA-Z_][a-zA-Z0-9_]*', '', [('alpha', 'alpha')]]) +suite.append(['^a(bc+|b[eh])g|.h$', '', [('abh', 'bh')]]) +suite.append(['(bc+d$|ef*g.|h?i(j|k))', '', [('effgz', 'effgz'), ('ij', 'ij'), ('reffgz', 'effgz'), ('*** Failers', None), ('effg', None), ('bcdd', None)]]) +suite.append(['((((((((((a))))))))))', '', [('a', 'a')]]) +suite.append(['(((((((((a)))))))))', '', [('a', 'a')]]) suite.append(['multiple words of text', '', [('*** Failers', None), ('aa', None), ('uh-uh', None)]]) -suite.append(['multiple words', '', [('multiple words, yeah', ' 0: multiple words')]]) -suite.append(['(.*)c(.*)', '', [('abcde', ' 0: abcde')]]) -suite.append(['\\((.*), (.*)\\)', '', [('(a, b)', ' 0: (a, b)')]]) -suite.append(['[k]', '', []]) -suite.append(['abcd', '', [('abcd', ' 0: abcd')]]) -suite.append(['a(bc)d', '', [('abcd', ' 0: abcd')]]) -suite.append(['a[-]?c', '', [('ac', ' 0: ac')]]) -suite.append(['((foo)|(bar))*', '', [('foobar', ' 0: foobar')]]) -suite.append(['^(.+)?B', '', [('AB', ' 0: AB')]]) -suite.append(['^([^a-z])|(\\^)$', '', [('.', ' 0: .')]]) -suite.append(['^[<>]&', '', [('<&OUT', ' 0: <&')]]) -suite.append(['^(){3,5}', '', [('abc', ' 0: ')]]) -suite.append(['^(a+)*ax', '', [('aax', ' 0: aax')]]) -suite.append(['^((a|b)+)*ax', '', [('aax', ' 0: aax')]]) -suite.append(['^((a|bc)+)*ax', '', [('aax', ' 0: aax')]]) -suite.append(['(a|x)*ab', '', [('cab', ' 0: ab')]]) -suite.append(['(a)*ab', '', [('cab', ' 0: ab')]]) -suite.append(['foo\\w*\\d{4}baz', '', [('foobar1234baz', ' 0: foobar1234baz')]]) -suite.append(['^b', '', []]) -suite.append(['(\\w+:)+', '', [('one:', ' 0: one:')]]) -suite.append(['([\\w:]+::)?(\\w+)$', '', [('abcd', ' 0: abcd'), ('xy:z:::abcd', ' 0: xy:z:::abcd')]]) -suite.append(['^[^bcd]*(c+)', '', [('aexycd', ' 0: aexyc')]]) -suite.append(['(a*)b+', '', [('caab', ' 0: aab')]]) -suite.append(['([\\w:]+::)?(\\w+)$', '', [('abcd', ' 0: abcd'), ('xy:z:::abcd', ' 0: xy:z:::abcd'), ('*** Failers', ' 0: Failers'), ('abcd:', None), ('abcd:', None)]]) -suite.append(['^[^bcd]*(c+)', '', [('aexycd', ' 0: aexyc')]]) -suite.append(['(>a+)ab', '', []]) -suite.append(['([[:]+)', '', [('a:[b]:', ' 0: :[')]]) -suite.append(['([[=]+)', '', [('a=[b]=', ' 0: =[')]]) -suite.append(['([[.]+)', '', [('a.[b].', ' 0: .[')]]) -suite.append(['((Z)+|A)*', '', [('ZABCDEFG', ' 0: ZA')]]) -suite.append(['(Z()|A)*', '', [('ZABCDEFG', ' 0: ZA')]]) -suite.append(['(Z(())|A)*', '', [('ZABCDEFG', ' 0: ZA')]]) -suite.append(['^[a-\\d]', '', [('abcde', ' 0: a'), ('-things', ' 0: -'), ('0digit', ' 0: 0'), ('*** Failers', None), ('bcdef', None)]]) -suite.append(['^[\\d-a]', '', [('abcde', ' 0: a'), ('-things', ' 0: -'), ('0digit', ' 0: 0'), ('*** Failers', None), ('bcdef', None)]]) -suite.append(['[\\s]+', '', [('> \t\n\x0c\r\x0b<', ' 0: \t\n\x0c\r')]]) -suite.append(['\\s+', '', [('> \t\n\x0c\r\x0b<', ' 0: \t\n\x0c\r')]]) -suite.append(['\\M', '', [('M', ' 0: M')]]) +suite.append(['multiple words', '', [('multiple words, yeah', 'multiple words')]]) +suite.append(['(.*)c(.*)', '', [('abcde', 'abcde')]]) +suite.append(['\\((.*), (.*)\\)', '', [('(a, b)', '(a, b)')]]) +suite.append(['abcd', '', [('abcd', 'abcd')]]) +suite.append(['a(bc)d', '', [('abcd', 'abcd')]]) +suite.append(['a[-]?c', '', [('ac', 'ac')]]) +suite.append(['((foo)|(bar))*', '', [('foobar', 'foobar')]]) +suite.append(['^(.+)?B', '', [('AB', 'AB')]]) +suite.append(['^([^a-z])|(\\^)$', '', [('.', '.')]]) +suite.append(['^[<>]&', '', [('<&OUT', '<&')]]) +suite.append(['^(){3,5}', '', [('abc', '')]]) +suite.append(['^(a+)*ax', '', [('aax', 'aax')]]) +suite.append(['^((a|b)+)*ax', '', [('aax', 'aax')]]) +suite.append(['^((a|bc)+)*ax', '', [('aax', 'aax')]]) +suite.append(['(a|x)*ab', '', [('cab', 'ab')]]) +suite.append(['(a)*ab', '', [('cab', 'ab')]]) +suite.append(['foo\\w*\\d{4}baz', '', [('foobar1234baz', 'foobar1234baz')]]) +suite.append(['(\\w+:)+', '', [('one:', 'one:')]]) +suite.append(['([\\w:]+::)?(\\w+)$', '', [('abcd', 'abcd'), ('xy:z:::abcd', 'xy:z:::abcd')]]) +suite.append(['^[^bcd]*(c+)', '', [('aexycd', 'aexyc')]]) +suite.append(['(a*)b+', '', [('caab', 'aab')]]) +suite.append(['([\\w:]+::)?(\\w+)$', '', [('abcd', 'abcd'), ('xy:z:::abcd', 'xy:z:::abcd'), ('*** Failers', 'Failers'), ('abcd:', None), ('abcd:', None)]]) +suite.append(['^[^bcd]*(c+)', '', [('aexycd', 'aexyc')]]) +suite.append(['([[:]+)', '', [('a:[b]:', ':[')]]) +suite.append(['([[=]+)', '', [('a=[b]=', '=[')]]) +suite.append(['([[.]+)', '', [('a.[b].', '.[')]]) +suite.append(['((Z)+|A)*', '', [('ZABCDEFG', 'ZA')]]) +suite.append(['(Z()|A)*', '', [('ZABCDEFG', 'ZA')]]) +suite.append(['(Z(())|A)*', '', [('ZABCDEFG', 'ZA')]]) +suite.append(['^[a-\\d]', '', [('abcde', 'a'), ('-things', '-'), ('0digit', '0'), ('*** Failers', None), ('bcdef', None)]]) +suite.append(['^[\\d-a]', '', [('abcde', 'a'), ('-things', '-'), ('0digit', '0'), ('*** Failers', None), ('bcdef', None)]]) +suite.append(['[\\s]+', '', [('> \t\n\x0c\r\x0b<', ' \t\n\x0c\r')]]) +suite.append(['\\s+', '', [('> \t\n\x0c\r\x0b<', ' \t\n\x0c\r')]]) +suite.append(['\\M', '', [('M', 'M')]]) suite.append(['(a+)*b', '', [('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', None)]]) -suite.append(['\xc5\xe6\xe5\xe4[\xe0-\xff\xc0-\xdf]+', '', [('\xc5\xe6\xe5\xe4\xe0', ' 0: \xc5\xe6\xe5\xe4\xe0'), ('\xc5\xe6\xe5\xe4\xff', ' 0: \xc5\xe6\xe5\xe4\xff'), ('\xc5\xe6\xe5\xe4\xc0', ' 0: \xc5\xe6\xe5\xe4\xc0'), ('\xc5\xe6\xe5\xe4\xdf', ' 0: \xc5\xe6\xe5\xe4\xdf')]]) -suite.append(['line\\nbreak', '', [('this is a line\nbreak', ' 0: line\nbreak'), ('line one\nthis is a line\nbreak in the second line', ' 0: line\nbreak')]]) -suite.append(['1234', '', []]) -suite.append(['1234', '', []]) -suite.append(['Content-Type\\x3A[^\\r\\n]{6,}', '', [('Content-Type:xxxxxyyy', ' 0: Content-Type:xxxxxyyy')]]) -suite.append(['Content-Type\\x3A[^\\r\\n]{6,}z', '', [('Content-Type:xxxxxyyyz', ' 0: Content-Type:xxxxxyyyz')]]) -suite.append(['Content-Type\\x3A[^a]{6,}', '', [('Content-Type:xxxyyy', ' 0: Content-Type:xxxyyy')]]) -suite.append(['Content-Type\\x3A[^a]{6,}z', '', [('Content-Type:xxxyyyz', ' 0: Content-Type:xxxyyyz')]]) -suite.append(['^\\w+=.*(\\\\\\n.*)*', '', [('abc=xyz\\\npqr', ' 0: abc=xyz\\\npqr')]]) -suite.append(['^(a()*)*', '', [('aaaa', ' 0: aaaa')]]) -suite.append(['^(a()+)+', '', [('aaaa', ' 0: aaaa')]]) -suite.append(['(a|)*\\d', '', [('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', None), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4', ' 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4')]]) -suite.append(['.+foo', '', [('afoo', ' 0: afoo'), ('** Failers', None), ('\r\nfoo', None), ('\nfoo', None)]]) -suite.append([' End of testinput7 ', '', []]) +suite.append(['\xc5\xe6\xe5\xe4[\xe0-\xff\xc0-\xdf]+', '', [('\xc5\xe6\xe5\xe4\xe0', '\xc5\xe6\xe5\xe4\xe0'), ('\xc5\xe6\xe5\xe4\xff', '\xc5\xe6\xe5\xe4\xff'), ('\xc5\xe6\xe5\xe4\xc0', '\xc5\xe6\xe5\xe4\xc0'), ('\xc5\xe6\xe5\xe4\xdf', '\xc5\xe6\xe5\xe4\xdf')]]) +suite.append(['line\\nbreak', '', [('this is a line\nbreak', 'line\nbreak'), ('line one\nthis is a line\nbreak in the second line', 'line\nbreak')]]) +suite.append(['Content-Type\\x3A[^\\r\\n]{6,}', '', [('Content-Type:xxxxxyyy', 'Content-Type:xxxxxyyy')]]) +suite.append(['Content-Type\\x3A[^\\r\\n]{6,}z', '', [('Content-Type:xxxxxyyyz', 'Content-Type:xxxxxyyyz')]]) +suite.append(['Content-Type\\x3A[^a]{6,}', '', [('Content-Type:xxxyyy', 'Content-Type:xxxyyy')]]) +suite.append(['Content-Type\\x3A[^a]{6,}z', '', [('Content-Type:xxxyyyz', 'Content-Type:xxxyyyz')]]) +suite.append(['^\\w+=.*(\\\\\\n.*)*', '', [('abc=xyz\\\npqr', 'abc=xyz\\\npqr')]]) +suite.append(['^(a()*)*', '', [('aaaa', 'aaaa')]]) +suite.append(['^(a()+)+', '', [('aaaa', 'aaaa')]]) +suite.append(['(a|)*\\d', '', [('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', None), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4')]]) +suite.append(['.+foo', '', [('afoo', 'afoo'), ('** Failers', None), ('\r\nfoo', None), ('\nfoo', None)]]) Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Sat Apr 5 19:37:39 2008 @@ -87,11 +87,14 @@ py.test.skip("Still in progress") +# Dumper's are objects that can dump/load the suite class Dumper(object): def __init__(self, file): pass def dump(self, tests): pass + def load(self): + return [] class PickleDumper(Dumper): import pickle @@ -118,12 +121,12 @@ exec text in d return d['suite'] +def generate_output7(): + """Create the testoutput7.py file from the PCRE file testoutput7""" + create_pcre_pickle(open('testoutput7','r'), PythonDumper(open('pcre_test_7.py','w'))) + def create_pcre_pickle(file, dumper): - """Create a filtered PCRE test file for the test. - - The pickle file was created by: - create_pcre_pickle(open('testoutput1','r'), open('testoutput1.pickle','w')) - """ + """Create a filtered PCRE test file for the test.""" lines = [line for line in file.readlines()] # Look for things to skip... @@ -225,6 +228,7 @@ elif match.startswith(' 0:'): # Now we need to eat any further lines like: # ' 1: ....' a subgroup match + match = match[4:] while lines[0].strip(): # ' 0+ ...' is also possible here if lines[0][2] in [':','+']: @@ -237,9 +241,17 @@ raise Exception("Lost sync in output.") if not disqualify_test: tests.append((test,match)) + + # Last step, if there are regex's that dont have any tests, + # might as well strip them out + suite = [test for test in suite if test[2]] + dumper.dump(suite) def run_individual_test(regex, tests): + """Run a test from the PCRE suite.""" + + # Process the regex and make it ready for make_runner regex_to_use = regex anchor_left = regex_to_use.startswith('^') @@ -256,9 +268,10 @@ print "%s:" % regex_to_use runner = make_runner(regex_to_use) + # Now run the test expressions against the Regex for test, match in tests: - print "/%r/%r/"%(test, match) + print "/%r/%r/" % (test, match) # Create possible subsequences that we should test if anchor_left: @@ -276,26 +289,17 @@ for start, end in subseq_gen: attempt = test[start:end] if runner.recognize(attempt): - assert match and attempt==match[4:] + assert attempt==match break else: - assert not match + assert match is None -def run_pcre_tests(suite): - """Run PCRE tests as given in suite.""" +def test_output7(): + suite = PythonDumper(open('pcre_test_7.py','r')).load() while suite: regex, flags, tests = suite.pop(0) yield run_individual_test, regex, tests -def test_output7(): - suite = PythonDumper(open('pcre_test_7.py','r')).load() - for test in run_pcre_tests(suite): - yield test - -def generate_output7(): - """Create the testoutput1.pickle file from the PCRE file testoutput1""" - create_pcre_pickle(open('testoutput7','r'), PythonDumper(open('pcre_test_7.py','w'))) - if __name__=="__main__": for fcn, regex, tests in test_output7(): fcn(regex,tests) \ No newline at end of file From cami at codespeak.net Sun Apr 6 00:48:07 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 6 Apr 2008 00:48:07 +0200 (CEST) Subject: [pypy-svn] r53413 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080405224807.B797B16A713@codespeak.net> Author: cami Date: Sun Apr 6 00:48:06 2008 New Revision: 53413 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Log: extended timer tests cleaned up interrupt adapted interrupt tests introduced interrupt flag objects Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sun Apr 6 00:48:06 2008 @@ -51,8 +51,7 @@ self.cpu.cycles += 1 else: self.setHi(hi, useCycles) - self.setLo(lo, useCycles) - + self.setLo(lo, useCycles) def reset(self): self.set(self.resetValue, None, False) @@ -270,8 +269,6 @@ if self.halted: val += 0x80 return val - - def isZ(self): """ zero flag""" @@ -306,31 +303,23 @@ def isNotN(self): return not self.isN() - - + # Flags ............................................ - def setROM(self, banks): - self.rom = banks - + self.rom = banks def emulate(self, ticks): self.cycles += ticks - self.interrupt() + self.handlePendingInterrupt() while (self.cycles > 0): self.execute() # Interrupts - def interrupt(self, address=None): - if address != None: - self.ime = False - self.call(address) - return + def handlePendingInterrupt(self): if self.halted: if (self.interrupt.isPending()): self.halted = False - # Zerd no Densetsu self.cycles -= 4 elif (self.cycles > 0): self.cycles = 0 @@ -338,21 +327,10 @@ self.lowerPendingInterrupt() def lowerPendingInterrupt(self): - if (self.interrupt.isPending(constants.VBLANK)): - self.interrupt(0x40) - self.interrupt.lower(constants.VBLANK) - elif (self.interrupt.isPending(constants.LCD)): - self.interrupt(0x48) - self.interrupt.lower(constants.LCD) - elif (self.interrupt.isPending(constants.TIMER)): - self.interrupt(0x50) - self.interrupt.lower(constants.TIMER) - elif (self.interrupt.isPending(constants.SERIAL)): - self.interrupt(0x58) - self.interrupt.lower(constants.SERIAL) - elif (self.interrupt.isPending(constants.JOYPAD)): - self.interrupt(0x60) - self.interrupt.lower(constants.JOYPAD) + for flag in self.interrupt.interruptFlags: + if flag.isPending(): + self.call(flag.callCode, disableIme=True) + flag.setPending(False) # Execution def fetchExecute(self): @@ -383,6 +361,11 @@ data = self.memory.read(self.pc.get()) self.pc.inc() # 2 cycles return data + + def fetchDoubleAddress(self): + lo = self.fetch() # 1 cycle + hi = self.fetch() # 1 cycle + return (hi << 8) + lo def fetchDoubleRegister(self, register): self.popDoubleRegister(CPU.fetch, register) @@ -415,7 +398,9 @@ self.cycles += 1 # 4 cycles - def call(self, address): + def call(self, address, disableIME=False): + if disableIME: + self.ime = False self.push(self.pc.getHi()) # 2 cycles self.push(self.pc.getLo()) # 2 cycles self.pc.set(address) # 1 cycle @@ -457,24 +442,23 @@ s = self.a.get() + getter(); if self.f.cFlag: s +=1 - self.f.reset() - self.f.zeroFlagAdd(s) + self.carryFlagFinish(getter, 0x10) if s >= 0x100: self.f.cFlag= True - if ((s ^ self.a.get() ^ getter()) & 0x10) != 0: - self.f.hFlag= True - self.a.set(s & 0xFF) # 1 cycle # 1 cycle def subtractWithCarry(self, getter, setter=None): s = self.a.get() - getter(); if self.f.cFlag: s -= 1 - self.f.reset() - self.f.nFlag = True - self.f.zeroFlagAdd(s) + self.carryFlagFinish(getter, 0x10) if (s & 0xFF00) != 0: self.f.cFlag = True + self.f.nFlag = True + + def carryFlagFinish(self, getter): + self.f.reset() + self.f.zeroFlagAdd(s) if ((s ^ self.a.get() ^ getter()) & 0x10) != 0: self.f.hFlag = True self.a.set(s & 0xFF) # 1 cycle @@ -547,7 +531,6 @@ self.f.cFlagAdd(self.a.get(), 0x80, reset=True) self.a.set(((self.a.get() & 0x7F) << 1) + ((self.a.get() & 0x80) >> 7)) - # 1 cycle def rotateLeft(self, getter, setter): s = ((getter() & 0x7F) << 1) @@ -634,9 +617,7 @@ # LD A,(nnnn), 4 cycles def storeFetchedMemoryInA(self): - lo = self.fetch() # 1 cycle - hi = self.fetch() # 1 cycle - self.a.set(self.read(hi, lo)) # 1+1 cycles + self.a.set(self.read(self.fetchDoubleAddress())) # 1+1 + 2 cycles # 2 cycles def writeAAtBCAddress(self): @@ -657,18 +638,14 @@ # LD (nnnn),SP 5 cycles def load_mem_SP(self): - lo = self.fetch() # 1 cycle - hi = self.fetch() # 1 cycle - address = (hi << 8) + lo + address = self.fetchDoubleAddress() # 2 cycles self.write(address, self.sp.getLo()) # 2 cycles self.write((address + 1), self.sp.getHi()) # 2 cycles self.cycles += 1 # LD (nnnn),A 4 cycles - def storeAatFetchedAddress(self): - lo = self.fetch() # 1 cycle - hi = self.fetch() # 1 cycle - self.write((hi << 8) + lo, self.a.get()) # 2 cycles + def storeAAtFetchedAddress(self): + self.write(self.fetchDoubleAddress(), self.a.get()) # 2 cycles # LDH A,(nn) 3 cycles def storeMemoryAtExpandedFetchAddressInA(self): @@ -715,7 +692,7 @@ self.sp.set(self.hl.get()) # 1 cycle self.cycles -= 1 - # + # CPA def complementA(self): self.a.set(self.a.get() ^ 0xFF) self.f.nFlag = True @@ -793,9 +770,8 @@ # JP nnnn, 4 cycles def unconditionalJump(self): - lo = self.fetch() # 1 cycle - hi = self.fetch() # 1 cycle - self.pc.set(hi,lo) # 2 cycles + self.pc.set(self.fetchDoubleAddress()) # 1+2 cycles + self.cycles -= 1 # JP cc,nnnn 3,4 cycles def conditionalJump(self, cc): @@ -818,9 +794,7 @@ # CALL nnnn, 6 cycles def unconditionalCall(self): - lo = self.fetch() # 1 cycle - hi = self.fetch() # 1 cycle - self.call((hi << 8) + lo) # 4 cycles + self.call(self.fetchDoubleAddress()) # 4+2 cycles # CALL cc,nnnn, 3,6 cycles def conditionalCall(self, getter): @@ -847,12 +821,8 @@ # RETI 4 cycles def returnFormInterrupt(self): self.ret() # 4 cycles - # enable interrupts - self.ime = True - # execute next instruction - self.execute(self.fetch()) - # check pending interrupts - self.interrupt() + self.enableInterrupts() + self.cycles += 1 # RST nn 4 cycles def restart(self, nn): @@ -860,19 +830,15 @@ # DI/EI 1 cycle def disableInterrupts(self): - # disable interrupts self.ime = False self.cycles -= 1; # 1 cycle def enableInterrupts(self): - # enable interrupts self.ime = True self.cycles -= 1 - # execute next instruction self.execute(self.fetch()) - # check pending interrupts - self.interrupt() + self.handlePendingInterrupt() # HALT/STOP def halt(self): @@ -880,8 +846,7 @@ # emulate bug when interrupts are pending if (not self.ime and self.interrupt.isPending()): self.execute(self.memory.read(self.pc.get())) - # check pending interrupts - self.interrupt() + self.handlePendingInterrupt() # 0 cycles def stop(self): @@ -957,7 +922,7 @@ return result # OPCODE TABLES --------------------------------------------------------------- - + FIRST_ORDER_OP_CODES = [ (0x00, CPU.nop), (0x08, CPU.load_mem_SP), @@ -983,7 +948,7 @@ (0xF3, CPU.disableInterrupts), (0xFB, CPU.enableInterrupts), (0xE2, CPU.writeAAtExpandedCAddress), - (0xEA, CPU.storeAatFetchedAddress), + (0xEA, CPU.storeAAtFetchedAddress), (0xF2, CPU.storeExpandedCinA), (0xFA, CPU.storeFetchedMemoryInA), (0xC3, CPU.unconditionalJump), Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Sun Apr 6 00:48:06 2008 @@ -1,5 +1,24 @@ from pypy.lang.gameboy import constants + +class InterruptFlag(object): + + def __init__(self, _reset, mask, callCode): + self._reset = _reset + self.mask = mask + self.callCode = callCode + self.reset() + + def reset(self): + self._isPending = self._reset + + def isPending(self): + return self._isPending + + def setPending(self, _isPending): + self._isPending = _isPending + + class Interrupt(object): """ PyBoy GameBoy (TM) Emulator @@ -8,23 +27,50 @@ """ def __init__(self): + self.createInterruptFlags() + self.createFlagList() + self.createFlagMaskMapping() self.reset() - + + def createInterruptFlags(self): + self.vBlank = InterruptFlag(True, constants.VBLANK, 0x40) + self.lcd = InterruptFlag(False, constants.LCD, 0x48) + self.timer = InterruptFlag(False, constants.TIMER, 0x50) + self.serial = InterruptFlag(False, constants.SERIAL, 0x58) + self.joypad = InterruptFlag(False, constants.JOYPAD, 0x60) + + def createFlagList(self): + self.interruptFlags = [ + self.vBlank, self.lcd, + self.timer, self.serial, + self.joypad + ] + + def createFlagMaskMapping(self): + self.maskMapping = {} + for flag in self.interruptFlags: + self.maskMapping[flag.mask] = flag + def reset(self): - self.enable = 0 - self.flag = constants.VBLANK + self.enable = False + for flag in self.interruptFlags: + flag.reset() def isPending(self, mask=None): + if not self.enable: + return False if mask==None: - return (self.enable & self.flag) != 0 + return self.vBlank.isPending() + elif self.vBlank.isPending(): + return self.maskMapping[mask].isPending() else: - return (self.enable & self.flag & mask) != 0 + return False def raiseInterrupt(self, mask): - self.flag |= mask + self.maskMapping[mask].setPending(True) def lower(self, mask): - self.flag &= ~mask + self.maskMapping[mask].setPending(False) def write(self, address, data): if address == constants.IE: @@ -40,13 +86,21 @@ return 0xFF def getInterruptEnable(self): - return self.enable - - def getInterruptFlag(self): - return 0xE0 | self.flag + return int(self.enable) def setInterruptEnable(self, data): - self.enable = data + self.enable = bool(data) + + def getInterruptFlag(self): + flag = 0x00 + for interruptFlag in self.interruptFlags: + if interruptFlag.isPending(): + flag |= interruptFlag.mask + return 0xE0 | flag def setInterruptFlag(self, data): - self.flag = data + for flag in self.interruptFlags: + if (data & flag.mask) != 0: + flag.setPending(True) + else: + flag.setPending(False) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Sun Apr 6 00:48:06 2008 @@ -19,14 +19,14 @@ return self.cycles def emulate(self, ticks): - if ((self.sc & 0x81) == 0x81): - self.cycles -= ticks - if (self.cycles <= 0): - self.sb = 0xFF - self.sc &= 0x7F - self.cycles = constants.SERIAL_IDLE_CLOCK - self.interrupt.raiseInterrupt(constants.SERIAL) - + if ((self.sc & 0x81) != 0x81): + return + self.cycles -= ticks + if (self.cycles <= 0): + self.sb = 0xFF + self.sc &= 0x7F + self.cycles = constants.SERIAL_IDLE_CLOCK + self.interrupt.raiseInterrupt(constants.SERIAL) def setSerialData(self, data): self.sb = data Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sun Apr 6 00:48:06 2008 @@ -82,19 +82,15 @@ self.generateNoiseTables() self.reset() - def start(self): self.driver.start() - def stop(self): self.driver.stop() - def cycles(self): return self.cycles - def emulate(self, ticks): self.cycles -= ticks while (self.cycles <= 0): @@ -107,8 +103,6 @@ self.frames %= constants.SOUND_CLOCK self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK - - def reset(self): self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK @@ -197,10 +191,8 @@ elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): return self.getAudio3WavePattern(address) - return 0xFF - def write(self, address, data): if address==constants.NR10: self.setAudio1Sweep(data) @@ -252,7 +244,6 @@ elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): self.setAudio3WavePattern(address, data) - def updateAudio(self): if ((self.nr52 & 0x80) == 0): return @@ -265,10 +256,8 @@ if ((self.nr52 & 0x08) != 0): self.updateAudio4() - def mixAudio(self,buffer, length): - for index in range(0, length): - buffer[index] = 0 + buffer = [0]*length if ((self.nr52 & 0x80) == 0): return if ((self.nr52 & 0x01) != 0): @@ -280,38 +269,30 @@ if ((self.nr52 & 0x08) != 0): self.mixAudio4(buffer, length) - # Audio Channel 1 def getAudio1Sweep(self): return self.nr10 - def getAudio1Length(self): return self.nr11 - def getAudio1Envelope(self): return self.nr12 - def getAudio1Frequency(self): return self.nr13 - def getAudio1Playback(self): return self.nr14 - def setAudio1Sweep(self, data): self.nr10 = data self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07) - def setAudio1Length(self, data): self.nr11 = data self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F)) - def setAudio1Envelope(self, data): self.nr12 = data if ((self.nr14 & 0x40) != 0): @@ -323,12 +304,10 @@ else: self.audio1Volume = (self.audio1Volume + 2) & 0x0F - def setAudio1Frequency(self, data): self.nr13 = data self.audio1Frequency = self.frequencyTable[self.nr13 + ((self.nr14 & 0x07) << 8)] - def setAudio1Playback(self, data): self.nr14 = data self.audio1Frequency = self.frequencyTable[self.nr13 @@ -340,7 +319,6 @@ self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07) self.audio1Volume = self.nr12 >> 4 self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07) - def updateAudio1(self): if ((self.nr14 & 0x40) != 0 and self.audio1Length > 0): @@ -375,7 +353,6 @@ self.nr52 &= ~0x01 self.audio1SweepLength += (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07) - def mixAudio1(self, buffer, length): wavePattern = 0x18 @@ -399,29 +376,23 @@ if ((self.nr51 & 0x01) != 0): buffer[index + 1] += self.audio1Volume - # Audio Channel 2 def getAudio2Length(self): return self.nr21 - def getAudio2Envelope(self): return self.nr22 - def getAudio2Frequency(self): return self.nr23 - def getAudio2Playback(self): return self.nr24 - def setAudio2Length(self, data): self.nr21 = data self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F)) - def setAudio2Envelope(self, data): self.nr22 = data if ((self.nr24 & 0x40) == 0): @@ -432,13 +403,11 @@ else: self.audio2Volume = (self.audio2Volume + 2) & 0x0F - def setAudio2Frequency(self, data): self.nr23 = data self.audio2Frequency = self.frequencyTable[self.nr23\ + ((self.nr24 & 0x07) << 8)] - def setAudio2Playback(self, data): self.nr24 = data self.audio2Frequency = self.frequencyTable[self.nr23\ @@ -450,8 +419,6 @@ self.audio2Volume = self.nr22 >> 4 self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07) - - def updateAudio2(self): if ((self.nr24 & 0x40) != 0 and self.audio2Length > 0): self.audio2Length-=1 @@ -468,7 +435,6 @@ self.audio2Volume-=1 self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07) - def mixAudio2(self, buffer, length): wavePattern = 0x18 if (self.nr21 & 0xC0) == 0x00: @@ -491,48 +457,38 @@ if ((self.nr51 & 0x02) != 0): buffer[index + 1] += self.audio2Volume - # Audio Channel 3 def getAudio3Enable(self): return self.nr30 - def getAudio3Length(self): return self.nr31 - def getAudio3Level(self): return self.nr32 - def getAudio4Frequency(self): return self.nr33 - def getAudio3Playback(self): return self.nr34 - def setAudio3Enable(self, data): self.nr30 = data & 0x80 if ((self.nr30 & 0x80) == 0): self.nr52 &= ~0x04 - def setAudio3Length(self, data): self.nr31 = data self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31) - def setAudio3Level(self, data): self.nr32 = data - def setAudio3Frequency(self, data): self.nr33 = data self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1 - def setAudio3Playback(self, data): self.nr34 = data self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1 @@ -541,24 +497,18 @@ if ((self.nr34 & 0x40) != 0 and self.audio3Length == 0): self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31) - - def setAudio3WavePattern(self, address, data): - #TODO convert to byte self.audio3WavePattern[address & 0x0F] = data - def getAudio3WavePattern(self, address): return self.audio3WavePattern[address & 0x0F] & 0xFF - def updateAudio3(self): if ((self.nr34 & 0x40) != 0 and self.audio3Length > 0): self.audio3Length-=1 if (self.audio3Length <= 0): self.nr52 &= ~0x04 - def mixAudio3(self, buffer, length): wavePattern = 2 if (self.nr32 & 0x60) == 0x00: @@ -583,29 +533,23 @@ if ((self.nr51 & 0x04) != 0): buffer[index + 1] += sample - # Audio Channel 4 def getAudio4Length(self): return self.nr41 - def getAudio4Envelope(self): return self.nr42 - def getAudio4Polynomial(self): return self.nr43 - def getAudio4Playback(self): return self.nr44 - def setAudio4Length(self, data): self.nr41 = data self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F)) - def setAudio4Envelope(self, data): self.nr42 = data if ((self.nr44 & 0x40) == 0): @@ -616,7 +560,6 @@ else: self.audio4Volume = (self.audio4Volume + 2) & 0x0F - def setAudio4Polynomial(self, data): self.nr43 = data if ((self.nr43 >> 4) <= 12): @@ -624,7 +567,6 @@ else: self.audio4Frequency = 0 - def setAudio4Playback(self, data): self.nr44 = data if ((self.nr44 & 0x80) != 0): @@ -634,8 +576,6 @@ self.audio4Volume = self.nr42 >> 4 self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07) self.audio4Index = 0 - - def updateAudio4(self): if ((self.nr44 & 0x40) != 0 and self.audio4Length > 0): @@ -651,7 +591,6 @@ elif (self.audio4Volume > 0): self.audio4Volume-=1 self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07) - def mixAudio4(self, buffer, length): for index in range(0, length, 2): @@ -676,28 +615,22 @@ if ((self.nr51 & 0x08) != 0): buffer[index + 1] += self.audio4Volume - # Output Control def getOutputLevel(self): return self.nr50 - def getOutputTerminal(self): return self.nr51 - def getOutputEnable(self): return self.nr52 - def setOutputLevel(self, data): self.nr50 = data - def setOutputTerminal(self, data): self.nr51 = data - def setOutputEnable(self, data): self.nr52 = (self.nr52 & 0x7F) | (data & 0x80) if ((self.nr52 & 0x80) == 0x00): @@ -741,7 +674,6 @@ self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31) - # SOUND DRIVER ----------------------------------------------------------------- class SoundDriver(object): @@ -749,7 +681,6 @@ def __init__(self): self.enabled = True - def isEnabled(self): return self.enabled Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py Sun Apr 6 00:48:06 2008 @@ -7,15 +7,15 @@ -def test_rest(): +def test_reset(): interrupt = get_interrupt() assert interrupt.enable == 0 - assert interrupt.flag == constants.VBLANK + assert interrupt.getInterruptFlag() == 0xE0 | constants.VBLANK interrupt.enable = 1 interrupt.flag = ~constants.VBLANK interrupt.reset() assert interrupt.enable == 0 - assert interrupt.flag == constants.VBLANK + assert interrupt.getInterruptFlag() == 0xE0 | constants.VBLANK def test_is_pending(): @@ -23,34 +23,41 @@ assert interrupt.isPending() == False assert interrupt.isPending(0x00) == False interrupt.setInterruptEnable(True) - assert interrupt.isPending() == True + assert interrupt.isPending() -def test_raise_interrupt(): +def test_is_pending_common_masks(): interrupt = get_interrupt() - value = 0x12 - mask = 0xAA - interrupt.flag = value - assert interrupt.flag == value - interrupt.raiseInterrupt(mask) - assert interrupt.flag == value|mask + for flag in interrupt.interruptFlags: + interrupt.reset() + interrupt.enable = True + assert interrupt.vBlank.isPending() + flag.setPending(True) + assert interrupt.isPending(flag.mask) + -def test_lower(): +def test_raise_lower_interrupt(): interrupt = get_interrupt() - value = 0x12 - mask = 0xAA - interrupt.flag = value - assert interrupt.flag == value - interrupt.lower(mask) - assert interrupt.flag == value & (~mask) + masks= [constants.LCD, constants.TIMER, + constants.JOYPAD, constants.SERIAL] + interrupt.setInterruptEnable(True) + interrupt.vBlank.setPending(True) + for mask in masks: + interrupt.raiseInterrupt(mask) + assert interrupt.maskMapping[mask].isPending() == True + assert interrupt.isPending(mask) == True + interrupt.lower(mask) + assert interrupt.isPending(mask) == False def test_read_write(): interrupt = get_interrupt() - value = 0x12 + value = 1 interrupt.write(constants.IE, value) assert interrupt.enable == value assert interrupt.read(constants.IE) == value - value+=1 + + interrupt.reset() + value = constants.LCD interrupt.write(constants.IF, value) - assert interrupt.flag == value + assert interrupt.getInterruptFlag() == 0xE0 | value assert interrupt.read(constants.IF) == 0xE0 | value Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py Sun Apr 6 00:48:06 2008 @@ -5,11 +5,7 @@ def get_timer(): - return Timer(get_timer_interrupt()) - -def get_timer_interrupt(): - return Interrupt() - + return Timer(Interrupt()) # ------------------------------------------------------------------------------ @@ -47,26 +43,93 @@ timer.reset() - - -def test_setTimerControl(): +def test_getTimerControl(): timer = get_timer() value = 0x12 timer.write(constants.TAC, value) assert timer.getTimerControl() == 0xF8 | value assert timer.read(constants.TAC) == 0xF8 |value + +def test_setTimerControl(): + timer = get_timer() + value = 0x12 + timer.setTimerControl(value) + assert timer.tac == value + assert timer.timerCycles == constants.TIMER_CLOCK[value & 0x03] + assert timer.timerClock == constants.TIMER_CLOCK[value & 0x03] + timer.reset() + timer.tac = value+1 + timer.timerClock = 0 + timer.timerCycles = 0 + timer.setTimerControl(value+1) + assert timer.tac == value+1 + assert timer.timerClock == 0 + assert timer.timerClock == 0 +def test_read_write_Divider(): + timer = get_timer() + value = 0x12 + timer.div = value + assert timer.getDivider() == timer.div + # divider resets on write + timer.setDivider(value) + assert timer.getDivider() == 0 def test_cycles(): - py.test.skip("not yet implemented") timer = get_timer() + value = 10 + timer.dividerCycles = value + assert timer.cycles() == timer.dividerCycles + timer.tac = 0x04 + timer.timerCycles = value-1 + timer.timerCycles = value + assert timer.cycles() == timer.timerCycles - -def test_emulateDivider(): - py.test.skip("not yet implemented") +def test_emulateDivider_normal(): timer = get_timer() + value = 2 + timer.timerCycles = 0 + timer.emulateTimer(value) - -def test_emulateTimer(): - py.test.skip("not yet implemented") - timer = get_timer() \ No newline at end of file +def test_test_emulateDivider_zero(): + timer = get_timer() + value = 2 + timer.timerCycles = value + timer.emulateTimer(value) + assert timer.timerCycles == value + +def test_emulateTimer_tac_return(): + timer = get_timer() + timer.tac = 0 + timer.timerCycles = -10 + cycles = timer.timerCycles + timer.emulateTimer(10) + assert timer.timerCycles == cycles + +def test_emulateTimer_timer_cycles_return(): + timer = get_timer() + timer.tac = 0x04 + value = 10 + timer.timerCycles = value+1 + cycles = timer.timerCycles + timer.emulateTimer(value) + assert timer.timerCycles == 1 + + timer = get_timer() + timer.tac = 0x04 + + +def test_emulateTimer_interrupt(): + timer = get_timer() + ticks = 0 + timer.tac = 0x04 + timer.tima = -1 + # raise an interupt as we pass 0 + assert timer.interrupt.isPending(constants.TIMER) == False + timer.timerCycles = -timer.timerClock+1 + timer.emulateTimer(ticks) + assert timer.timerCycles == 1 + assert timer.tima == timer.tma + assert timer.interrupt.timer.isPending() + + \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sun Apr 6 00:48:06 2008 @@ -4,6 +4,7 @@ Timer and Divider """ from pypy.lang.gameboy import constants +from math import ceil class Timer(object): @@ -15,7 +16,7 @@ self.div = 0 self.dividerCycles = constants.DIV_CLOCK self.tima = self.tma = self.tac = 0x00 - self.timerCycles = self.timerClock = constants.TIMER_CLOCK[self.tac & 0x03] + self.timerCycles = self.timerClock = constants.TIMER_CLOCK[0] def write(self, address, data): if address==constants.DIV: @@ -61,7 +62,7 @@ def setTimerControl(self, data): if ((self.tac & 0x03) != (data & 0x03)): - self.timerCycles = self.timerClock = constants.TIMER_CLOCK[data & 0x03] + self.timerClock = self.timerCycles = constants.TIMER_CLOCK[data & 0x03] self.tac = data def cycles(self): @@ -75,20 +76,30 @@ def emulateDivider(self, ticks): self.dividerCycles -= ticks - while (self.dividerCycles <= 0): - self.div = (self.div + 1) & 0xFF - self.dividerCycles += constants.DIV_CLOCK - + if self.dividerCycles > 0: + return + count = int(ceil(-1.0*self.dividerCycles / constants.DIV_CLOCK)) + self.div = (self.div + count) & 0xFF + self.dividerCycles += constants.DIV_CLOCK*count + def emulateTimer(self, ticks): - if ((self.tac & 0x04) != 0): - self.timerCycles -= ticks - while (self.timerCycles <= 0): - self.tima = (self.tima + 1) & 0xFF - self.timerCycles += self.timerClock - if (self.tima == 0x00): - self.tima = self.tma - self.interrupt.raiseInterrupt(constants.TIMER) - + if (self.tac & 0x04) == 0: + return + self.timerCycles -= ticks + if self.timerCycles > 0: + return + count = int(ceil(-1.0*self.timerCycles / self.timerClock)) + self.timaZeroPassCheck(count) + self.tima = (self.tima + count) & 0xFF + self.timerCycles += self.timerClock * count + + def timaZeroPassCheck(self, count): + if (self.tima < 0) and (self.tima + count >= 0): + self.tima = self.tma - count + print "raising" + self.interrupt.raiseInterrupt(constants.TIMER) + print self.interrupt.timer.isPending(), self.interrupt.isPending(constants.TIMER) + # CLOCK DRIVER ----------------------------------------------------------------- class ClockDriver(object): From fijal at codespeak.net Sun Apr 6 03:20:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 03:20:22 +0200 (CEST) Subject: [pypy-svn] r53414 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080406012022.ADFE316A7CD@codespeak.net> Author: fijal Date: Sun Apr 6 03:20:20 2008 New Revision: 53414 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: A test for float frame_place_write Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sun Apr 6 03:20:20 2008 @@ -1,4 +1,5 @@ import random, sys, py +from pypy.rlib.objectmodel import specialize from pypy.rpython.annlowlevel import MixLevelAnnotatorPolicy, llhelper from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rlib.objectmodel import keepalive_until_here @@ -729,39 +730,58 @@ return res return read_frame_var_runner -class FramePlaceWriter: - FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address, lltype.Signed], - lltype.Void)) - def __init__(self, RGenOp): - def writer(base, value): - if value > 5: - RGenOp.write_frame_place(lltype.Signed, base, - self.place1, value * 7) - RGenOp.write_frame_place(lltype.Signed, base, - self.place2, value * 10) - self.writer = writer - def get_writer(self, place1, place2): - self.place1 = place1 - self.place2 = place2 - return llhelper(self.FUNC, self.writer) - -def make_write_frame_place(rgenop, get_writer): - signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) - writertoken = rgenop.sigToken(FramePlaceWriter.FUNC.TO) +def get_frame_place_writer(TP): + class FramePlaceWriter: + FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address, TP], + lltype.Void)) + def __init__(self, RGenOp): + def writer(base, value): + if value > 5: + RGenOp.write_frame_place(TP, base, + self.place1, value * 7) + RGenOp.write_frame_place(TP, base, + self.place2, value * 10) + self.writer = writer + def get_writer(self, place1, place2): + self.place1 = place1 + self.place2 = place2 + return llhelper(self.FUNC, self.writer) + return FramePlaceWriter + +FramePlaceWriter = get_frame_place_writer(lltype.Signed) +FramePlaceWriterFloat = get_frame_place_writer(lltype.Float) + + at specialize.arg(2, 3) +def make_write_frame_place(rgenop, get_writer, TP, frame_writer): + kind = rgenop.kindToken(TP) + if TP is lltype.Signed: + F = FUNC + else: + F = FLOATFUNC + sigtoken = rgenop.sigToken(F) + writertoken = rgenop.sigToken(frame_writer.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") builder.start_writing() gv_base = builder.genop_get_frame_base() - gv_k = rgenop.genconst(-100) - place1 = builder.alloc_frame_place(signed_kind, gv_initial_value=gv_k) - place2 = builder.alloc_frame_place(signed_kind) + if TP is lltype.Signed: + gv_k = rgenop.genconst(-100) + elif TP is lltype.Float: + gv_k = rgenop.genconst(-33.3) + else: + raise NotImplementedError + place1 = builder.alloc_frame_place(kind, gv_initial_value=gv_k) + place2 = builder.alloc_frame_place(kind) gv_writer = rgenop.constPrebuiltGlobal(get_writer(place1, place2)) builder.genop_call(writertoken, gv_writer, [gv_base, gv_x]) gv_y = builder.genop_absorb_place(place1) gv_z = builder.genop_absorb_place(place2) - gv_diff = builder.genop2("int_sub", gv_y, gv_z) + if TP is lltype.Float: + op = "float_sub" + else: + op = "int_sub" + gv_diff = builder.genop2(op, gv_y, gv_z) builder.finish_and_return(sigtoken, gv_diff) builder.end() @@ -772,7 +792,8 @@ def write_frame_place_runner(x): rgenop = RGenOp() - gv_f = make_write_frame_place(rgenop, fvw.get_writer) + gv_f = make_write_frame_place(rgenop, fvw.get_writer, lltype.Signed, + FramePlaceWriter) fn = gv_f.revealconst(lltype.Ptr(FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive @@ -1574,13 +1595,31 @@ return writer_ptr rgenop = self.RGenOp() - gv_callable = make_write_frame_place(rgenop, get_writer) + gv_callable = make_write_frame_place(rgenop, get_writer, + lltype.Signed, FramePlaceWriter) fnptr = self.cast(gv_callable, 1) res = fnptr(3) assert res == -100 - 30 res = fnptr(6) assert res == 42 - 60 + def test_write_frame_place_float_direct(self): + def get_writer(place1, place2): + fvw = FramePlaceWriterFloat(self.RGenOp) + fvw.place1 = place1 + fvw.place2 = place2 + writer_ptr = self.directtesthelper(fvw.FUNC, fvw.writer) + return writer_ptr + + rgenop = self.RGenOp() + gv_callable = make_write_frame_place(rgenop, get_writer, lltype.Float, + FramePlaceWriterFloat) + fnptr = self.cast_float(gv_callable, 1) + res = fnptr(3.3) + assert res == -33.3 - 33. + res = fnptr(6.3) + assert res == -18.9 + def test_write_lots_of_frame_places_direct(self): def get_writer(places): fvw = ManyFramePlaceWriter(self.RGenOp) From fijal at codespeak.net Sun Apr 6 03:28:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 03:28:05 +0200 (CEST) Subject: [pypy-svn] r53415 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080406012805.BF95016A7CD@codespeak.net> Author: fijal Date: Sun Apr 6 03:28:05 2008 New Revision: 53415 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: * make kindToken return some info * hack pieces a bit in order to pass test (the test finally doesn't pass, few more functions to patch) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sun Apr 6 03:28:05 2008 @@ -545,11 +545,13 @@ res = FloatVar(self.stackdepth + 1) if op is st0: self.pushfloatfromst0(res) + elif op is None: + self.push(imm(0)) + self.push(imm(0)) else: raise NotImplementedError("Return float var not on fp stack") return res - def newvarfromaddr(self, kindtoken, addr): # XXX probably we can still do something here with unrolling # iterable, but let's not be too smart... @@ -564,6 +566,18 @@ else: raise NotImplementedError("Return var of kind %s" % (kindtoken,)) + def newvar(self, kindtoken): + if kindtoken == 'i': + return self.returnintvar(None) + elif kindtoken == 'a': + return self.returnaddrvar(None) + elif kindtoken == 'b': + return self.returnboolvar(None) + elif kindtoken == 'f': + return self.returnfloatvar(None) + else: + raise NotImplementedError("Return var of kind %s" % (kindtoken,)) + def newfloatfrommem(self, (base, reg, shift, ofs)): res = FloatVar(self.stackdepth + 1) self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) @@ -913,12 +927,9 @@ return self.returnfloatvar(st0) def alloc_frame_place(self, kind, gv_initial_value=None): - # XXX kind if gv_initial_value is not None: - res = self.returnintvar(gv_initial_value.operand(self)) - else: - res = self.returnintvar(None) - return res + return gv_initial_value.newvar(self) + return self.newvar(kind) def genop_absorb_place(self, v): return v @@ -1272,7 +1283,7 @@ @staticmethod @specialize.memo() def kindToken(T): - return None + return map_arg(T) @staticmethod @specialize.memo() From arigo at codespeak.net Sun Apr 6 10:29:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 10:29:36 +0200 (CEST) Subject: [pypy-svn] r53417 - pypy/dist/pypy/tool Message-ID: <20080406082936.2F2A216A41D@codespeak.net> Author: arigo Date: Sun Apr 6 10:29:35 2008 New Revision: 53417 Modified: pypy/dist/pypy/tool/udir.py Log: Merge udir.py from the jit-hotpath branch: setting PYPY_USESSION_BASENAME to the string "-" gives the old behavior back (i.e. not separate names for each branch). Modified: pypy/dist/pypy/tool/udir.py ============================================================================== --- pypy/dist/pypy/tool/udir.py (original) +++ pypy/dist/pypy/tool/udir.py Sun Apr 6 10:29:35 2008 @@ -17,9 +17,11 @@ else: return basename.split('/')[-2] -try: - basename = '-' + svn_info(py.path.svnwc(py.magic.autopath().dirpath()).info().url) + '-' -except: - basename = '-' +basename = os.environ.get('PYPY_USESSION_BASENAME') +if not basename: + try: + basename = '-' + svn_info(py.path.svnwc(py.magic.autopath().dirpath()).info().url) + '-' + except: + basename = '-' udir = local.make_numbered_dir(prefix='usession' + basename, keep=3) From arigo at codespeak.net Sun Apr 6 16:18:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 16:18:10 +0200 (CEST) Subject: [pypy-svn] r53451 - in pypy/dist/pypy: config lib translator/goal Message-ID: <20080406141810.1020F16A665@codespeak.net> Author: arigo Date: Sun Apr 6 16:18:09 2008 New Revision: 53451 Added: pypy/dist/pypy/lib/_minimal_curses.py - copied unchanged from r53449, user/arigo/hack/pypy-hack/_minimal_curses.py pypy/dist/pypy/lib/readline.py - copied unchanged from r53449, user/arigo/hack/pypy-hack/readline.py Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/translator/goal/app_main.py Log: * A new readline.py quite more complete than module/readline, based on pyrepl. * A new _minimal_curses.py based on ctypes, with just enough to make pyrepl happy. * Change the default modules of --allworkingmodules so that readline is no longer included, but _rawffi is (on non-Windows platforms). Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun Apr 6 16:18:09 2008 @@ -23,7 +23,7 @@ working_modules = default_modules.copy() working_modules.update(dict.fromkeys( ["_socket", "unicodedata", "mmap", "fcntl", "rctime", "select", - "crypt", "signal", "dyngram", "readline", "termios", "zlib", + "crypt", "signal", "dyngram", "_rawffi", "termios", "zlib", "struct", "md5", "sha", "bz2", ] )) @@ -33,6 +33,7 @@ del working_modules["readline"] del working_modules["crypt"] del working_modules["termios"] + del working_modules["_rawffi"] module_dependencies = {} 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 Apr 6 16:18:09 2008 @@ -337,18 +337,7 @@ success = run_toplevel(execfile, sys.argv[0], mainmodule.__dict__) if is_interactive(): - try: - import _curses - import termios - from pyrepl.python_reader import main - from pyrepl import cmdrepl - #import pdb - #pdb.Pdb = cmdrepl.replize(pdb.Pdb, 1) - except ImportError: - success = run_toplevel(interactive_console, mainmodule) - else: - main(print_banner=False, clear_main=False) - success = True + success = run_toplevel(interactive_console, mainmodule) except SystemExit, e: return e.code else: From arigo at codespeak.net Sun Apr 6 16:36:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 16:36:49 +0200 (CEST) Subject: [pypy-svn] r53456 - pypy/dist/pypy/lib Message-ID: <20080406143649.A878116A6B5@codespeak.net> Author: arigo Date: Sun Apr 6 16:36:49 2008 New Revision: 53456 Modified: pypy/dist/pypy/lib/readline.py Log: Bug fix. Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Sun Apr 6 16:36:49 2008 @@ -70,8 +70,7 @@ if self.startup_hook is not None: self.startup_hook() reader.ps1 = prompt - result = reader.readline() - return result + '\n' + return reader.readline() def parse_and_bind(self, string): pass # XXX we don't support parsing GNU-readline-style init files From arigo at codespeak.net Sun Apr 6 17:41:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 17:41:53 +0200 (CEST) Subject: [pypy-svn] r53464 - in pypy/dist/pypy: lib translator/goal Message-ID: <20080406154153.1353216A66D@codespeak.net> Author: arigo Date: Sun Apr 6 17:41:52 2008 New Revision: 53464 Added: pypy/dist/pypy/lib/_pypy_interact.py (contents, props changed) Modified: pypy/dist/pypy/lib/readline.py pypy/dist/pypy/translator/goal/app_main.py Log: * Move interactive_console() to its own module for easier experimentation. * Extend the pyrepl-based readline with a multiline_input() function. * Use it for multiline inputs in the default pypy-c prompt. Yay :-) Added: pypy/dist/pypy/lib/_pypy_interact.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/_pypy_interact.py Sun Apr 6 17:41:52 2008 @@ -0,0 +1,74 @@ +"""Imported by app_main.py when PyPy needs to fire up the interactive console. +""" +import sys + + +def interactive_console(mainmodule=None): + import code + if mainmodule is None: + import __main__ as mainmodule + console = code.InteractiveConsole(mainmodule.__dict__) + try: + from readline import multiline_input + except ImportError: + run_simple_interactive_console(console) + else: + run_multiline_interactive_console(console) + +def run_simple_interactive_console(console): + # some parts of code.py are copied here because it seems to be impossible + # to start an interactive console without printing at least one line + # of banner + more = 0 + while 1: + try: + if more: + prompt = getattr(sys, 'ps2', '... ') + else: + prompt = getattr(sys, 'ps1', '>>> ') + try: + line = raw_input(prompt) + except EOFError: + console.write("\n") + break + else: + more = console.push(line) + except KeyboardInterrupt: + console.write("\nKeyboardInterrupt\n") + console.resetbuffer() + more = 0 + +def run_multiline_interactive_console(console): + from readline import multiline_input + + def more_lines(unicodetext): + # ooh, look at the hack: + src = "#coding:utf-8\n"+unicodetext.encode('utf-8') + try: + code = console.compile(src, '', 'single') + except (OverflowError, SyntaxError, ValueError): + return False + else: + return code is None + + while 1: + try: + ps1 = getattr(sys, 'ps1', '>>> ') + ps2 = getattr(sys, 'ps2', '... ') + try: + statement = multiline_input(more_lines, ps1, ps2) + except EOFError: + break + more = console.push(statement) + assert not more + except KeyboardInterrupt: + console.write("\nKeyboardInterrupt\n") + console.resetbuffer() + +# ____________________________________________________________ + +if __name__ == '__main__': # for testing + import os + if os.getenv('PYTHONSTARTUP'): + execfile(os.getenv('PYTHONSTARTUP')) + interactive_console() Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Sun Apr 6 17:41:52 2008 @@ -45,6 +45,38 @@ cut = 0 return self.history[cut:] + # --- simplified support for reading multiline Python statements --- + + # This duplicates small parts of pyrepl.python_reader. I'm not + # reusing the PythonicReader class directly for two reasons. One is + # to try to keep as close as possible to CPython's prompt. The + # other is that it is the readline module that we are ultimately + # implementing here, and I don't want the built-in raw_input() to + # start trying to read multiline inputs just because what the user + # typed look like valid but incomplete Python code. So we get the + # multiline feature only when using the multiline_input() function + # directly (see _pypy_interact.py). + + more_lines = None + + def collect_keymap(self): + return super(_ReaderMixin, self).collect_keymap() + ( + (r'\n', 'maybe-accept'),) + + def __init__(self, console): + super(_ReaderMixin, self).__init__(console) + from pyrepl import commands + class maybe_accept(commands.Command): + def do(self): + r = self.reader + text = r.get_unicode() + if r.more_lines is not None and r.more_lines(text): + r.insert("\n") + else: + self.finish = 1 + self.commands['maybe_accept'] = maybe_accept + self.commands['maybe-accept'] = maybe_accept + # ____________________________________________________________ class _ReadlineWrapper(object): @@ -72,6 +104,27 @@ reader.ps1 = prompt return reader.readline() + def multiline_input(self, more_lines, ps1, ps2): + """Read an input on possibly multiple lines, asking for more + lines as long as 'more_lines(unicodetext)' returns an object whose + boolean value is true. + """ + reader = self.get_reader() + saved = reader.more_lines + try: + reader.more_lines = more_lines + reader.ps1 = reader.ps2 = ps1 + reader.ps3 = reader.ps4 = ps2 + return reader.readline() + finally: + reader.more_lines = saved + + def compiler(self, textstring): + if self.pyconsole is None: + return True + else: + return self.pyconsole.compile(textstring, '', 'single') + def parse_and_bind(self, string): pass # XXX we don't support parsing GNU-readline-style init files @@ -172,6 +225,9 @@ add_history = _wrapper.add_history set_startup_hook = _wrapper.set_startup_hook +# Extension +multiline_input = _wrapper.multiline_input + # ____________________________________________________________ # Stubs @@ -225,11 +281,3 @@ __builtin__.raw_input = _wrapper.raw_input _setup() - -if __name__ == '__main__': # for testing - import __main__ - sys.modules['readline'] = __main__ - if os.getenv('PYTHONSTARTUP'): - execfile(os.getenv('PYTHONSTARTUP')) - import code - code.interact() 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 Apr 6 17:41:52 2008 @@ -337,6 +337,7 @@ success = run_toplevel(execfile, sys.argv[0], mainmodule.__dict__) if is_interactive(): + from _pypy_interact import interactive_console success = run_toplevel(interactive_console, mainmodule) except SystemExit, e: return e.code @@ -363,35 +364,6 @@ print ('Type "help", "copyright", "credits" or ' '"license" for more information.') -def interactive_console(mainmodule): - # some parts of code.py are copied here because it seems to be impossible - # to start an interactive console without printing at least one line - # of banner - import code - console = code.InteractiveConsole(mainmodule.__dict__) - try: - import readline - except ImportError: - pass - more = 0 - while 1: - try: - if more: - prompt = sys.ps2 - else: - prompt = sys.ps1 - try: - line = raw_input(prompt) - except EOFError: - console.write("\n") - break - else: - more = console.push(line) - except KeyboardInterrupt: - console.write("\nKeyboardInterrupt\n") - console.resetbuffer() - more = 0 - if __name__ == '__main__': import autopath From arigo at codespeak.net Sun Apr 6 17:42:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 17:42:35 +0200 (CEST) Subject: [pypy-svn] r53465 - pypy/dist/pypy/lib Message-ID: <20080406154235.CF3C116A66D@codespeak.net> Author: arigo Date: Sun Apr 6 17:42:35 2008 New Revision: 53465 Modified: pypy/dist/pypy/lib/readline.py Log: Forgot to save before checking in. Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Sun Apr 6 17:42:35 2008 @@ -119,12 +119,6 @@ finally: reader.more_lines = saved - def compiler(self, textstring): - if self.pyconsole is None: - return True - else: - return self.pyconsole.compile(textstring, '', 'single') - def parse_and_bind(self, string): pass # XXX we don't support parsing GNU-readline-style init files From arigo at codespeak.net Sun Apr 6 17:48:42 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 17:48:42 +0200 (CEST) Subject: [pypy-svn] r53466 - pypy/dist/pypy/lib Message-ID: <20080406154842.F097116A6D9@codespeak.net> Author: arigo Date: Sun Apr 6 17:48:42 2008 New Revision: 53466 Modified: pypy/dist/pypy/lib/readline.py Log: Tweaking. Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Sun Apr 6 17:48:42 2008 @@ -69,8 +69,12 @@ class maybe_accept(commands.Command): def do(self): r = self.reader + # if there are already several lines and the cursor + # is not on the last one, always insert a new \n. text = r.get_unicode() - if r.more_lines is not None and r.more_lines(text): + if "\n" in r.buffer[r.pos:]: + r.insert("\n") + elif r.more_lines is not None and r.more_lines(text): r.insert("\n") else: self.finish = 1 From arigo at codespeak.net Sun Apr 6 18:05:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 18:05:47 +0200 (CEST) Subject: [pypy-svn] r53469 - pypy/dist/pypy/lib Message-ID: <20080406160547.8FC0816A6FC@codespeak.net> Author: arigo Date: Sun Apr 6 18:05:45 2008 New Revision: 53469 Modified: pypy/dist/pypy/lib/readline.py Log: A hack to preserve the boundaries in multiline inputs in the history file on disk. Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Sun Apr 6 18:05:45 2008 @@ -153,10 +153,23 @@ return len(self.get_reader().history) def read_history_file(self, filename='~/.history'): + # multiline extension (really a hack) for the end of lines that + # are actually continuations inside a single multiline_input() + # history item: we use \r\n instead of just \n. If the history + # file is passed to GNU readline, the extra \r are just ignored. history = self.get_reader().history f = open(os.path.expanduser(filename), 'r') + buffer = [] for line in f: - history.append(self._histline(line)) + if line.endswith('\r\n'): + buffer.append(line) + else: + line = self._histline(line) + if buffer: + line = ''.join(buffer).replace('\r', '') + line + del buffer[:] + if line: + history.append(line) f.close() def write_history_file(self, filename='~/.history'): @@ -166,6 +179,7 @@ for entry in history: if isinstance(entry, unicode): entry = entry.encode(ENCODING) + entry = entry.replace('\n', '\r\n') # multiline history support f.write(entry + '\n') f.close() From arigo at codespeak.net Sun Apr 6 18:13:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 18:13:18 +0200 (CEST) Subject: [pypy-svn] r53471 - pypy/dist/pypy/lib Message-ID: <20080406161318.B2D2016A53D@codespeak.net> Author: arigo Date: Sun Apr 6 18:13:18 2008 New Revision: 53471 Modified: pypy/dist/pypy/lib/_pypy_interact.py Log: Add an XXX. Modified: pypy/dist/pypy/lib/_pypy_interact.py ============================================================================== --- pypy/dist/pypy/lib/_pypy_interact.py (original) +++ pypy/dist/pypy/lib/_pypy_interact.py Sun Apr 6 18:13:18 2008 @@ -59,6 +59,10 @@ statement = multiline_input(more_lines, ps1, ps2) except EOFError: break + # XXX with Alt-Enter we can actually enter more than one + # statement, and compile() ignores everything after the + # first statement in 'single' mode... We should either + # find some obscure workaround or tweak PyPy's compiler. more = console.push(statement) assert not more except KeyboardInterrupt: From arigo at codespeak.net Sun Apr 6 18:30:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 18:30:17 +0200 (CEST) Subject: [pypy-svn] r53472 - pypy/dist/pypy/module/posix Message-ID: <20080406163017.EDB7616A637@codespeak.net> Author: arigo Date: Sun Apr 6 18:30:15 2008 New Revision: 53472 Modified: pypy/dist/pypy/module/posix/app_posix.py Log: Add an XXX. Modified: pypy/dist/pypy/module/posix/app_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/app_posix.py (original) +++ pypy/dist/pypy/module/posix/app_posix.py Sun Apr 6 18:30:15 2008 @@ -113,7 +113,7 @@ else: os.dup2(read_end, 0) os.close(write_end) - for i in range(3, MAXFD): + for i in range(3, MAXFD): # XXX this loop can be slow try_close(i) cmd = ['/bin/sh', '-c', command] os.execvp(cmd[0], cmd) From arigo at codespeak.net Sun Apr 6 19:44:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 19:44:27 +0200 (CEST) Subject: [pypy-svn] r53473 - pypy/dist/pypy/module/posix/test Message-ID: <20080406174427.C512E16A6B8@codespeak.net> Author: arigo Date: Sun Apr 6 19:44:26 2008 New Revision: 53473 Modified: pypy/dist/pypy/module/posix/test/test_posix2.py Log: A popen test. Passes, but shows an issue: it prints a number of "ignored OSError in method __del__". They are caused by file.__del__ being invoked exactly between the fork-and-close-all-fds and the execvp. pypy-c has exactly the same issue. At the moment it prints the annoying warnings half of the time just when starting up (because it uses ctypes.util which calls os.popen()). 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 Apr 6 19:44:26 2008 @@ -234,10 +234,10 @@ 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' + for i in range(5): + stream = os.popen('echo 1') + assert stream.read() == '1\n' if hasattr(__import__(os.name), '_getfullpathname'): def test__getfullpathname(self): From arigo at codespeak.net Sun Apr 6 19:46:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 19:46:35 +0200 (CEST) Subject: [pypy-svn] r53474 - in pypy/dist/pypy: config module/_curses module/_minimal_curses Message-ID: <20080406174635.0073E16A6BB@codespeak.net> Author: arigo Date: Sun Apr 6 19:46:35 2008 New Revision: 53474 Added: pypy/dist/pypy/module/_minimal_curses/ - copied from r53461, pypy/dist/pypy/module/_curses/ Removed: pypy/dist/pypy/module/_curses/ Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/module/_minimal_curses/__init__.py Log: Rename _curses to _minimal_curses. Enable it by default with --allworkingmodules. This should let readline.py import without bringing in all of ctypes. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun Apr 6 19:46:35 2008 @@ -24,7 +24,7 @@ working_modules.update(dict.fromkeys( ["_socket", "unicodedata", "mmap", "fcntl", "rctime", "select", "crypt", "signal", "dyngram", "_rawffi", "termios", "zlib", - "struct", "md5", "sha", "bz2", + "struct", "md5", "sha", "bz2", "_minimal_curses", ] )) Modified: pypy/dist/pypy/module/_minimal_curses/__init__.py ============================================================================== --- pypy/dist/pypy/module/_curses/__init__.py (original) +++ pypy/dist/pypy/module/_minimal_curses/__init__.py Sun Apr 6 19:46:35 2008 @@ -9,7 +9,7 @@ """ Low-level interface for curses module, not meant to be used directly """ - applevel_name = "_curses" + applevel_name = "_minimal_curses" appleveldefs = { 'error' : 'app_curses.error', From arigo at codespeak.net Sun Apr 6 19:47:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 19:47:05 +0200 (CEST) Subject: [pypy-svn] r53475 - pypy/dist/pypy/lib Message-ID: <20080406174705.D5DAC16A6B3@codespeak.net> Author: arigo Date: Sun Apr 6 19:47:05 2008 New Revision: 53475 Modified: pypy/dist/pypy/lib/_minimal_curses.py Log: Note. Modified: pypy/dist/pypy/lib/_minimal_curses.py ============================================================================== --- pypy/dist/pypy/lib/_minimal_curses.py (original) +++ pypy/dist/pypy/lib/_minimal_curses.py Sun Apr 6 19:47:05 2008 @@ -4,6 +4,9 @@ Based on ctypes. It's too incomplete to be really called '_curses', so to use it, you have to import it and stick it in sys.modules['_curses'] manually. + +Note that there is also a built-in module _minimal_curses which will +hide this one if compiled in. """ import ctypes, ctypes.util From arigo at codespeak.net Sun Apr 6 19:49:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Apr 2008 19:49:09 +0200 (CEST) Subject: [pypy-svn] r53476 - pypy/dist/pypy/module/_minimal_curses Message-ID: <20080406174909.E236916A6B3@codespeak.net> Author: arigo Date: Sun Apr 6 19:49:09 2008 New Revision: 53476 Modified: pypy/dist/pypy/module/_minimal_curses/__init__.py pypy/dist/pypy/module/_minimal_curses/fficurses.py Log: Fix imports. Modified: pypy/dist/pypy/module/_minimal_curses/__init__.py ============================================================================== --- pypy/dist/pypy/module/_minimal_curses/__init__.py (original) +++ pypy/dist/pypy/module/_minimal_curses/__init__.py Sun Apr 6 19:49:09 2008 @@ -1,7 +1,7 @@ from pypy.interpreter.mixedmodule import MixedModule -from pypy.module._curses import fficurses -from pypy.module._curses import interp_curses +from pypy.module._minimal_curses import fficurses +from pypy.module._minimal_curses import interp_curses from pypy.rlib.nonconst import NonConstant import _curses Modified: pypy/dist/pypy/module/_minimal_curses/fficurses.py ============================================================================== --- pypy/dist/pypy/module/_minimal_curses/fficurses.py (original) +++ pypy/dist/pypy/module/_minimal_curses/fficurses.py Sun Apr 6 19:49:09 2008 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.extfunc import register_external from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.module._curses import interp_curses +from pypy.module._minimal_curses import interp_curses from pypy.rpython.lltypesystem import llmemory from pypy.translator.tool.cbuild import ExternalCompilationInfo From fijal at codespeak.net Sun Apr 6 20:24:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 20:24:03 +0200 (CEST) Subject: [pypy-svn] r53477 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080406182403.B7F0E16A69E@codespeak.net> Author: fijal Date: Sun Apr 6 20:24:01 2008 New Revision: 53477 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: A test that might showcase lack of address.float[0] Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sun Apr 6 20:24:01 2008 @@ -1070,6 +1070,14 @@ res = fn(30) assert res == 60 + def test_read_frame_float_var_compile(self): + runner = get_read_frame_var_runner(self.RGenOp, False, + FrameVarFloatReader, FLOATFUNC) + + fn = self.compile(runner, [float]) + res = fn(3.3) + assert res == 3.3 * 2 + def test_genconst_from_frame_var_compile(self): runner = get_read_frame_var_runner(self.RGenOp, True, FrameVarReader, FUNC) From fijal at codespeak.net Sun Apr 6 20:25:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 20:25:20 +0200 (CEST) Subject: [pypy-svn] r53478 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080406182520.384B5168427@codespeak.net> Author: fijal Date: Sun Apr 6 20:25:20 2008 New Revision: 53478 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Log: raw buffer is always immortal Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Sun Apr 6 20:25:20 2008 @@ -201,8 +201,7 @@ # XXX we should take more care who is creating this and # eventually release this buffer # never moves and never dies - self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', - immortal=True) + self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') self.rawbuf[0] = floatval def newvar(self, builder): From fijal at codespeak.net Sun Apr 6 20:32:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 20:32:49 +0200 (CEST) Subject: [pypy-svn] r53479 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test Message-ID: <20080406183249.A9D3416A69E@codespeak.net> Author: fijal Date: Sun Apr 6 20:32:49 2008 New Revision: 53479 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: Skip this test with knowledge what's happening Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Sun Apr 6 20:32:49 2008 @@ -13,3 +13,6 @@ class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked + + def test_read_frame_float_var_compile(self): + py.test.skip("no support for addr.float[0]") From pypy-svn at codespeak.net Sun Apr 6 20:50:27 2008 From: pypy-svn at codespeak.net (pypy-svn at codespeak.net) Date: Sun, 6 Apr 2008 20:50:27 +0200 (CEST) Subject: SALE 73% OFF on VIAGRA® Message-ID: <20080406094909.165961.qmail@host214-112-dynamic.116-80-r.retail.telecomitalia.it> An HTML attachment was scrubbed... URL: From fijal at codespeak.net Sun Apr 6 20:51:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 20:51:17 +0200 (CEST) Subject: [pypy-svn] r53480 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080406185117.C4F2F16A6A8@codespeak.net> Author: fijal Date: Sun Apr 6 20:51:17 2008 New Revision: 53480 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Fix (a bit) test for write_frame_places. I still get some subtle float errors (but I don't think I can ignore them) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Sun Apr 6 20:51:17 2008 @@ -85,10 +85,8 @@ return builder.stack_access64(self.stackpos) def newvar(self, builder): - # XXX not tested and not sure if ever needed - raise NotImplementedError("write test first") ofs = (builder.stackdepth - self.stackpos - 1) * WORD - return builder.newfloatfrommem(esp, None, 0, ofs) + return builder.newfloatfrommem((esp, None, 0, ofs)) def movetonewaddr(self, builder, addr): dstop1 = builder.mem_access(addr) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sun Apr 6 20:51:17 2008 @@ -25,26 +25,28 @@ # address. When not, it's an integer. It just happens to # make the test pass, but that's probably going to change. if objectmodel.we_are_translated(): - if T is lltype.Signed: - return addr.signed[0] - elif T is lltype.Float: + if T is lltype.Float: return addr.float[0] else: - raise NotImplementedError("Not implemented types " + str(T)) + return addr.signed[0] else: tp = ctypes_mapping[T] p = cast(c_void_p(addr), POINTER(tp)) return p[0] -def poke_word_into(addr, value): + at specialize.arg(0) +def poke_value_into(T, addr, value): # now the Very Obscure Bit: when translated, 'addr' is an # address. When not, it's an integer. It just happens to # make the test pass, but that's probably going to change. if objectmodel.we_are_translated(): - addr.signed[0] = value + if T is lltype.Float: + addr.float[0] = value + else: + addr.signed[0] = value else: - from ctypes import cast, c_void_p, c_int, POINTER - p = cast(c_void_p(addr), POINTER(c_int)) + tp = ctypes_mapping[T] + p = cast(c_void_p(addr), POINTER(tp)) p[0] = value def map_arg(arg): @@ -402,19 +404,17 @@ return self.returnintvar(eax) def genop_call(self, sigtoken, gv_fnptr, args_gv): - # WUAAA, this does not support floats numargs = len(sigtoken[0]) MASK = CALL_ALIGN-1 if MASK: final_depth = self.stackdepth + numargs delta = ((final_depth+MASK)&~MASK)-final_depth if delta: - xxx 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)) + gv_arg.newvar(self) if DEBUG_CALL_ALIGN: self.mc.MOV(eax, esp) self.mc.AND(eax, imm8((WORD*CALL_ALIGN)-1)) @@ -425,7 +425,10 @@ self.mc.CALL(rel32(target)) else: self.mc.CALL(gv_fnptr.operand(self)) - # XXX only for int return_kind, check calling conventions + # XXX implement different calling conventions and different types + RESULT = sigtoken[1] + if RESULT == "f": + return self.returnfloatvar(st0) return self.returnintvar(eax) def genop_same_as(self, gv_x): @@ -1351,8 +1354,7 @@ @staticmethod @specialize.arg(0) def write_frame_place(T, base, place, value): - assert T is lltype.Signed - poke_word_into(base - place.stackpos * WORD, value) + poke_value_into(T, base - place.stackpos * WORD, value) @staticmethod @specialize.arg(0) From fijal at codespeak.net Sun Apr 6 21:40:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 21:40:23 +0200 (CEST) Subject: [pypy-svn] r53481 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080406194023.7179716A697@codespeak.net> Author: fijal Date: Sun Apr 6 21:40:20 2008 New Revision: 53481 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: A test pointing out that there is something wrong with genop_call for floats. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sun Apr 6 21:40:20 2008 @@ -736,6 +736,7 @@ lltype.Void)) def __init__(self, RGenOp): def writer(base, value): + print value if value > 5: RGenOp.write_frame_place(TP, base, self.place1, value * 7) @@ -800,6 +801,22 @@ return res return write_frame_place_runner +def make_float_caller(rgenop): + FUNC = lltype.FuncType([lltype.Signed, lltype.Float], lltype.Float) + sigtoken = rgenop.sigToken(FLOATFUNC) + innertoken = rgenop.sigToken(FUNC) + builder, gv_f, [gv_y, gv_x] = rgenop.newgraph(innertoken, "inner") + builder.start_writing() + builder.finish_and_return(innertoken, gv_x) + builder.end() + builder, gv_f2, [gv_x] = rgenop.newgraph(sigtoken, "outer") + builder.start_writing() + gv_res = builder.genop_call(innertoken, gv_f, [rgenop.genconst(3), gv_x]) + builder.finish_and_return(sigtoken, gv_res) + builder.end() + + return gv_f2 + class ManyFramePlaceWriter: FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address, lltype.Signed], lltype.Void)) @@ -1157,6 +1174,12 @@ res = fnptr(1.2) assert res == 4.4 + def test_float_call(self): + rgenop = self.RGenOp() + gv_f = make_float_caller(rgenop) + fnptr = self.cast_float(gv_f, 1) + assert fnptr(1.2) == 1.2 + def test_float_loop_direct(self): def f(x, y): i = 0 @@ -1624,9 +1647,9 @@ FramePlaceWriterFloat) fnptr = self.cast_float(gv_callable, 1) res = fnptr(3.3) - assert res == -33.3 - 33. + assert res == (-33.3 - 3.3*10) res = fnptr(6.3) - assert res == -18.9 + assert res == -18.9 def test_write_lots_of_frame_places_direct(self): def get_writer(places): From fijal at codespeak.net Sun Apr 6 21:42:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 21:42:07 +0200 (CEST) Subject: [pypy-svn] r53482 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080406194207.7E90416A699@codespeak.net> Author: fijal Date: Sun Apr 6 21:42:07 2008 New Revision: 53482 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: Simplify the test Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Sun Apr 6 21:42:07 2008 @@ -802,16 +802,14 @@ return write_frame_place_runner def make_float_caller(rgenop): - FUNC = lltype.FuncType([lltype.Signed, lltype.Float], lltype.Float) sigtoken = rgenop.sigToken(FLOATFUNC) - innertoken = rgenop.sigToken(FUNC) - builder, gv_f, [gv_y, gv_x] = rgenop.newgraph(innertoken, "inner") + builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "inner") builder.start_writing() - builder.finish_and_return(innertoken, gv_x) + builder.finish_and_return(sigtoken, gv_x) builder.end() builder, gv_f2, [gv_x] = rgenop.newgraph(sigtoken, "outer") builder.start_writing() - gv_res = builder.genop_call(innertoken, gv_f, [rgenop.genconst(3), gv_x]) + gv_res = builder.genop_call(sigtoken, gv_f, [gv_x]) builder.finish_and_return(sigtoken, gv_res) builder.end() From fijal at codespeak.net Sun Apr 6 21:51:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Apr 2008 21:51:09 +0200 (CEST) Subject: [pypy-svn] r53483 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080406195109.B16A816A65F@codespeak.net> Author: fijal Date: Sun Apr 6 21:51:09 2008 New Revision: 53483 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Fix. Still quite fragile, need to rethink it (don't use PUSH?) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Sun Apr 6 21:51:09 2008 @@ -413,8 +413,7 @@ self.mc.SUB(esp, imm(delta*WORD)) self.stackdepth += delta for i in range(numargs-1, -1, -1): - gv_arg = args_gv[i] - gv_arg.newvar(self) + args_gv[i].newvar(self) if DEBUG_CALL_ALIGN: self.mc.MOV(eax, esp) self.mc.AND(eax, imm8((WORD*CALL_ALIGN)-1)) @@ -584,7 +583,11 @@ def newfloatfrommem(self, (base, reg, shift, ofs)): res = FloatVar(self.stackdepth + 1) self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) - self.mc.PUSH(memSIB(base, reg, shift, ofs)) + # XXX pom pom pom, stupid hack + if base is esp: + self.mc.PUSH(memSIB(base, reg, shift, ofs + WORD)) + else: + self.mc.PUSH(memSIB(base, reg, shift, ofs)) self.stackdepth += 2 return res From cfbolz at codespeak.net Sun Apr 6 22:36:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Apr 2008 22:36:10 +0200 (CEST) Subject: [pypy-svn] r53484 - in pypy/dist/pypy: rpython/lltypesystem rpython/lltypesystem/test translator/c/test Message-ID: <20080406203610.6312416A68C@codespeak.net> Author: cfbolz Date: Sun Apr 6 22:36:08 2008 New Revision: 53484 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/dist/pypy/translator/c/test/test_lladdresses.py Log: support for address.float[x] Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sun Apr 6 22:36:08 2008 @@ -491,6 +491,9 @@ class _signed_fakeaccessor(_fakeaccessor): TYPE = lltype.Signed +class _float_fakeaccessor(_fakeaccessor): + TYPE = lltype.Float + class _char_fakeaccessor(_fakeaccessor): TYPE = lltype.Char @@ -520,9 +523,11 @@ "unsigned": lltype.Unsigned, "char": lltype.Char, "address": Address, + "float": lltype.Float, } fakeaddress.signed = property(_signed_fakeaccessor) +fakeaddress.float = property(_float_fakeaccessor) fakeaddress.char = property(_char_fakeaccessor) fakeaddress.address = property(_address_fakeaccessor) fakeaddress._TYPE = Address 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 Sun Apr 6 22:36:08 2008 @@ -15,6 +15,18 @@ b.signed[0] = 234 assert s.x == 234 +def test_simple_float(): + S = lltype.GcStruct("S", ("x", lltype.Float), ("y", lltype.Float)) + s = lltype.malloc(S) + s.x = 123.2 + s.y = 456.2 + a = fakeaddress(s) + assert a.ref() == s + b = a + FieldOffset(S, 'x') + assert b.float[0] == 123.2 + b.float[0] = 234.1 + assert s.x == 234.1 + def test_composite(): S1 = lltype.GcStruct("S1", ("x", lltype.Signed), ("y", lltype.Signed)) S2 = lltype.GcStruct("S2", ("s", S1)) Modified: pypy/dist/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/dist/pypy/translator/c/test/test_lladdresses.py Sun Apr 6 22:36:08 2008 @@ -33,6 +33,24 @@ res = fc(1) assert res == 1 +def test_memory_float(): + S = lltype.GcStruct("S", ("x", lltype.Float), ("y", lltype.Float)) + offset = FieldOffset(S, 'x') + offsety = FieldOffset(S, 'y') + def f(value): + s = lltype.malloc(S) + s.x = 123.2 + a = cast_ptr_to_adr(s) + b = a + offset + assert b.float[0] == 123.2 + b.float[0] = 234.1 + (a + offsety).float[0] = value + assert s.x == 234.1 + return s.x + value + fc = compile(f, [float]) + res = fc(42.42) + assert res == f(42.42) + def test_pointer_arithmetic(): def f(offset, char): addr = raw_malloc(10000) From cami at codespeak.net Mon Apr 7 00:34:15 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 7 Apr 2008 00:34:15 +0200 (CEST) Subject: [pypy-svn] r53486 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080406223415.28E1A16A68C@codespeak.net> Author: cami Date: Mon Apr 7 00:34:14 2008 New Revision: 53486 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Log: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Mon Apr 7 00:34:14 2008 @@ -6,6 +6,23 @@ from pypy.lang.gameboy import constants + +class Channel(object): + + # Audio Channel 1 int + nr10=0 + nr11=0 + nr12=0 + nr13=0 + nr14=0 + audio1Index=0 + audio1Length=0 + audio1Frequency=0 + + def __init__(self): + pass + + class Sound(object): # Audio Channel 1 int @@ -82,28 +99,6 @@ self.generateNoiseTables() self.reset() - def start(self): - self.driver.start() - - def stop(self): - self.driver.stop() - - def cycles(self): - return self.cycles - - def emulate(self, ticks): - self.cycles -= ticks - while (self.cycles <= 0): - self.updateAudio() - if (self.driver.isEnabled()): - self.frames += self.driver.getSampleRate() - length = (self.frames / constants.SOUND_CLOCK) << 1 - self.mixAudio(self.buffer, length) - self.driver.write(self.buffer, length) - self.frames %= constants.SOUND_CLOCK - - self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK - def reset(self): self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK self.frames = 0 @@ -139,8 +134,28 @@ if (address & 1) == 0: write = 0x00 self.write(address, write) + + def start(self): + self.driver.start() + + def stop(self): + self.driver.stop() + + def cycles(self): + return self.cycles + def emulate(self, ticks): + self.cycles -= ticks + while (self.cycles <= 0): + self.updateAudio() + if self.driver.isEnabled(): + self.frames += self.driver.getSampleRate() + length = (self.frames / constants.SOUND_CLOCK) << 1 + self.mixAudio(self.buffer, length) + self.driver.write(self.buffer, length) + self.frames %= constants.SOUND_CLOCK + self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK def read(self, address): if address==constants.NR10: return self.getAudio1Sweep() @@ -245,28 +260,28 @@ self.setAudio3WavePattern(address, data) def updateAudio(self): - if ((self.nr52 & 0x80) == 0): + if (self.nr52 & 0x80) == 0: return - if ((self.nr52 & 0x01) != 0): + if (self.nr52 & 0x01) != 0: self.updateAudio1() - if ((self.nr52 & 0x02) != 0): + if (self.nr52 & 0x02) != 0: self.updateAudio2() - if ((self.nr52 & 0x04) != 0): + if (self.nr52 & 0x04) != 0: self.updateAudio3() - if ((self.nr52 & 0x08) != 0): + if (self.nr52 & 0x08) != 0: self.updateAudio4() def mixAudio(self,buffer, length): buffer = [0]*length - if ((self.nr52 & 0x80) == 0): + if (self.nr52 & 0x80) == 0: return - if ((self.nr52 & 0x01) != 0): + if (self.nr52 & 0x01) != 0: self.mixAudio1(buffer, length) - if ((self.nr52 & 0x02) != 0): + if (self.nr52 & 0x02) != 0: self.mixAudio2(buffer, length) - if ((self.nr52 & 0x04) != 0): + if (self.nr52 & 0x04) != 0: self.mixAudio3(buffer, length) - if ((self.nr52 & 0x08) != 0): + if (self.nr52 & 0x08) != 0: self.mixAudio4(buffer, length) # Audio Channel 1 @@ -321,11 +336,11 @@ self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07) def updateAudio1(self): - if ((self.nr14 & 0x40) != 0 and self.audio1Length > 0): + if (self.nr14 & 0x40) != 0 and self.audio1Length > 0: self.audio1Length-=1 - if (self.audio1Length <= 0): + if self.audio1Length <= 0: self.nr52 &= ~0x01 - if (self.audio1EnvelopeLength > 0): + if self.audio1EnvelopeLength > 0: self.audio1EnvelopeLength-=1 if (self.audio1EnvelopeLength <= 0): if ((self.nr12 & 0x08) != 0): From fijal at codespeak.net Mon Apr 7 02:14:38 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 02:14:38 +0200 (CEST) Subject: [pypy-svn] r53487 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080407001438.132AA16A69D@codespeak.net> Author: fijal Date: Mon Apr 7 02:14:36 2008 New Revision: 53487 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: * in-progress test for frame_place_read and floats * isolate does not like printing at all :( Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Mon Apr 7 02:14:36 2008 @@ -736,7 +736,6 @@ lltype.Void)) def __init__(self, RGenOp): def writer(base, value): - print value if value > 5: RGenOp.write_frame_place(TP, base, self.place1, value * 7) @@ -867,16 +866,19 @@ return write_lots_of_frame_places_runner -class FramePlaceReader: - FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Signed)) - def __init__(self, RGenOp): - def reader(base): - return RGenOp.read_frame_place(lltype.Signed, base, - self.place) - self.reader = reader - def get_reader(self, place): - self.place = place - return llhelper(self.FUNC, self.reader) +def get_frame_place_reader(TP): + class FramePlaceReader: + FUNC = lltype.Ptr(lltype.FuncType([llmemory.Address], TP)) + def __init__(self, RGenOp): + def reader(base): + return RGenOp.read_frame_place(TP, base, + self.place) + self.reader = reader + def get_reader(self, place): + self.place = place + return llhelper(self.FUNC, self.reader) + return FramePlaceReader +FramePlaceReader = get_frame_place_reader(lltype.Signed) def make_read_frame_place(rgenop, get_reader): signed_kind = rgenop.kindToken(lltype.Signed) From fijal at codespeak.net Mon Apr 7 02:24:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 02:24:22 +0200 (CEST) Subject: [pypy-svn] r53488 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080407002422.1EAC516A690@codespeak.net> Author: fijal Date: Mon Apr 7 02:24:20 2008 New Revision: 53488 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: Test for read_frame_place for floats Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Mon Apr 7 02:24:20 2008 @@ -879,17 +879,27 @@ return llhelper(self.FUNC, self.reader) return FramePlaceReader FramePlaceReader = get_frame_place_reader(lltype.Signed) +FramePlaceFloatReader = get_frame_place_reader(lltype.Float) -def make_read_frame_place(rgenop, get_reader): - signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) - readertoken = rgenop.sigToken(FramePlaceReader.FUNC.TO) +def make_read_frame_place(rgenop, get_reader, TP): + kind = rgenop.kindToken(TP) + if TP is lltype.Signed: + F = FUNC + reader = FramePlaceReader + else: + F = FLOATFUNC + reader = FramePlaceFloatReader + sigtoken = rgenop.sigToken(F) + readertoken = rgenop.sigToken(reader.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") builder.start_writing() - place = builder.alloc_frame_place(signed_kind, - rgenop.genconst(42)) + if TP is lltype.Signed: + place = builder.alloc_frame_place(kind, + rgenop.genconst(42)) + else: + place = builder.alloc_frame_place(kind, rgenop.genconst(3.3)) gv_base = builder.genop_get_frame_base() gv_reader = rgenop.constPrebuiltGlobal(get_reader(place)) gv_z = builder.genop_call(readertoken, gv_reader, [gv_base]) @@ -899,12 +909,15 @@ return gv_f -def get_read_frame_place_runner(RGenOp): - fpr = FramePlaceReader(RGenOp) +def get_read_frame_place_runner(RGenOp, TP): + if TP is lltype.Signed: + fpr = FramePlaceReader(RGenOp) + else: + fpr = FramePlaceFloatReader(RGenOp) def read_frame_place_runner(x): rgenop = RGenOp() - gv_f = make_read_frame_place(rgenop, fpr.get_reader) + gv_f = make_read_frame_place(rgenop, fpr.get_reader, TP) fn = gv_f.revealconst(lltype.Ptr(FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive @@ -1102,6 +1115,15 @@ res = fn(30) assert res == 60 + + def test_genconst_from_frame_float_var_compile(self): + runner = get_read_frame_var_runner(self.RGenOp, True, + FrameVarFloatReader, FLOATFUNC) + + fn = self.compile(runner, [float]) + res = fn(3.3) + assert res == 3.3 * 2 + def test_write_frame_place_compile(self): fn = self.compile(get_write_frame_place_runner(self.RGenOp), [int]) res = fn(-42) @@ -1110,11 +1132,11 @@ assert res == 4242 - 6060 def test_read_frame_place_compile(self): - fn = self.compile(get_read_frame_place_runner(self.RGenOp), [int]) + fn = self.compile(get_read_frame_place_runner(self.RGenOp, + lltype.Signed), [int]) res = fn(-1) assert res == 42 - def test_ovfcheck_adder_compile(self): fn = self.compile(get_ovfcheck_adder_runner(self.RGenOp), [int, int]) res = fn(9080983, -9080941) @@ -1674,11 +1696,24 @@ return reader_ptr rgenop = self.RGenOp() - gv_callable = make_read_frame_place(rgenop, get_reader) + gv_callable = make_read_frame_place(rgenop, get_reader, lltype.Signed) fnptr = self.cast(gv_callable, 1) res = fnptr(-1) assert res == 42 + def test_read_float_frame_place_direct(self): + def get_reader(place): + fpr = FramePlaceFloatReader(self.RGenOp) + fpr.place = place + reader_ptr = self.directtesthelper(fpr.FUNC, fpr.reader) + return reader_ptr + + rgenop = self.RGenOp() + gv_callable = make_read_frame_place(rgenop, get_reader, lltype.Float) + fnptr = self.cast_float(gv_callable, 1) + res = fnptr(-3.3) + assert res == 3.3 + def test_frame_vars_like_the_frontend_direct(self): rgenop = self.RGenOp() sigtoken = rgenop.sigToken(FUNC3) From fijal at codespeak.net Mon Apr 7 02:25:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 02:25:30 +0200 (CEST) Subject: [pypy-svn] r53489 - in pypy/branch/jit-hotpath/pypy/jit/codegen/ia32: . test Message-ID: <20080407002530.3A37316A699@codespeak.net> Author: fijal Date: Mon Apr 7 02:25:29 2008 New Revision: 53489 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Log: Fix test, easy :) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 02:25:29 2008 @@ -1019,8 +1019,6 @@ ## target.stackdepth, ## target.arg_positions)) - # XXX rewrite in a float-friendly way - N = target.stackdepth if builder.stackdepth < N: builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth))) @@ -1336,7 +1334,6 @@ @staticmethod @specialize.arg(1) def genzeroconst(kind): - # XXX kind probably goes away return zero_const @staticmethod @@ -1348,7 +1345,6 @@ @staticmethod def genconst_from_frame_var(kind, base, info, index): - # eh, kind here should be "what we're looking for?" v = info[index] if isinstance(v, GenConst): return v @@ -1362,7 +1358,6 @@ @staticmethod @specialize.arg(0) def read_frame_place(T, base, place): - assert T is lltype.Signed return peek_value_at(T, base - place.stackpos * WORD) global_rgenop = RI386GenOp() Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_rgenop.py Mon Apr 7 02:25:29 2008 @@ -13,6 +13,3 @@ class TestRI386GenopCompile(AbstractRGenOpTestsCompile): RGenOp = RI386GenOp from pypy.jit.codegen.ia32.test.test_operation import RGenOpPacked - - def test_read_frame_float_var_compile(self): - py.test.skip("no support for addr.float[0]") From fijal at codespeak.net Mon Apr 7 02:28:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 02:28:07 +0200 (CEST) Subject: [pypy-svn] r53490 - pypy/branch/jit-hotpath/pypy/rpython/lltypesystem Message-ID: <20080407002807.C870516A694@codespeak.net> Author: fijal Date: Mon Apr 7 02:28:07 2008 New Revision: 53490 Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/llmemory.py Log: Port address.float[] change from trunk Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/llmemory.py Mon Apr 7 02:28:07 2008 @@ -456,6 +456,9 @@ class _char_fakeaccessor(_fakeaccessor): TYPE = lltype.Char +class _float_fakeaccessor(_fakeaccessor): + TYPE = lltype.Float + class _address_fakeaccessor(_fakeaccessor): TYPE = Address @@ -482,10 +485,12 @@ "unsigned": lltype.Unsigned, "char": lltype.Char, "address": Address, + "float": lltype.Float, } fakeaddress.signed = property(_signed_fakeaccessor) fakeaddress.char = property(_char_fakeaccessor) +fakeaddress.float = property(_float_fakeaccessor) fakeaddress.address = property(_address_fakeaccessor) fakeaddress._TYPE = Address From fijal at codespeak.net Mon Apr 7 02:32:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 02:32:46 +0200 (CEST) Subject: [pypy-svn] r53491 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407003246.E1AF316A42A@codespeak.net> Author: fijal Date: Mon Apr 7 02:32:46 2008 New Revision: 53491 Added: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py - copied unchanged from r53490, pypy/branch/jit-hotpath/pypy/jit/tl/targettiny2hotpath.py pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py - copied unchanged from r53490, pypy/branch/jit-hotpath/pypy/jit/tl/tiny2_hotpath.py Log: (verbatim) copy of tiny languages in order to make a float version of them From fijal at codespeak.net Mon Apr 7 03:32:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 03:32:24 +0200 (CEST) Subject: [pypy-svn] r53492 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080407013224.D9F6F16A681@codespeak.net> Author: fijal Date: Mon Apr 7 03:32:21 2008 New Revision: 53492 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Log: A test for promoting floats. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Mon Apr 7 03:32:21 2008 @@ -265,6 +265,38 @@ assert res == ord('2') self.check_insns(indirect_call=0) + def test_float_promote(self): + class Base(object): + pass + class Int(Base): + def __init__(self, n): + self.n = n + def double(self): + return float(2*self.n) + + class Float(Base): + def __init__(self, n): + self.n = n + def double(self): + return 2*self.n + + def ll_main(n): + if n > 3: + o = Int(int(n)) + else: + o = Float(n) + return ll_function(o) + + def ll_function(o): + hint(None, global_merge_point=True) + hint(o.__class__, promote=True) + return o.double() + + res = self.timeshift_from_portal(ll_main, ll_function, [2.8], policy=P_NOVIRTUAL) + assert res == 2.8*2 + res = self.timeshift_from_portal(ll_main, ll_function, [3.6], policy=P_NOVIRTUAL) + assert res == 3*2 + def test_isinstance(self): class Base(object): pass From fijal at codespeak.net Mon Apr 7 04:07:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 04:07:13 +0200 (CEST) Subject: [pypy-svn] r53493 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080407020713.8684316A68C@codespeak.net> Author: fijal Date: Mon Apr 7 04:07:10 2008 New Revision: 53493 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Log: adapt a test a bit Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Mon Apr 7 04:07:10 2008 @@ -291,11 +291,12 @@ hint(None, global_merge_point=True) hint(o.__class__, promote=True) return o.double() + ll_main.convert_result = str res = self.timeshift_from_portal(ll_main, ll_function, [2.8], policy=P_NOVIRTUAL) - assert res == 2.8*2 + assert float(res) == 2.8*2 res = self.timeshift_from_portal(ll_main, ll_function, [3.6], policy=P_NOVIRTUAL) - assert res == 3*2 + assert float(res) == 3*2 def test_isinstance(self): class Base(object): From fijal at codespeak.net Mon Apr 7 04:08:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 04:08:00 +0200 (CEST) Subject: [pypy-svn] r53494 - pypy/branch/jit-hotpath/pypy/jit/rainbow Message-ID: <20080407020800.0B39916A68C@codespeak.net> Author: fijal Date: Mon Apr 7 04:08:00 2008 New Revision: 53494 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Log: Kill r_uint here. It's compared with -1 later on (stuff even returns -1, please explain me what's going on) This prevented jit from compilation. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Mon Apr 7 04:08:00 2008 @@ -253,7 +253,7 @@ self.queue = rtimeshift.DispatchQueue(bytecode.num_mergepoints) rtimeshift.enter_frame(self.jitstate, self.queue) self.frame = self.jitstate.frame - self.frame.pc = r_uint(0) + self.frame.pc = 0 self.frame.bytecode = bytecode self.frame.local_boxes = redargs self.frame.local_green = greenargs @@ -384,10 +384,10 @@ def load_4byte(self): pc = self.frame.pc - result = ((r_uint(ord(self.frame.bytecode.code[pc + 0])) << 24) | - (r_uint(ord(self.frame.bytecode.code[pc + 1])) << 16) | - (r_uint(ord(self.frame.bytecode.code[pc + 2])) << 8) | - (r_uint(ord(self.frame.bytecode.code[pc + 3])) << 0)) + result = (((ord(self.frame.bytecode.code[pc + 0])) << 24) | + ((ord(self.frame.bytecode.code[pc + 1])) << 16) | + ((ord(self.frame.bytecode.code[pc + 2])) << 8) | + ((ord(self.frame.bytecode.code[pc + 3])) << 0)) self.frame.pc = pc + 4 return result @@ -904,7 +904,7 @@ def hp_direct_call(self, greenargs, redargs, targetbytecode): frame = rtimeshift.VirtualFrame(self.frame, None) self.frame = self.jitstate.frame = frame - frame.pc = r_uint(0) + frame.pc = 0 frame.bytecode = targetbytecode frame.local_boxes = redargs frame.local_green = greenargs From fijal at codespeak.net Mon Apr 7 04:08:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 04:08:28 +0200 (CEST) Subject: [pypy-svn] r53495 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test Message-ID: <20080407020828.3667D16A68C@codespeak.net> Author: fijal Date: Mon Apr 7 04:08:27 2008 New Revision: 53495 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py Log: adapt a test a bit Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py Mon Apr 7 04:08:27 2008 @@ -44,7 +44,7 @@ decoders = main.convert_arguments assert len(decoders) == len(main_args) else: - decoders = [int] * len(main_args) + decoders = [type(arg) for arg in main_args] decoders = unrolling_iterable(decoders) numargs = len(main_args) USAGE = '%s: %d arguments expected\n' % (self.testname, numargs) From fijal at codespeak.net Mon Apr 7 04:08:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 04:08:58 +0200 (CEST) Subject: [pypy-svn] r53496 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407020858.D5BF716A68C@codespeak.net> Author: fijal Date: Mon Apr 7 04:08:58 2008 New Revision: 53496 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Attempt to fix translation a bit Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 04:08:58 2008 @@ -27,8 +27,12 @@ if objectmodel.we_are_translated(): if T is lltype.Float: return addr.float[0] + elif T is llmemory.Address: + return addr.address[0] + elif isinstance(T, lltype.Ptr): + return lltype.cast_int_to_ptr(T, addr.signed[0]) else: - return addr.signed[0] + return lltype.cast_primitive(T, addr.signed[0]) else: tp = ctypes_mapping[T] p = cast(c_void_p(addr), POINTER(tp)) @@ -42,8 +46,12 @@ if objectmodel.we_are_translated(): if T is lltype.Float: addr.float[0] = value + elif isinstance(T, lltype.Ptr): + addr.signed[0] = intmask(lltype.cast_ptr_to_int(value)) + elif T is llmemory.Address: + addr.signed[0] = intmask(llmemory.cast_adr_to_int(value)) else: - addr.signed[0] = value + addr.signed[0] = lltype.cast_primitive(lltype.Signed, value) else: tp = ctypes_mapping[T] p = cast(c_void_p(addr), POINTER(tp)) From fijal at codespeak.net Mon Apr 7 04:29:52 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 04:29:52 +0200 (CEST) Subject: [pypy-svn] r53497 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407022952.9997316A62D@codespeak.net> Author: fijal Date: Mon Apr 7 04:29:44 2008 New Revision: 53497 Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Log: The same engine, but for ints/floats (still not sure how efficient it is, or how jit-friendly) Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Mon Apr 7 04:29:44 2008 @@ -4,13 +4,14 @@ words have another action. The result is the space-separated words from the stack. - Hello World => 'Hello World' 6 7 ADD => '13' 'ADD' is a special word 7 * 5 = 7 5 MUL => '7 * 5 = 35' '*' and '=' are not special words + 3.8 => 3.8 -Arithmetic on non-integers gives a 'symbolic' result: +Arithmetic on integers and floats automatically casts arguments +to floats (always). - X 2 MUL => 'X*2' + 3.8 1 ADD => 4.8 Input arguments can be passed on the command-line, and used as #1, #2, etc.: @@ -48,30 +49,34 @@ self.intval = intval def as_int(self): return self.intval + def as_float(self): + return float(self.intval) def as_str(self): return str(self.intval) -class StrBox(Box): +class FloatBox(Box): _immutable_ = True - def __init__(self, strval): - self.strval = strval + def __init__(self, floatval): + self.floatval = floatval def as_int(self): - return myint(self.strval) + return int(self.floatval) + def as_float(self): + return self.floatval def as_str(self): - return self.strval - + return str(self.floatval) +# consider if we need both def func_add_int(ix, iy): return ix + iy def func_sub_int(ix, iy): return ix - iy def func_mul_int(ix, iy): return ix * iy -def func_add_str(sx, sy): return sx + '+' + sy -def func_sub_str(sx, sy): return sx + '-' + sy -def func_mul_str(sx, sy): return sx + '*' + sy +def func_add_float(fx, fy): return fx + fy +def func_sub_float(fx, fy): return fx - fy +def func_mul_float(fx, fy): return fx * fy -def op2(stack, func_int, func_str): +def op2(stack, func_int, func_float): # Operate on the top two stack items. The promotion hints force the - # class of each arguments (IntBox or StrBox) to turn into a compile-time + # class of each arguments (IntBox or FloatBox) to turn into a compile-time # constant if they weren't already. The effect we seek is to make the # calls to as_int() direct calls at compile-time, instead of indirect # ones. The JIT compiler cannot look into indirect calls, but it @@ -80,10 +85,10 @@ hint(y.__class__, promote=True) stack, x = stack.pop() hint(x.__class__, promote=True) - try: + if isinstance(x, IntBox) and isinstance(y, IntBox): z = IntBox(func_int(x.as_int(), y.as_int())) - except ValueError: - z = StrBox(func_str(x.as_str(), y.as_str())) + else: + z = FloatBox(func_float(x.as_float(), y.as_float())) stack = Stack(z, stack) return stack @@ -98,7 +103,6 @@ def empty_stack(): return None - class TinyJitDriver(JitDriver): reds = ['args', 'loops', 'stack'] greens = ['bytecode', 'pos'] @@ -157,11 +161,11 @@ hint(opcode, concrete=True) # same as in tiny1.py pos += 1 if opcode == 'ADD': - stack = op2(stack, func_add_int, func_add_str) + stack = op2(stack, func_add_int, func_add_float) elif opcode == 'SUB': - stack = op2(stack, func_sub_int, func_sub_str) + stack = op2(stack, func_sub_int, func_sub_float) elif opcode == 'MUL': - stack = op2(stack, func_mul_int, func_mul_str) + stack = op2(stack, func_mul_int, func_mul_float) elif opcode[0] == '#': n = myint(opcode, start=1) stack = Stack(args[n-1], stack) @@ -193,7 +197,14 @@ tinyjitdriver.can_enter_jit(args=args, loops=loops, stack=stack, bytecode=bytecode, pos=pos) else: - stack = Stack(StrBox(opcode), stack) + try: + try: + v = IntBox(int(opcode)) + except ValueError: + v = FloatBox(float(opcode)) + stack = Stack(v, stack) + except ValueError: + pass # ignore rest return stack @@ -243,22 +254,22 @@ main = """#1 5 ADD""".split() res = interpret(main, [IntBox(20)]) assert repr(res) == '25' - res = interpret(main, [StrBox('foo')]) - assert repr(res) == 'foo+5' + res = interpret(main, [FloatBox(3.2)]) + assert repr(res) == '8.2' FACTORIAL = """The factorial of #1 is 1 { #1 MUL #1 1 SUB ->#1 #1 }""".split() def test_factorial(): res = interpret(FACTORIAL, [IntBox(5)]) - assert repr(res) == 'The factorial of 5 is 120' + assert repr(res) == '5 120' FIBONACCI = """Fibonacci numbers: { #1 #2 #1 #2 ADD ->#2 ->#1 #3 1 SUB ->#3 #3 }""".split() def test_fibonacci(): res = interpret(FIBONACCI, [IntBox(1), IntBox(1), IntBox(10)]) - assert repr(res) == "Fibonacci numbers: 1 1 2 3 5 8 13 21 34 55" + assert repr(res) == "1 1 2 3 5 8 13 21 34 55" FIBONACCI_SINGLE = """#3 1 SUB ->#3 { #2 #1 #2 ADD ->#2 ->#1 #3 1 SUB ->#3 #3 } #1""".split() From fijal at codespeak.net Mon Apr 7 04:45:21 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 04:45:21 +0200 (CEST) Subject: [pypy-svn] r53498 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407024521.8AFC716801F@codespeak.net> Author: fijal Date: Mon Apr 7 04:45:16 2008 New Revision: 53498 Modified: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Log: Make it all a bit more jit-friendly Modified: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py Mon Apr 7 04:45:16 2008 @@ -1,4 +1,4 @@ -from pypy.jit.tl import tiny2_hotpath as tiny2 +from pypy.jit.tl import tiny3_hotpath as tiny3 from pypy.jit.codegen.hlinfo import highleveljitinfo @@ -6,7 +6,7 @@ print err print highleveljitinfo.sys_executable, print "[-j param=value,...]", - print "'tiny2 program string' arg0 [arg1 [arg2 [...]]]" + print "'tiny3 program string' arg0 [arg1 [arg2 [...]]]" return 1 def entry_point(args): @@ -22,14 +22,19 @@ if len(args) < 3: return help() try: - tiny2.tinyjitdriver.set_user_param(args[1]) + tiny3.tinyjitdriver.set_user_param(args[1]) except ValueError: return help("Bad argument to -j.") args = args[2:] bytecode = [s for s in args[0].split(' ') if s != ''] - args = [tiny2.StrBox(arg) for arg in args[1:]] - res = tiny2.interpret(bytecode, args) - print tiny2.repr(res) + real_args = [] + for arg in args[1:]: + try: + real_args.append(tiny3.IntBox(int(arg))) + except ValueError: + real_args.append(tiny3.FloatBox(float(arg))) + res = tiny3.interpret(bytecode, real_args) + print tiny3.repr(res) return 0 def target(driver, args): @@ -46,7 +51,8 @@ def look_inside_graph(self, graph): # temporary workaround - return getattr(graph, 'func', None) is not tiny2.myint_internal + return getattr(graph, 'func', None) not in (tiny3.myint_internal, + tiny3.myfloat) def portal(driver): """Return the 'portal' function, and the hint-annotator policy. Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Mon Apr 7 04:45:16 2008 @@ -29,6 +29,7 @@ """ from pypy.rlib.jit import hint, _is_early_constant, JitDriver +from pypy.rlib.objectmodel import specialize # # See pypy/doc/jit.txt for a higher-level overview of the JIT techniques @@ -50,7 +51,7 @@ def as_int(self): return self.intval def as_float(self): - return float(self.intval) + return myfloat(self.intval) def as_str(self): return str(self.intval) @@ -201,7 +202,7 @@ try: v = IntBox(int(opcode)) except ValueError: - v = FloatBox(float(opcode)) + v = FloatBox(myfloat(opcode)) stack = Stack(v, stack) except ValueError: pass # ignore rest @@ -247,6 +248,10 @@ if n < 0: raise ValueError return n + + at specialize.argtype(0) +def myfloat(i): + return float(i) # ------------------------------ From fijal at codespeak.net Mon Apr 7 05:22:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 05:22:00 +0200 (CEST) Subject: [pypy-svn] r53499 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407032200.7DE6E16A619@codespeak.net> Author: fijal Date: Mon Apr 7 05:21:57 2008 New Revision: 53499 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: * Keepalive FloatConsts (they're not yet needing it, but they'll) * Fix assertion to work even after translation Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 05:21:57 2008 @@ -1012,8 +1012,12 @@ res_positions.append(pos) res_positions.append(pos - 1) # no repeats please - if not objectmodel.we_are_translated(): - assert sorted(dict.fromkeys(res_positions).keys()) == sorted(res_positions) + all = {} + for key in res_positions: + assert key not in all + all[key] = True + #if not objectmodel.we_are_translated(): + # assert sorted(dict.fromkeys(res_positions).keys()) == sorted(res_positions) return res_gv, res_positions def remap_stack_layout(builder, outputargs_gv, target): @@ -1266,7 +1270,9 @@ elif T is lltype.Bool: return BoolConst(llvalue) elif T is lltype.Float: - return FloatConst(llvalue) + res = FloatConst(llvalue) + self.keepalive_gc_refs.append(res) + return res elif isinstance(T, lltype.Ptr): lladdr = llmemory.cast_ptr_to_adr(llvalue) if T.TO._gckind == 'gc': From fijal at codespeak.net Mon Apr 7 05:49:19 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 05:49:19 +0200 (CEST) Subject: [pypy-svn] r53500 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407034919.7AE6716A65A@codespeak.net> Author: fijal Date: Mon Apr 7 05:49:18 2008 New Revision: 53500 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: * Fix last remaining test * Refactor floats to work better with JIT (jit is suspicious about raw malloc) the problem is that our fakeaddr is not powerful enough, hence we really need to have two versions of those :( Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 05:49:18 2008 @@ -2,7 +2,7 @@ from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.rpython.lltypesystem import lltype, rffi, llmemory from pypy.rlib.unroll import unrolling_iterable -from pypy.rlib.objectmodel import specialize +from pypy.rlib.objectmodel import specialize, we_are_translated from pypy.jit.codegen.i386.ri386 import * WORD = 4 @@ -190,30 +190,47 @@ dstop = builder.mem_access(addr) builder.mc.MOV(dstop, self.operand(builder)) +FLOATBUF = lltype.Ptr(lltype.GcArray(lltype.Float)) + class FloatConst(Const): SIZE = 2 # XXX hack for annotator - rawbuf = lltype.nullptr(rffi.DOUBLEP.TO) + buf = lltype.nullptr(FLOATBUF.TO) def __init__(self, floatval): - # XXX we should take more care who is creating this and - # eventually release this buffer - # never moves and never dies - self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') - self.rawbuf[0] = floatval + if we_are_translated(): + self.buf = lltype.malloc(FLOATBUF.TO, 1) + else: + self.buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') + self.buf[0] = floatval + + def _compute_addr(self): + if we_are_translated(): + addr = llmemory.cast_ptr_to_adr(self.buf) + \ + llmemory.itemoffsetof(FLOATBUF.TO, 0) + return llmemory.cast_adr_to_int(addr) + else: + return rffi.cast(rffi.INT, self.buf) + + @specialize.arg(1) + def revealconst(self, T): + assert T is lltype.Float + return self.buf[0] def newvar(self, builder): - return builder.newfloatfrommem((None, None, 0, - rffi.cast(rffi.INT, self.rawbuf))) + offset = self._compute_addr() + return builder.newfloatfrommem((None, None, 0, offset)) def operand(self, builder): - return heap64(rffi.cast(rffi.INT, self.rawbuf)) + return heap64(self._compute_addr()) def movetonewaddr(self, builder, addr): dstop1 = builder.mem_access(addr) dstop2 = builder.mem_access(addr, WORD) - builder.mc.MOV(dstop1, imm(rffi.cast(rffi.INTP, self.rawbuf)[0])) - builder.mc.MOV(dstop2, imm(rffi.cast(rffi.INTP, self.rawbuf)[1])) + offset = self._compute_addr() + b = rffi.cast(rffi.INTP, offset) + builder.mc.MOV(dstop1, imm(b[0])) + builder.mc.MOV(dstop2, imm(b[1])) def repr(self): return "const=$%s" % (self.rawbuf[0],) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 05:49:18 2008 @@ -1006,7 +1006,7 @@ res_gv.append(IntVar(gv.stackpos - 1)) else: assert isinstance(gv, FloatConst) - buf = rffi.cast(rffi.INTP, gv.rawbuf) + buf = rffi.cast(rffi.INTP, gv._compute_addr()) res_gv.append(IntConst(buf[0])) res_gv.append(IntConst(buf[1])) res_positions.append(pos) @@ -1362,7 +1362,10 @@ v = info[index] if isinstance(v, GenConst): return v - return IntConst(peek_value_at(lltype.Signed, base - v.stackpos * WORD)) + if kind == "f": + return FloatConst(peek_value_at(lltype.Float, base - v.stackpos * WORD)) + else: + return IntConst(peek_value_at(lltype.Signed, base - v.stackpos * WORD)) @staticmethod @specialize.arg(0) From fijal at codespeak.net Mon Apr 7 05:53:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 05:53:41 +0200 (CEST) Subject: [pypy-svn] r53501 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407035341.4032A16A62D@codespeak.net> Author: fijal Date: Mon Apr 7 05:53:40 2008 New Revision: 53501 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Log: be more specific (and make annotator happier) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 05:53:40 2008 @@ -200,9 +200,10 @@ def __init__(self, floatval): if we_are_translated(): self.buf = lltype.malloc(FLOATBUF.TO, 1) + self.buf[0] = floatval else: - self.buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') - self.buf[0] = floatval + self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') + self.rawbuf[0] = floatval def _compute_addr(self): if we_are_translated(): @@ -210,12 +211,15 @@ llmemory.itemoffsetof(FLOATBUF.TO, 0) return llmemory.cast_adr_to_int(addr) else: - return rffi.cast(rffi.INT, self.buf) + return rffi.cast(rffi.INT, self.rawbuf) @specialize.arg(1) def revealconst(self, T): assert T is lltype.Float - return self.buf[0] + if we_are_translated(): + return self.buf[0] + else: + return self.rawbuf[0] def newvar(self, builder): offset = self._compute_addr() From fijal at codespeak.net Mon Apr 7 05:55:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 05:55:13 +0200 (CEST) Subject: [pypy-svn] r53502 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407035513.6D1DE16A640@codespeak.net> Author: fijal Date: Mon Apr 7 05:55:12 2008 New Revision: 53502 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Be more precise (and make annotator happier) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 05:55:12 2008 @@ -1196,7 +1196,8 @@ def __init__(self): self.mcs = [] # machine code blocks where no-one is currently writing - self.keepalive_gc_refs = [] + self.keepalive_gc_refs = [] + self.keepalive_float_consts = [] self.total_code_blocks = 0 def open_mc(self): @@ -1271,7 +1272,7 @@ return BoolConst(llvalue) elif T is lltype.Float: res = FloatConst(llvalue) - self.keepalive_gc_refs.append(res) + self.keepalive_float_consts.append(res) return res elif isinstance(T, lltype.Ptr): lladdr = llmemory.cast_ptr_to_adr(llvalue) From fijal at codespeak.net Mon Apr 7 06:03:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 06:03:56 +0200 (CEST) Subject: [pypy-svn] r53503 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407040356.D266616A662@codespeak.net> Author: fijal Date: Mon Apr 7 06:03:56 2008 New Revision: 53503 Modified: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py Log: JIT is not happy seeing float() Modified: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py Mon Apr 7 06:03:56 2008 @@ -32,7 +32,7 @@ try: real_args.append(tiny3.IntBox(int(arg))) except ValueError: - real_args.append(tiny3.FloatBox(float(arg))) + real_args.append(tiny3.FloatBox(tiny3.myfloat(arg))) res = tiny3.interpret(bytecode, real_args) print tiny3.repr(res) return 0 From fijal at codespeak.net Mon Apr 7 07:34:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 07:34:01 +0200 (CEST) Subject: [pypy-svn] r53504 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407053401.8BE8D16A630@codespeak.net> Author: fijal Date: Mon Apr 7 07:34:00 2008 New Revision: 53504 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Be ultra paranoid. It seems that this one causes pypy-c to explode (there is -1 somewhere around) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 07:34:00 2008 @@ -1035,9 +1035,14 @@ if builder.stackdepth < N: builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth))) builder.stackdepth = N - + + for pos in arg_positions: + assert pos >= 0 outputargs_gv, arg_positions = _remap_bigger_values(outputargs_gv, target.arg_positions) + for pos in arg_positions: + assert pos >= 0 + M = len(outputargs_gv) assert M == len(arg_positions) targetlayout = [None] * N From fijal at codespeak.net Mon Apr 7 08:15:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 08:15:32 +0200 (CEST) Subject: [pypy-svn] r53505 - pypy/branch/jit-hotpath/pypy/jit/codegen/test Message-ID: <20080407061532.E388C16A5E5@codespeak.net> Author: fijal Date: Mon Apr 7 08:15:30 2008 New Revision: 53505 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: Adapt a test. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Mon Apr 7 08:15:30 2008 @@ -2401,8 +2401,9 @@ if self.RGenOpPacked is None: py.test.skip("requires RGenOpPacked") T = lltype.GcStruct('T', ('x', lltype.Signed), - ('y', lltype.Float), - ('z', lltype.Signed)) + ('y', lltype.Float), + ('k', lltype.Char), + ('z', lltype.Bool)) rgenop = self.RGenOpPacked() ARGS = [lltype.Signed, lltype.Float, lltype.Signed] FUNC = lltype.FuncType(ARGS, lltype.Float) @@ -2413,10 +2414,14 @@ gv_s = builder.genop_malloc_fixedsize(rgenop.allocToken(T)) builder.genop_setfield(rgenop.fieldToken(T, 'x'), gv_s, gv_x) builder.genop_setfield(rgenop.fieldToken(T, 'y'), gv_s, gv_y) - builder.genop_setfield(rgenop.fieldToken(T, 'z'), gv_s, gv_z) + gv_z1 = builder.genop1('int_is_true', gv_z) + builder.genop_setfield(rgenop.fieldToken(T, 'z'), gv_s, gv_z1) + gv_z2 = builder.genop1('cast_int_to_char', gv_z) + builder.genop_setfield(rgenop.fieldToken(T, 'k'), gv_s, gv_z2) gv_y1 = builder.genop_getfield(rgenop.fieldToken(T, 'y'), gv_s) - gv_z1 = builder.genop_getfield(rgenop.fieldToken(T, 'z'), gv_s) - gv_z2 = builder.genop1('cast_int_to_float', gv_z1) + gv_z1 = builder.genop_getfield(rgenop.fieldToken(T, 'k'), gv_s) + gv_z1b = builder.genop1('cast_char_to_int', gv_z1) + gv_z2 = builder.genop1('cast_int_to_float', gv_z1b) gv_res = builder.genop2('float_add', gv_y1, gv_z2) builder.finish_and_return(sigtoken, gv_res) builder.end() From fijal at codespeak.net Mon Apr 7 08:17:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 08:17:50 +0200 (CEST) Subject: [pypy-svn] r53506 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407061750.C812416A5E5@codespeak.net> Author: fijal Date: Mon Apr 7 08:17:49 2008 New Revision: 53506 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Small fix, but that's not what I'm looking for :-/ Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 08:17:49 2008 @@ -76,7 +76,7 @@ return builder.returnboolvar(self.operand(builder)) def movetonewaddr(self, builder, addr): - destop = builder.mem_access(addr) + destop = builder.mem_access8(addr) builder.mc.MOV(eax, self.operand(builder)) builder.mc.MOV(destop, al) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 08:17:49 2008 @@ -294,6 +294,7 @@ return genmethod(gv_arg) def genop_getfield(self, (offset, fieldsize, kindtoken), gv_ptr): + assert fieldsize != 2 self.mc.MOV(edx, gv_ptr.operand(self)) return self.newvarfromaddr(kindtoken, (edx, None, 0, offset)) @@ -319,6 +320,7 @@ return vars_gv def genop_setfield(self, (offset, fieldsize, kt), gv_ptr, gv_value): + assert fieldsize != 2 self.mc.MOV(edx, gv_ptr.operand(self)) gv_value.movetonewaddr(self, (edx, None, 0, offset)) @@ -377,6 +379,7 @@ itemsize = arraytoken[2] self.mc.MOV(edx, gv_ptr.operand(self)) destaddr = self._compute_itemaddr(edx, arraytoken, gv_index) + assert itemsize != 2 gv_value.movetonewaddr(self, destaddr) #if itemsize <= WORD: # self.mc.MOV(eax, gv_value.operand(self)) @@ -1036,7 +1039,7 @@ builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth))) builder.stackdepth = N - for pos in arg_positions: + for pos in target.arg_positions: assert pos >= 0 outputargs_gv, arg_positions = _remap_bigger_values(outputargs_gv, target.arg_positions) From arigo at codespeak.net Mon Apr 7 10:54:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Apr 2008 10:54:32 +0200 (CEST) Subject: [pypy-svn] r53508 - pypy/dist/pypy/lib Message-ID: <20080407085432.6506C16A5B2@codespeak.net> Author: arigo Date: Mon Apr 7 10:54:31 2008 New Revision: 53508 Modified: pypy/dist/pypy/lib/_minimal_curses.py pypy/dist/pypy/lib/readline.py Log: Remove the hack: sys.modules["_curses"] = _minimal_curses This avoids confusing users - previously, "import curses" would fail on PyPy but "import readline, curses" would work (but crash later by giving you an incomplete curses). Modified: pypy/dist/pypy/lib/_minimal_curses.py ============================================================================== --- pypy/dist/pypy/lib/_minimal_curses.py (original) +++ pypy/dist/pypy/lib/_minimal_curses.py Mon Apr 7 10:54:31 2008 @@ -52,6 +52,3 @@ if result is None: raise error("tparm() returned NULL") return result - -def has_key(*args): - XXX Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Mon Apr 7 10:54:31 2008 @@ -3,6 +3,7 @@ """ import sys, os +import pyrepl.curses # check to give an early ImportError ENCODING = 'latin1' # XXX hard-coded @@ -266,15 +267,6 @@ def _setup(): try: - import _curses - except ImportError: - try: - import _minimal_curses - except ImportError: - raise ImportError("readline.py needs a minimal curses module") - sys.modules['_curses'] = _minimal_curses - - try: f_in = sys.stdin.fileno() f_out = sys.stdout.fileno() except AttributeError: From cami at codespeak.net Mon Apr 7 10:57:02 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 7 Apr 2008 10:57:02 +0200 (CEST) Subject: [pypy-svn] r53509 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080407085702.0ED5316A5B9@codespeak.net> Author: cami Date: Mon Apr 7 10:57:01 2008 New Revision: 53509 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Log: extended flag testing completed test Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Mon Apr 7 10:57:01 2008 @@ -523,13 +523,12 @@ # 1 cycle def rotateLeftCircular(self, getter, setter): - s = ((getter() & 0x7F) << 1) + ((getter() & 0x80) >> 7) + s = (getter() << 1) + (getter() >> 7) self.flagsAndSetterFinish(s, setter, 0x80) # rotateLeftCircularA 1 cycle def rotateLeftCircularA(self): - self.f.cFlagAdd(self.a.get(), 0x80, reset=True) - self.a.set(((self.a.get() & 0x7F) << 1) + ((self.a.get() & 0x80) >> 7)) + self.rotateLeftCircular(self.a.get, self.a.set) # 1 cycle def rotateLeft(self, getter, setter): @@ -540,21 +539,16 @@ # RLA 1 cycle def rotateLeftA(self): - s = ((self.a.get() & 0x7F) << 1) - if self.f.cFlag: - s += 0x01 - self.f.cFlagAdd(self.a.get(), 0x80, reset=True) - self.a.set(s) # 1 cycle + self.rotateLeft(self.a.get, self.a.set) # 1 cycle def rotateRightCircular(self, getter, setter): - s = (getter() >> 1) + ((getter() & 0x01) << 7) + s = (getter() >> 1) + (getter() << 7) self.flagsAndSetterFinish(s, setter) # 1 cycle # RRCA 1 cycle def rotateRightCircularA(self): - self.f.cFlagAdd(self.a.get(), reset=True) - self.a.set(((self.a.get() >> 1) & 0x7F) + ((self.a.get() << 7) & 0x80)) #1 cycle + self.rotateRightCircular(self.a.get, self.a.set) # 1 cycle def rotateRight(self, getter, setter): @@ -565,11 +559,7 @@ # RRA 1 cycle def rotateRightA(self): - s = ((self.a.get() >> 1) & 0x7F) - if self.f.cFlag: - s += 0x80 - self.f.cFlagAdd(self.a.get(), reset=True) - self.a.set(s) # 1 cycle + self.rotateRight(self.a.get, self.a.set) # 2 cycles def shiftLeftArithmetic(self, getter, setter): @@ -588,13 +578,14 @@ # 2 cycles def flagsAndSetterFinish(self, s, setter, compareAnd=0x01): + s &= 0xFF self.f.zeroFlagAdd(s, reset=True) self.f.cFlagAdd(s, compareAnd) setter(s) # 1 cycle # 1 cycle def swap(self, getter, setter): - s = ((getter() << 4) & 0xF0) + ((getter() >> 4) & 0x0F) + s = ((getter() << 4) + (getter() >> 4)) & 0xFF self.f.zeroFlagAdd(s, reset=True) setter(s) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Mon Apr 7 10:57:01 2008 @@ -324,6 +324,24 @@ if pc is not None: assert cpu.pc.get() == pc, "Register pc is %s but should be %s" % (hex(cpu.pc.get()), hex(pc)) + +def assert_default_flags(cpu, zFlag=True, nFlag=False, hFlag=False, cFlag=False, pFlag=False, sFlag=False): + assert_flags(cpu, zFlag, nFlag, hFlag, cFlag, pFlag, sFlag) + +def assert_flags(cpu, zFlag=None, nFlag=None, hFlag=None, cFlag=None, pFlag=None, sFlag=None): + if zFlag is not None: + assert cpu.f.zFlag == zFlag, "Z-Flag is %s but should be %s" % (cpu.f.zFlag, zFlag) + if nFlag is not None: + assert cpu.f.nFlag == nFlag, "N-Flag is %s but should be %s" % (cpu.f.nFlag, nFlag) + if hFlag is not None: + assert cpu.f.hFlag == hFlag, "H-Flag is %s but should be %s" % (cpu.f.hFlag, hFlag) + if cFlag is not None: + assert cpu.f.cFlag == cFlag, "C-Flag is %s but should be %s" % (cpu.f.cFlag, cFlag) + if pFlag is not None: + assert cpu.f.pFlag == pFlag, "P-Flag is %s but should be %s" % (cpu.f.pFlag, pFlag) + if sFlag is not None: + assert cpu.f.sFlag == sFlag, "S-Flag is %s but should be %s" % (cpu.f.sFlag, sFlag) + def prepare_for_fetch(cpu, value, valueLo=None): pc = cpu.pc.get() if valueLo is not None: @@ -561,6 +579,23 @@ cpu.reset() opCode += 0x10 value += 3 + +def test_inc(): + cpu = get_cpu() + # cycle testing is done in the other tests + a = cpu.a + a.set(0xFF) + cpu.f.cFlag = True + cpu.inc(a.get, a.set) + assert_default_flags(cpu, zFlag=True, hFlag=True, cFlag=True) + + a.set(0x01) + cpu.inc(a.get, a.set) + assert_default_flags(cpu, zFlag=False, hFlag=False, cFlag=True) + + a.set(0x0F) + cpu.inc(a.get, a.set) + assert_default_flags(cpu, zFlag=False, hFlag=True, cFlag=True) # inc_B C D E H L A def test_0x04_to_0x3C_inc_registers(): @@ -589,6 +624,21 @@ assert cpu.read(cpu.hl.get()) == value cycle_test(cpu, 0x34, 3) assert cpu.read(cpu.hl.get()) == value +1 + + +def test_dec(): + cpu = get_cpu() + # cycle testing is done in the other tests + a = cpu.a + a.set(1) + cpu.f.cFlag = True + cpu.dec(a.get, a.set) + assert_default_flags(cpu, zFlag=True, hFlag=False, nFlag=True, cFlag=True) + + a.set(0x0F+1) + cpu.dec(a.get, a.set) + assert_default_flags(cpu, zFlag=False, hFlag=True, nFlag=True, cFlag=True) + # dec_B C D E H L A def test_0x05_to_0x3D_dec_registers(): @@ -647,28 +697,92 @@ cpu.hl.set(address) oldPC = cpu.pc.get() cycle_test(cpu, 0x36, 3) - assert cpu.read(cpu.hl.get()) == value - assert cpu.pc.get() - oldPC == 1 + assert cpu.read(cpu.hl.get()) == value + assert_default_registers(cpu, pc=oldPC+1, hl=address) # rlca def test_0x07(): cpu = get_cpu() + value = 0x80 + cpu.a.set(value) + cycle_test(cpu, 0x07, 1) + assert_default_registers(cpu, a=((value << 1) | (value >> 7)) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=False) + + cpu.reset() + value = 0x40 + cpu.a.set(value) cycle_test(cpu, 0x07, 1) + assert_default_registers(cpu, a=((value << 1) | (value >> 7)) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=True) # rrca def test_0x0F(): cpu = get_cpu() + value = 0x01 + cpu.a.set(value) cycle_test(cpu, 0x0F, 1) + assert_default_registers(cpu, a=((value >> 1) | (value << 7)) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=False) + + cpu.reset() + value = 0x02 + cpu.a.set(value) + cycle_test(cpu, 0x0F, 1) + assert_default_registers(cpu, a=((value >> 1) | (value << 7)) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=True) # rla def test_0x17(): cpu = get_cpu() + value = 0x01 + cpu.a.set(value) + cpu.f.cFlag = False cycle_test(cpu, 0x17, 1) - + assert_default_registers(cpu, a=(value << 1) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=False) + + cpu.reset() + value = 0x01 + cpu.a.set(value) + cpu.f.cFlag = True + cycle_test(cpu, 0x17, 1) + assert_default_registers(cpu, a=((value << 1)+1) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=False) + + cpu.reset() + value = 0x40 + cpu.a.set(value) + cpu.f.cFlag = False + cycle_test(cpu, 0x17, 1) + assert_default_registers(cpu, a=(value << 1) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=True) + # rra def test_0x1F(): cpu = get_cpu() + value = 0x40 + cpu.a.set(value) + cpu.f.cFlag = False + cycle_test(cpu, 0x1F, 1) + assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=False) + + cpu.reset() + value = 0x40 + cpu.a.set(value) + cpu.f.cFlag = True + cycle_test(cpu, 0x1F, 1) + assert_default_registers(cpu, a=(0x08+(value >> 1)) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=False) + + cpu.reset() + value = 0x02 + cpu.a.set(value) + cpu.f.cFlag = False cycle_test(cpu, 0x1F, 1) + assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); + assert_default_flags(cpu, zFlag=False, cFlag=True) # daa def test_0x27(): @@ -682,24 +796,35 @@ fValue = cpu.f.get() cpu.a.set(value) cycle_test(cpu, 0x2F, 1) - assert_default_registers(cpu, a=value^0xFF, f=fValue+constants.N_FLAG+constants.H_FLAG) + assert_default_registers(cpu, a=value^0xFF, f=None) + assert_default_flags(cpu, nFlag=True, hFlag=True) # scf def test_0x37(): cpu = get_cpu() - value = 0x12 - cpu.f.set(value) + cpu.f.cFlag = False cycle_test(cpu, 0x37, 0) - assert_default_registers(cpu, f=(value & constants.Z_FLAG)|constants.C_FLAG) + assert_default_registers(cpu, f=None) + assert_default_flags(cpu, cFlag=True) + + cpu.f.cFlag = True + cycle_test(cpu, 0x37, 0) + assert_default_registers(cpu, f=None) + assert_default_flags(cpu, cFlag=True) # ccf def test_0x3F(): cpu = get_cpu() - value = 0x12 - cpu.f.set(value) + cpu.f.cFlag = True cycle_test(cpu, 0x3F, 0) - assert_default_registers(cpu, f=(value & (constants.Z_FLAG|constants.C_FLAG))^constants.C_FLAG) - + assert_default_registers(cpu, f=None) + assert_default_flags(cpu, cFlag=False) + + cpu.f.cFlag = False + cycle_test(cpu, 0x3F, 0) + assert_default_registers(cpu, f=None) + assert_default_flags(cpu, cFlag=True) + # halt def test_0x76(): py.test.skip("test not completed yet") @@ -707,6 +832,7 @@ assert cpu.halted == False cycle_test(cpu, 0x76, 0) assert cpu.halted == True + assert_default_registers(cpu) # ld_B_B to ld_A_A From antocuni at codespeak.net Mon Apr 7 11:24:41 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 11:24:41 +0200 (CEST) Subject: [pypy-svn] r53510 - pypy/dist/pypy/doc/discussion Message-ID: <20080407092441.0915716A5EC@codespeak.net> Author: antocuni Date: Mon Apr 7 11:24:39 2008 New Revision: 53510 Added: pypy/dist/pypy/doc/discussion/list_comprehension_ootype.txt (contents, props changed) Log: save this conversation not to forget in the future Added: pypy/dist/pypy/doc/discussion/list_comprehension_ootype.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/list_comprehension_ootype.txt Mon Apr 7 11:24:39 2008 @@ -0,0 +1,58 @@ + I think it's nearly impossible to implement the hint "fence" efficiently + ouch + that's why test_simplify is failing at the moment + what is the problem btw? + even in lltype, the implementation is along the lines of + make a fixed list of length 'fence' + and at the end if less items have been added + make a copy of the list + I think 'fence' also means 'I promize no one else has seen this list yet' + arigato: I was referring mainly to ll_list2fixed_exact, which doesn't do any copy +* arigato tries to remember +* antocuni tries to understand :-) + lltype gets good results using a subtle interplay of hints and the backendopt malloc removal + in other words, a hack + roughly speaking yes + while the list is being built, it is varsized, so it is a GcStruct pointing to a GcArray + but malloc removal gets rid of the GcStruct + so all that's left is the GcArray that is pre-allocated for exactly the right size + and when it escapes the loop, turning this GcArray into a fixed-sized list is a no-op + ah + for now, on ootype you'll have to keep the varsized list, I suppose + then, exactlength or not, the fence operation needs to copy it into a fixedsized array + looks a bit wasteful :-( + are we sure this is an optimization? + no + I think that for now the simplest thing to do is to disable detect_list_comprehension for ootype + not completely nice + in theory this is an annotation phase, so it comes before we chose lltype vs ootype + the problem is that the result of hint is annotated as a fixed size list, so the corresponding repr will be chosen + and then we need a way to convert from ootype.List to ootype.Array, which is not cheap + yes + if we want good results, we could try to mimic the lltype behavior + we could somehow flag the annotation of the temporary varsized-list + so that ootype can pick a 3rd kind of repr for it + which would be a bit like ootype: a Record of an ootype.Array and a current length + this is not so horrible because it needs only to support the append() method, nothing else + (plus of course the hints added by simplify.py) + I see + and it's an append_noresize() method + i.e. we are sure that there is still enough space in the ootype.Array + right + so it's even easy to implement + and cheap + yes, probably + how much speed did we gain with that optimization on lltype? + I think it's not really useful for PyPy + but I wrote it when we were working on the jit + because rtimeshifter.py & co. create small lists all the time + I didn't measure anything though + (so, it was a quite un-scientific experiment :-) + so, I guess we could mark is as TODO + I don't really feel like doing it now, especially if it won't bring any speed improvement :-) + fine :-) + ah, it seems that there is even already a flag on the varsized list annotation + yes, it's used by lltypesystem.rlist to choose if the append() method can be implemented with ll_append_noresize or not + so in ootypesystem.rlist it could be used to choose this special repr + arigato: you mean hint_maxlength? + yes From antocuni at codespeak.net Mon Apr 7 11:48:49 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 11:48:49 +0200 (CEST) Subject: [pypy-svn] r53512 - in pypy/dist/pypy: config rpython/ootypesystem translator/test Message-ID: <20080407094849.2614116A640@codespeak.net> Author: antocuni Date: Mon Apr 7 11:48:48 2008 New Revision: 53512 Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/rpython/ootypesystem/rlist.py pypy/dist/pypy/translator/test/test_simplify.py Log: disable list comprehension detection for ootype. See doc/discussion/list_comprehension_ootype.txt Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Mon Apr 7 11:48:48 2008 @@ -21,6 +21,7 @@ ("translation.backendopt.constfold", False), ("translation.backendopt.heap2stack", False), ("translation.backendopt.clever_malloc_removal", False), + ("translation.list_comprehension_operations", False), ] }), ChoiceOption("backend", "Backend to use for code generation", Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Mon Apr 7 11:48:48 2008 @@ -51,12 +51,9 @@ def rtype_hint(self, hop): hints = hop.args_s[-1].const - if 'maxlength' in hints: - v_list = hop.inputarg(self, arg=0) - # XXX give a hint to pre-allocate the list (see lltypesystem/rlist) - return v_list - if 'fence' in hints: - return hop.inputarg(self, arg=0) + if 'maxlength' in hints or 'fence' in hints: + # see doc/discussion/list_comprehension_ootype.txt + assert False, 'TODO' return AbstractBaseListRepr.rtype_hint(self, hop) Modified: pypy/dist/pypy/translator/test/test_simplify.py ============================================================================== --- pypy/dist/pypy/translator/test/test_simplify.py (original) +++ pypy/dist/pypy/translator/test/test_simplify.py Mon Apr 7 11:48:48 2008 @@ -337,5 +337,7 @@ res = interp.eval_graph(graph, [4, 4]) assert res == 1 + 4 * 17 + 4 * 17 -class TestOOSpecializeListComprehension(TestLLSpecializeListComprehension): - typesystem = 'ootype' +## TODO: maxlength and fence hints are not supported by ootype +## see doc/discussion/list_comprehension_ootype.txt +##class TestOOSpecializeListComprehension(TestLLSpecializeListComprehension): +## typesystem = 'ootype' From antocuni at codespeak.net Mon Apr 7 11:50:23 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 11:50:23 +0200 (CEST) Subject: [pypy-svn] r53513 - in pypy/dist/pypy/rpython: lltypesystem test Message-ID: <20080407095023.4376316A640@codespeak.net> Author: antocuni Date: Mon Apr 7 11:50:22 2008 New Revision: 53513 Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: kill unused code Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Mon Apr 7 11:50:22 2008 @@ -56,10 +56,6 @@ self.listitem = listitem self.list_cache = {} # setup() needs to be called to finish this initialization -## self.list_builder = ListBuilder(self) - -## def _setup_repr_final(self): -## self.list_builder.setup() def null_const(self): return nullptr(self.LIST) @@ -79,93 +75,12 @@ "ll_newemptylist": ll_fixed_newemptylist, "ll_length": ll_fixed_length, "ll_items": ll_fixed_items, - ##"list_builder": self.list_builder, "ITEM": ITEM, "ll_getitem_fast": ll_fixed_getitem_fast, "ll_setitem_fast": ll_fixed_setitem_fast, })) return ITEMARRAY -##class ListBuilder(object): -## """Interface to allow lazy list building by the JIT.""" - -## def __init__(self, list_repr): -## # This should not keep a reference to the RTyper, even indirectly via -## # the list_repr. So tmp_list_repr is replaced by None in setup(). -## self.tmp_list_repr = list_repr - -## def setup(self): -## # Precompute the c_newitem and c_setitem_nonneg function pointers, -## # needed below. -## list_repr = self.tmp_list_repr -## if list_repr is None: -## return # already set up -## self.tmp_list_repr = None -## if list_repr.rtyper is None: -## return # only for test_rlist, which doesn't need this anyway - -## LIST = list_repr.LIST -## LISTPTR = list_repr.lowleveltype -## ITEM = list_repr.item_repr.lowleveltype -## self.LIST = LIST -## self.LISTPTR = LISTPTR - -## argtypes = [Signed] -## newlist_ptr = list_repr.rtyper.annotate_helper_fn(LIST.ll_newlist, -## argtypes) - -## bk = list_repr.rtyper.annotator.bookkeeper -## argtypes = [bk.immutablevalue(dum_nocheck), LISTPTR, Signed, ITEM] -## setitem_nonneg_ptr = list_repr.rtyper.annotate_helper_fn( -## ll_setitem_nonneg, argtypes) -## #self.c_dum_nocheck = inputconst(Void, dum_nocheck) -## #self.c_LIST = inputconst(Void, self.LIST) - -## def build_newlist(llops, length): -## c_newlist = llops.genconst(newlist_ptr) -## c_len = llops.genconst(length) -## c_LIST = llops.genvoidconst(LIST) -## return llops.genop('direct_call', -## [c_newlist, c_LIST, c_len], -## llops.constTYPE(LISTPTR)) - -## def build_setitem(llops, v_list, index, v_item): -## c_setitem_nonneg = llops.genconst(setitem_nonneg_ptr) -## c_i = llops.genconst(index) -## llops.genop('direct_call', [c_setitem_nonneg, -## llops.genvoidconst(dum_nocheck), -## v_list, c_i, v_item]) - -## self.build_newlist = build_newlist -## self.build_setitem = build_setitem - -## def build(self, llops, items_v): -## """Make the operations that would build a list containing the -## provided items.""" -## v_list = self.build_newlist(llops, len(items_v)) -## for i, v in enumerate(items_v): -## self.build_setitem(llops, v_list, i, v) -## return v_list - -## def getlistptr(self): -## list_repr = self.tmp_list_repr -## if list_repr is not None: -## list_repr.setup() -## return list_repr.lowleveltype -## else: -## return self.LISTPTR - -## def __eq__(self, other): -## if not isinstance(other, ListBuilder): -## return False -## return self.getlistptr() == other.getlistptr() - -## def __ne__(self, other): -## return not (self == other) - -## def __hash__(self): -## return 1 # bad but not used alone - class __extend__(pairtype(BaseListRepr, BaseListRepr)): def rtype_is_((r_lst1, r_lst2), hop): @@ -194,7 +109,6 @@ "ll_newemptylist": ll_newemptylist, "ll_length": ll_length, "ll_items": ll_items, - ##"list_builder": self.list_builder, "ITEM": ITEM, "ll_getitem_fast": ll_getitem_fast, "ll_setitem_fast": ll_setitem_fast, 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 Mon Apr 7 11:50:22 2008 @@ -188,47 +188,6 @@ def _freeze_(self): return True -##def test_list_builder(): -## def fixed_size_case(): -## return [42] -## def variable_size_case(): -## lst = [] -## lst.append(42) -## return lst - -## from pypy.rpython.rtyper import LowLevelOpList - -## for fn in [fixed_size_case, variable_size_case]: -## t = TranslationContext() -## t.buildannotator().build_types(fn, []) -## t.buildrtyper().specialize() -## LIST = t.graphs[0].getreturnvar().concretetype.TO -## llop = LowLevelOpList(None) -## v0 = Constant(42) -## v0.concretetype = Signed -## v1 = Variable() -## v1.concretetype = Signed -## vr = LIST.list_builder.build(llop, [v0, v1]) -## assert len(llop) == 3 -## assert llop[0].opname == 'direct_call' -## assert len(llop[0].args) == 3 -## assert llop[0].args[1].concretetype == Void -## assert llop[0].args[1].value == LIST -## assert llop[0].args[2].concretetype == Signed -## assert llop[0].args[2].value == 2 -## assert llop[0].result is vr -## for op, i, vi in [(llop[1], 0, v0), (llop[2], 1, v1)]: -## assert op.opname == 'direct_call' -## assert len(op.args) == 5 -## assert op.args[1].value is dum_nocheck -## assert op.args[2] is vr -## assert op.args[3].concretetype == Signed -## assert op.args[3].value == i -## assert op.args[4] is vi -## assert op.result.concretetype is Void - - - class BaseTestRlist(BaseRtypingTest): From pedronis at codespeak.net Mon Apr 7 12:24:40 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 7 Apr 2008 12:24:40 +0200 (CEST) Subject: [pypy-svn] r53514 - pypy/dist/pypy/doc Message-ID: <20080407102440.05B8B16A5BC@codespeak.net> Author: pedronis Date: Mon Apr 7 12:24:39 2008 New Revision: 53514 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: progress toward finalizing the test and examples sections Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Mon Apr 7 12:24:39 2008 @@ -95,7 +95,8 @@ http://codespeak.net/svn/pypy/tag/ctypes-stable XXX make the tag -The various tests can be run on Linux. +The various tests and later examples can be run on x86-32 Linux. We tried them +on an up-to-date Ubuntu 7.10 x86-32 system. If one goes inside the checkout it is possible to run ``_rawffi`` tests with:: @@ -110,7 +111,7 @@ To run the test suite a compiled pypy-c is required with the proper configuration. To build the required pypy-c one should inside the checkout:: $ cd pypy/translator/goal - $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --withmod-_rawffi + $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --withmod-_rawffi --allworkingmodules this should produce a pypy-c executable in the ``goal`` directory. @@ -121,41 +122,51 @@ There should be 255 passed and 36 skipped tests. -Running example code -===================== +Running application examples +============================== -XXX not reviewed or tried yet +`pyglet`_ is known to run. We had some success also with pygame-ctypes and a snapshot of the experimental pysqlite-ctypes, both of these are not actively maintained. We will only describe how to run the pyglet examples. -You need a translation with ``--withmod-_rawffi`` in order to run any -ctypes code. For most examples ``--allworkingmodules`` translation option -also makes sense. Known applications to run are `pysqlite-ctypes`_ and -`pyglet`_. As of March 2008, from pysqlite all tests passes except one -that relies on __del__ being called immediately. From pyglet, the following -examples work: +pyglet +------- + +We tried pyglet checking it out from its repository at revision 1984. +For convenience a tarball of the checkout can also be found at: + +http://codespeak.net/~pedronis/pyglet-r1984.tgz + +From pyglet, the following examples are known to work: - opengl.py - multiple_windows.py - events.py - - window_platform_event.py - - fixed_resolution.py - html_label.py - - media_player.py - timer.py + - window_platform_event.py + - fixed_resolution.py -The following don't work: +The pypy-c translated to run the ctypes tests can be used to run the pyglet examples as well. They can be run like e.g.:: + + $ cd pyglet/ + $ PYTHONPATH=. ../ctypes-stable/pypy/translator/goal/pypy-c examples/opengl.py + + +they usually should be terminated with ctrl-c. Refer to the their doc strings for details about how they should behave. + +The following examples don't work for reasons independent from ctypes: - - fixed_resolution.py needs PIL - image_convert.py needs PIL - image_display.py needs PIL - astraea/astraea.py needs PIL - - video.py (but didn't work for me on CPython either) - - soundscape needs avbin -The `stress tests`_ of Johnathan Hartley is also working. +We did not try the following examples: + + - media_player.py needs avbin or at least a proper sound card setup for + .wav files + - video.py needs avbin + - soundscape needs avbin -.. _`pysqlite-ctypes`: http://XXX-link .. _`pyglet`: http://pyglet.org/ -.. _`stress tests`: http://tartley.com/?p=264 ctypes configure From pedronis at codespeak.net Mon Apr 7 13:38:36 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 7 Apr 2008 13:38:36 +0200 (CEST) Subject: [pypy-svn] r53516 - pypy/dist/pypy/doc Message-ID: <20080407113836.06E3316A154@codespeak.net> Author: pedronis Date: Mon Apr 7 13:38:34 2008 New Revision: 53516 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: rephrase Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Mon Apr 7 13:38:34 2008 @@ -125,7 +125,7 @@ Running application examples ============================== -`pyglet`_ is known to run. We had some success also with pygame-ctypes and a snapshot of the experimental pysqlite-ctypes, both of these are not actively maintained. We will only describe how to run the pyglet examples. +`pyglet`_ is known to run. We had some success also with pygame-ctypes which is not maintained anymore and with a snapshot of the experimental pysqlite-ctypes. We will only describe how to run the pyglet examples. pyglet ------- From pedronis at codespeak.net Mon Apr 7 13:39:20 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 7 Apr 2008 13:39:20 +0200 (CEST) Subject: [pypy-svn] r53517 - pypy/dist/pypy/doc Message-ID: <20080407113920.2D6C616A13A@codespeak.net> Author: pedronis Date: Mon Apr 7 13:39:19 2008 New Revision: 53517 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: clarify that is is a tag Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Mon Apr 7 13:39:19 2008 @@ -91,7 +91,7 @@ Getting the code and test suites ================================= -A stable revision of PyPy containing the ctypes implementation can be checked out with subversion from: +A stable revision of PyPy containing the ctypes implementation can be checked out with subversion from the tag: http://codespeak.net/svn/pypy/tag/ctypes-stable XXX make the tag From pedronis at codespeak.net Mon Apr 7 13:42:21 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 7 Apr 2008 13:42:21 +0200 (CEST) Subject: [pypy-svn] r53518 - pypy/dist/pypy/doc Message-ID: <20080407114221.9E82416A457@codespeak.net> Author: pedronis Date: Mon Apr 7 13:42:20 2008 New Revision: 53518 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: repeat this here too Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Mon Apr 7 13:42:20 2008 @@ -67,7 +67,7 @@ interface require more object allocations and copying than strictly necessary, this too could be improved. -The implementation was developed and has only been tested on Linux. +The implementation was developed and has only been tested on x86-32 Linux. Here is a list of the limitations and missing features of the current implementation: From pedronis at codespeak.net Mon Apr 7 14:13:50 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 7 Apr 2008 14:13:50 +0200 (CEST) Subject: [pypy-svn] r53520 - in pypy/branch/ctypes-stable/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20080407121350.8030E16A472@codespeak.net> Author: pedronis Date: Mon Apr 7 14:13:45 2008 New Revision: 53520 Modified: pypy/branch/ctypes-stable/pypy/lib/_ctypes/pointer.py pypy/branch/ctypes-stable/pypy/lib/app_test/ctypes_tests/test_parameters.py Log: ctypes pointers don't support comparison, tweak the test instead to be less implementation specific Modified: pypy/branch/ctypes-stable/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/ctypes-stable/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/ctypes-stable/pypy/lib/_ctypes/pointer.py Mon Apr 7 14:13:45 2008 @@ -106,12 +106,6 @@ contents = property(getcontents, setcontents) - def __eq__(self, other): - return self._buffer[0] == other - - def __ne__(self, other): - return not self == other - def _cast_addr(obj, _, tp): if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()): raise TypeError("cast() argument 2 must be a pointer type, not %s" Modified: pypy/branch/ctypes-stable/pypy/lib/app_test/ctypes_tests/test_parameters.py ============================================================================== --- pypy/branch/ctypes-stable/pypy/lib/app_test/ctypes_tests/test_parameters.py (original) +++ pypy/branch/ctypes-stable/pypy/lib/app_test/ctypes_tests/test_parameters.py Mon Apr 7 14:13:45 2008 @@ -100,7 +100,7 @@ assert x.contents.value == 42 assert LPINT(c_int(42)).contents.value == 42 - assert LPINT.from_param(None) == 0 + assert not LPINT.from_param(None) if c_int != c_long: raises(TypeError, LPINT.from_param, pointer(c_long(42))) From antocuni at codespeak.net Mon Apr 7 14:21:59 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 14:21:59 +0200 (CEST) Subject: [pypy-svn] r53521 - pypy/dist/pypy/doc/config Message-ID: <20080407122159.5DC4216A4A3@codespeak.net> Author: antocuni Date: Mon Apr 7 14:21:50 2008 New Revision: 53521 Added: pypy/dist/pypy/doc/config/objspace.usemodules._minimal_curses.txt - copied unchanged from r53520, pypy/dist/pypy/doc/config/objspace.usemodules._curses.txt Removed: pypy/dist/pypy/doc/config/objspace.usemodules._curses.txt Log: rename *_curses.txt to *._minimal_curses.txt to make the test happy From antocuni at codespeak.net Mon Apr 7 14:32:54 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 14:32:54 +0200 (CEST) Subject: [pypy-svn] r53522 - pypy/dist/pypy/translator/oosupport/test_template Message-ID: <20080407123254.C461E169E73@codespeak.net> Author: antocuni Date: Mon Apr 7 14:32:50 2008 New Revision: 53522 Modified: pypy/dist/pypy/translator/oosupport/test_template/string.py Log: skip this test in gencli and genjvm, it's too much trouble to make it working Modified: pypy/dist/pypy/translator/oosupport/test_template/string.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/test_template/string.py (original) +++ pypy/dist/pypy/translator/oosupport/test_template/string.py Mon Apr 7 14:32:50 2008 @@ -33,3 +33,6 @@ def fn(answer): return 'the answer is %s' % answer assert self.ll_to_string(self.interpret(fn, [42])) == 'the answer is 42' + + def test_prebuilt_ll_strings(self): + py.test.skip("The testing framework doesn't support returning low level strings") From antocuni at codespeak.net Mon Apr 7 14:48:28 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 14:48:28 +0200 (CEST) Subject: [pypy-svn] r53523 - pypy/dist/pypy/config Message-ID: <20080407124828.69F08169E21@codespeak.net> Author: antocuni Date: Mon Apr 7 14:48:27 2008 New Revision: 53523 Modified: pypy/dist/pypy/config/pypyoption.py Log: readline is not in workingmodules anymore Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Apr 7 14:48:27 2008 @@ -30,7 +30,6 @@ if sys.platform == "win32": del working_modules["fcntl"] - del working_modules["readline"] del working_modules["crypt"] del working_modules["termios"] del working_modules["_rawffi"] From antocuni at codespeak.net Mon Apr 7 14:58:42 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 14:58:42 +0200 (CEST) Subject: [pypy-svn] r53524 - in pypy/dist/pypy: rpython/test translator/cli/src translator/cli/test Message-ID: <20080407125842.721F7169E41@codespeak.net> Author: antocuni Date: Mon Apr 7 14:58:41 2008 New Revision: 53524 Modified: pypy/dist/pypy/rpython/test/test_rfloat.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_float.py Log: fix test_float2str for cli Modified: pypy/dist/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rfloat.py (original) +++ pypy/dist/pypy/rpython/test/test_rfloat.py Mon Apr 7 14:58:41 2008 @@ -36,7 +36,11 @@ print 'BINARY_OPERATIONS:', opname class BaseTestRfloat(BaseRtypingTest): - + + inf = 'inf' + minus_inf = '-inf' + nan = 'nan' + def test_float2str(self): def fn(f): return str(f) @@ -48,11 +52,11 @@ inf = 1e200 * 1e200 nan = inf/inf res = self.interpret(fn, [inf]) - assert self.ll_to_string(res) == 'inf' + assert self.ll_to_string(res) == self.inf res = self.interpret(fn, [-inf]) - assert self.ll_to_string(res) == '-inf' + assert self.ll_to_string(res) == self.minus_inf res = self.interpret(fn, [nan]) - assert self.ll_to_string(res) == 'nan' + assert self.ll_to_string(res) == self.nan def test_string_mod_float(self): def fn(f): 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 Mon Apr 7 14:58:41 2008 @@ -68,6 +68,20 @@ } } + public class Convert { + public static double ToDouble(string s) + { + if (s == "inf") + return Double.PositiveInfinity; + else if (s == "-inf") + return Double.NegativeInfinity; + else if (s == "nan") + return Double.NaN; + else + return System.Convert.ToDouble(s); + } + } + public delegate int DelegateType_int__int_1(int a); public delegate int DelegateType_int__int_2(int a, int b); public delegate int DelegateType_int__int_3(int a, int b, int c); 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 Mon Apr 7 14:58:41 2008 @@ -70,8 +70,7 @@ ilasm.opcode('ldc.i4 %d' % i) ilasm.opcode('ldelem.ref') arg_type, arg_var = self.cts.llvar_to_cts(arg) - ilasm.call('%s class [mscorlib]System.Convert::%s(string)' % - (arg_type, self.__convert_method(arg_type))) + self.__call_convert_method(ilasm, arg_type) # call the function and convert the result to a string containing a valid python expression ilasm.call(self.cts.graph_to_signature(self.graph)) @@ -118,6 +117,13 @@ ilasm.end_function() self.db.pending_function(self.graph) + def __call_convert_method(self, ilasm, arg_type): + if arg_type == CTS.types.float64: + ilasm.call('float64 class [pypylib]pypy.test.Convert::ToDouble(string)') + else: + ilasm.call('%s class [mscorlib]System.Convert::%s(string)' % + (arg_type, self.__convert_method(arg_type))) + def __convert_method(self, arg_type): _conv = { CTS.types.int32: 'ToInt32', @@ -125,7 +131,6 @@ CTS.types.int64: 'ToInt64', CTS.types.uint64: 'ToUInt64', CTS.types.bool: 'ToBoolean', - CTS.types.float64: 'ToDouble', CTS.types.char: 'ToChar', } 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 Mon Apr 7 14:58:41 2008 @@ -3,6 +3,11 @@ from pypy.rpython.test.test_rfloat import BaseTestRfloat class TestCliFloat(CliTest, BaseTestRfloat): + + inf = 'Infinity' + minus_inf = '-Infinity' + nan = 'NaN' + def test_parse_float(self): ex = ['', ' ', '0', '1', '-1.5', '1.5E2', '2.5e-1', ' 0 ', '?'] def fn(i): From antocuni at codespeak.net Mon Apr 7 15:08:15 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 7 Apr 2008 15:08:15 +0200 (CEST) Subject: [pypy-svn] r53525 - pypy/dist/pypy/translator Message-ID: <20080407130815.16D6616A257@codespeak.net> Author: antocuni Date: Mon Apr 7 15:08:14 2008 New Revision: 53525 Modified: pypy/dist/pypy/translator/driver.py Log: be more relaxed when checking uname Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon Apr 7 15:08:14 2008 @@ -666,7 +666,7 @@ f = file(newexename, 'w') f.write("""#!/bin/bash LEDIT=`type -p ledit` -if [ `uname -s` = 'Cygwin' ]; then MONO=; else MONO=mono; fi +if uname -s | grep -iq Cygwin ; then MONO=; else MONO=mono; fi $LEDIT $MONO "$(dirname $0)/$(basename $0)-data/%s" "$@" # XXX doesn't work if it's placed in PATH """ % main_exe_name) f.close() From fijal at codespeak.net Mon Apr 7 18:47:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 18:47:32 +0200 (CEST) Subject: [pypy-svn] r53531 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407164732.AAE04168576@codespeak.net> Author: fijal Date: Mon Apr 7 18:47:32 2008 New Revision: 53531 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Fix test method_call_promote. I promise I'll run tests all the time, I promise I'll run tests all the time, I promise I'll run tests all the time, ... Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 18:47:32 2008 @@ -294,9 +294,9 @@ return genmethod(gv_arg) def genop_getfield(self, (offset, fieldsize, kindtoken), gv_ptr): - assert fieldsize != 2 self.mc.MOV(edx, gv_ptr.operand(self)) - return self.newvarfromaddr(kindtoken, (edx, None, 0, offset)) + return self.newvarfromaddr(kindtoken, (edx, None, 0, offset), + fieldsize) if fieldsize == WORD: op = mem(edx, offset) @@ -362,7 +362,7 @@ self.mc.MOV(edx, gv_ptr.operand(self)) _, _, itemsize, kindtoken = arraytoken addr = self._compute_itemaddr(edx, arraytoken, gv_index) - return self.newvarfromaddr(kindtoken, addr) + return self.newvarfromaddr(kindtoken, addr, itemsize) def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index): self.mc.MOV(edx, gv_ptr.operand(self)) @@ -565,10 +565,19 @@ raise NotImplementedError("Return float var not on fp stack") return res - def newvarfromaddr(self, kindtoken, addr): + def newvarfromaddr(self, kindtoken, addr, size): # XXX probably we can still do something here with unrolling # iterable, but let's not be too smart... if kindtoken == 'i': + # XXX kind of a hack + if size == 1: + self.mc.MOVZX(eax, self.mem_access8(addr)) + return self.returnintvar(eax) + elif size == 2: + # XXX never tested + self.mc.MOV(eax, self.mem_access(addr)) + self.mc.o16() + return self.returnintvar(eax) return self.returnintvar(self.mem_access(addr)) elif kindtoken == 'a': return self.returnaddrvar(self.mem_access(addr)) From arigo at codespeak.net Mon Apr 7 19:26:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Apr 2008 19:26:11 +0200 (CEST) Subject: [pypy-svn] r53533 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407172611.709A616A0BB@codespeak.net> Author: arigo Date: Mon Apr 7 19:26:10 2008 New Revision: 53533 Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Log: Remove pointless function myfloat(). Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Mon Apr 7 19:26:10 2008 @@ -51,7 +51,7 @@ def as_int(self): return self.intval def as_float(self): - return myfloat(self.intval) + return float(self.intval) def as_str(self): return str(self.intval) @@ -202,7 +202,7 @@ try: v = IntBox(int(opcode)) except ValueError: - v = FloatBox(myfloat(opcode)) + v = FloatBox(float(opcode)) stack = Stack(v, stack) except ValueError: pass # ignore rest @@ -249,9 +249,6 @@ raise ValueError return n - at specialize.argtype(0) -def myfloat(i): - return float(i) # ------------------------------ From arigo at codespeak.net Mon Apr 7 19:29:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Apr 2008 19:29:09 +0200 (CEST) Subject: [pypy-svn] r53534 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407172909.04984169E6D@codespeak.net> Author: arigo Date: Mon Apr 7 19:29:09 2008 New Revision: 53534 Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Log: Revert r53533: myfloat is marked "don't look" by the hint-annotator policy. Modified: pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/tiny3_hotpath.py Mon Apr 7 19:29:09 2008 @@ -51,7 +51,7 @@ def as_int(self): return self.intval def as_float(self): - return float(self.intval) + return myfloat(self.intval) def as_str(self): return str(self.intval) @@ -202,7 +202,7 @@ try: v = IntBox(int(opcode)) except ValueError: - v = FloatBox(float(opcode)) + v = FloatBox(myfloat(opcode)) stack = Stack(v, stack) except ValueError: pass # ignore rest @@ -249,6 +249,9 @@ raise ValueError return n + at specialize.argtype(0) +def myfloat(i): + return float(i) # ------------------------------ From fijal at codespeak.net Mon Apr 7 19:52:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 19:52:48 +0200 (CEST) Subject: [pypy-svn] r53535 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407175248.40AC216A337@codespeak.net> Author: fijal Date: Mon Apr 7 19:52:46 2008 New Revision: 53535 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: ultra-paranoid asserts Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 19:52:46 2008 @@ -26,6 +26,7 @@ # ... <--- esp+4 # local var <--- esp # + assert stackpos >= 0 self.stackpos = stackpos def nonimmoperand(self, builder, tmpregister): Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 19:52:46 2008 @@ -464,8 +464,11 @@ if not isinstance(gv, Var) or gv.stackpos in seen: gv = args_gv[i] = gv.newvar(self) # remember the var's position in the stack + assert gv.stackpos >= 0 arg_positions.append(gv.stackpos) seen[gv.stackpos] = None + for pos in arg_positions: + assert pos >= 0 return Label(self.mc.tell(), arg_positions, self.stackdepth) def jump_if_false(self, gv_condition, args_gv): From fijal at codespeak.net Mon Apr 7 20:03:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 20:03:49 +0200 (CEST) Subject: [pypy-svn] r53536 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407180349.4EDFD16A28C@codespeak.net> Author: fijal Date: Mon Apr 7 20:03:47 2008 New Revision: 53536 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Log: Even more obscure hack :-/ Fixes segfault though Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 20:03:47 2008 @@ -202,12 +202,14 @@ if we_are_translated(): self.buf = lltype.malloc(FLOATBUF.TO, 1) self.buf[0] = floatval + self.is_pbc = False else: + self.is_pbc = True self.rawbuf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') self.rawbuf[0] = floatval def _compute_addr(self): - if we_are_translated(): + if not self.is_pbc: addr = llmemory.cast_ptr_to_adr(self.buf) + \ llmemory.itemoffsetof(FLOATBUF.TO, 0) return llmemory.cast_adr_to_int(addr) From arigo at codespeak.net Mon Apr 7 20:07:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Apr 2008 20:07:40 +0200 (CEST) Subject: [pypy-svn] r53538 - pypy/branch/jit-hotpath/pypy/rpython/lltypesystem Message-ID: <20080407180740.4EFB216A3FF@codespeak.net> Author: arigo Date: Mon Apr 7 20:07:39 2008 New Revision: 53538 Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py Log: Drop the exception path if the operation cannot raise. Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py Mon Apr 7 20:07:39 2008 @@ -122,7 +122,10 @@ def specialize_call(self, hop): op = self.instance # the LLOp object that was called args_v = [hop.inputarg(r, i+1) for i, r in enumerate(hop.args_r[1:])] - hop.exception_is_here() + if op.canraise: + hop.exception_is_here() + else: + hop.exception_cannot_occur() return hop.genop(op.opname, args_v, resulttype=hop.r_result.lowleveltype) From fijal at codespeak.net Mon Apr 7 20:19:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 20:19:00 +0200 (CEST) Subject: [pypy-svn] r53539 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407181900.8845516A3A3@codespeak.net> Author: fijal Date: Mon Apr 7 20:18:58 2008 New Revision: 53539 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: * fix annotation * compute stack depth correctly (it's return ADDRESS, not return VALUE) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 20:18:58 2008 @@ -197,6 +197,7 @@ SIZE = 2 # XXX hack for annotator buf = lltype.nullptr(FLOATBUF.TO) + is_pbc = False def __init__(self, floatval): if we_are_translated(): Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 20:18:58 2008 @@ -1247,9 +1247,7 @@ ofs = 0 for argtoken in arg_tokens: ofs += TOKEN_TO_SIZE[argtoken] - if rettoken != 'v': - return ofs + TOKEN_TO_SIZE[rettoken] - return ofs + return ofs + WORD def newgraph(self, sigtoken, name): arg_tokens, res_token = sigtoken From fijal at codespeak.net Mon Apr 7 21:13:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 21:13:20 +0200 (CEST) Subject: [pypy-svn] r53541 - in pypy/branch/jit-hotpath/pypy/jit/codegen/i386: . test Message-ID: <20080407191320.42EE616A120@codespeak.net> Author: fijal Date: Mon Apr 7 21:13:16 2008 New Revision: 53541 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/ri386setup.py pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: FNSTCW and special hacks for tests Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/ri386setup.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/i386/ri386setup.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/i386/ri386setup.py Mon Apr 7 21:13:16 2008 @@ -486,6 +486,9 @@ FILD = Instruction() FILD.mode1(MODRM, ['\xDB', orbyte(0<<3), modrm(1)]) +FNSTCW = Instruction() +FNSTCW.mode1(MODRM, ['\xD9', orbyte(7<<3), modrm(1)]) + # ------------------------- end of floating point ------------------------ UD2 = Instruction() # reserved as an illegal instruction Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_auto_encoding.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_auto_encoding.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_auto_encoding.py Mon Apr 7 21:13:16 2008 @@ -137,7 +137,8 @@ all = instr.as_all_suffixes for m, extra in args: if m in (i386.MODRM, i386.MODRM8) or all: - suffix = suffixes[sizes[m]] + suffix + if not instrname == 'FNSTCW': + suffix = suffixes[sizes[m]] + suffix following = "" if instr.indirect: suffix = "" @@ -190,7 +191,6 @@ def rec_test_all(instrname, modes, args=[]): if modes: m = modes[0] - # XXX evil hack if instrname.startswith('F') and m is i386.MODRM: lst = modrm_noreg_tests() else: From fijal at codespeak.net Mon Apr 7 21:24:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 21:24:24 +0200 (CEST) Subject: [pypy-svn] r53542 - in pypy/branch/jit-hotpath/pypy/jit/codegen: ia32 test Message-ID: <20080407192424.142B816A357@codespeak.net> Author: fijal Date: Mon Apr 7 21:24:23 2008 New Revision: 53542 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: cast_float_to_int (raising) + check Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 21:24:23 2008 @@ -285,12 +285,12 @@ @specialize.arg(1) def genraisingop2(self, opname, gv_arg1, gv_arg2): - genmethod = getattr(self, 'op_' + opname) + genmethod = getattr(self, 'op_raising_' + opname) return genmethod(gv_arg1, gv_arg2) @specialize.arg(1) def genraisingop1(self, opname, gv_arg): - genmethod = getattr(self, 'op_' + opname) + genmethod = getattr(self, 'op_raising_' + opname) return genmethod(gv_arg) def genop_getfield(self, (offset, fieldsize, kindtoken), gv_ptr): @@ -633,21 +633,21 @@ self.mc.ADD(eax, gv_y.operand(self)) return self.returnintvar(eax) - op_int_add_ovf = _create_ovf_two_version('op_int_add', 'O') + op_raising_int_add_ovf = _create_ovf_two_version('op_int_add', 'O') def op_int_sub(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.SUB(eax, gv_y.operand(self)) return self.returnintvar(eax) - op_int_sub_ovf = _create_ovf_two_version('op_int_sub', 'O') + op_raising_int_sub_ovf = _create_ovf_two_version('op_int_sub', 'O') def op_int_mul(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.IMUL(eax, gv_y.operand(self)) return self.returnintvar(eax) - op_int_mul_ovf = _create_ovf_two_version('op_int_mul', 'O') + op_raising_int_mul_ovf = _create_ovf_two_version('op_int_mul', 'O') def op_int_floordiv(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) @@ -717,7 +717,7 @@ self.mc.NEG(eax) return self.returnintvar(eax) - op_int_neg_ovf = _create_ovf_one_version('op_int_neg', 'O') + op_raising_int_neg_ovf = _create_ovf_one_version('op_int_neg', 'O') def op_int_abs(self, gv_x): # XXX cannot we employ fp unit to do that for us? :) @@ -730,7 +730,7 @@ self.mc.XOR(eax, edx) return self.returnintvar(eax) - op_int_abs_ovf = _create_ovf_one_version('op_int_abs', 'L') + op_raising_int_abs_ovf = _create_ovf_one_version('op_int_abs', 'L') def op_int_invert(self, gv_x): self.mc.MOV(eax, gv_x.operand(self)) @@ -942,14 +942,20 @@ return self._float_compare(gv_y, gv_x, 5) def op_cast_float_to_int(self, gv_x): - # XXX gcc is also checking something in control word self.mc.FLDL(gv_x.operand(self)) self.mc.SUB(esp, imm(WORD)) - self.stackdepth += 1 res = IntVar(self.stackdepth) + self.stackdepth += 1 self.mc.FISTP(res.operand(self)) return res + def op_raising_cast_float_to_int(self, gv_x): + # XXX think how to change it to bool + gv_res = self.op_cast_float_to_int(gv_x) + gv_cw = self.returnintvar(None) + self.mc.FNSTCW(gv_cw.operand(self)) + return gv_res, gv_cw + def op_cast_int_to_float(self, gv_x): # XXX gcc is also checking something in control word self.mc.FILD(gv_x.operand(self)) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Mon Apr 7 21:24:23 2008 @@ -1189,6 +1189,23 @@ res = fnptr(37) assert res == 42 + def test_cast_raising(self): + rgenop = self.RGenOp() + FUNC = lltype.FuncType([lltype.Float], lltype.Signed) + sigtoken = rgenop.sigToken(FUNC) + builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, 'cast_raising') + builder.start_writing() + + gv_x1, gv_flag = builder.genraisingop1('cast_float_to_int', gv_x) + + builder.finish_and_return(sigtoken, gv_x1) + builder.end() + + fnptr = self.cast_whatever(gv_fn, [lltype.Float], lltype.Signed) + + res = fnptr(3.4) + assert res == 3 + def test_float_adder(self): rgenop = self.RGenOp() gv_add_5 = make_float_adder(rgenop, 3.2) From fijal at codespeak.net Mon Apr 7 21:45:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 21:45:59 +0200 (CEST) Subject: [pypy-svn] r53544 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080407194559.D4C8816A42D@codespeak.net> Author: fijal Date: Mon Apr 7 21:45:59 2008 New Revision: 53544 Modified: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py Log: Make it directly runnable Modified: pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/tl/targettiny3hotpath.py Mon Apr 7 21:45:59 2008 @@ -60,3 +60,7 @@ compiler. """ return None, MyHintAnnotatorPolicy() + +if __name__ == '__main__': + import sys + entry_point(sys.argv) From fijal at codespeak.net Mon Apr 7 23:44:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 23:44:56 +0200 (CEST) Subject: [pypy-svn] r53548 - pypy/branch/jit-hotpath/pypy/interpreter Message-ID: <20080407214456.83A7616A2FB@codespeak.net> Author: fijal Date: Mon Apr 7 23:44:54 2008 New Revision: 53548 Modified: pypy/branch/jit-hotpath/pypy/interpreter/pyopcode.py Log: Don't try to handle NotImplementedError here Modified: pypy/branch/jit-hotpath/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/jit-hotpath/pypy/interpreter/pyopcode.py Mon Apr 7 23:44:54 2008 @@ -98,6 +98,10 @@ except MemoryError: next_instr = self.handle_asynchronous_error(ec, self.space.w_MemoryError) + except NotImplementedError, e: + # this one is a subclass of RuntimeError, but this only + # obscures reports (ie we got stack overflow instead of crash) + raise except RuntimeError, e: if we_are_translated(): # stack overflows should be the only kind of RuntimeErrors From fijal at codespeak.net Mon Apr 7 23:48:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 23:48:37 +0200 (CEST) Subject: [pypy-svn] r53549 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407214837.88A4916A2FD@codespeak.net> Author: fijal Date: Mon Apr 7 23:48:37 2008 New Revision: 53549 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: I didn't find any tests for that, but this is obviously missing Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 23:48:37 2008 @@ -41,6 +41,9 @@ def __repr__(self): return self.token + 'var@%d' % (self.stackpos,) + def getkind(self): + return self.token + repr = __repr__ class IntVar(Var): @@ -181,6 +184,9 @@ def repr(self): return "const=$%s" % (self.value,) + def getkind(self): + return self.token + class IntConst(Const): SIZE = 1 @@ -220,7 +226,7 @@ @specialize.arg(1) def revealconst(self, T): assert T is lltype.Float - if we_are_translated(): + if not self.is_pbc: return self.buf[0] else: return self.rawbuf[0] @@ -293,3 +299,10 @@ def repr(self): return "const=<0x%x>" % (llmemory.cast_adr_to_int(self.addr),) + +ZERO_CONST = { + 'a' : AddrConst(llmemory.NULL), + 'i' : IntConst(0), + 'b' : BoolConst(0), + 'f' : FloatConst(0.0) + } Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 23:48:37 2008 @@ -9,7 +9,8 @@ from pypy.rpython.annlowlevel import llhelper from pypy.jit.codegen.ia32.objmodel import IntVar, FloatVar, Var,\ BoolVar, IntConst, AddrConst, BoolConst, FloatConst,\ - LL_TO_GENVAR, TOKEN_TO_SIZE, token_to_genvar, WORD, AddrVar + LL_TO_GENVAR, TOKEN_TO_SIZE, token_to_genvar, WORD, AddrVar,\ + ZERO_CONST from pypy.jit.codegen.support import ctypes_mapping from ctypes import cast, c_void_p, POINTER @@ -1373,7 +1374,7 @@ @staticmethod @specialize.arg(1) def genzeroconst(kind): - return zero_const + return ZERO_CONST[kind] @staticmethod @specialize.arg(0) @@ -1404,4 +1405,3 @@ global_rgenop = RI386GenOp() RI386GenOp.constPrebuiltGlobal = global_rgenop.genconst -zero_const = AddrConst(llmemory.NULL) From fijal at codespeak.net Mon Apr 7 23:49:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 23:49:54 +0200 (CEST) Subject: [pypy-svn] r53550 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407214954.65EA716A2FB@codespeak.net> Author: fijal Date: Mon Apr 7 23:49:53 2008 New Revision: 53550 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: oops Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 23:49:53 2008 @@ -1372,7 +1372,7 @@ assert 0, "XXX not implemented" @staticmethod - @specialize.arg(1) + @specialize.arg(0) def genzeroconst(kind): return ZERO_CONST[kind] From fijal at codespeak.net Mon Apr 7 23:52:40 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 23:52:40 +0200 (CEST) Subject: [pypy-svn] r53551 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407215240.1355116A2FB@codespeak.net> Author: fijal Date: Mon Apr 7 23:52:39 2008 New Revision: 53551 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Log: Don't try to specialize this for now.... Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Mon Apr 7 23:52:39 2008 @@ -1372,7 +1372,6 @@ assert 0, "XXX not implemented" @staticmethod - @specialize.arg(0) def genzeroconst(kind): return ZERO_CONST[kind] From fijal at codespeak.net Mon Apr 7 23:54:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 7 Apr 2008 23:54:48 +0200 (CEST) Subject: [pypy-svn] r53552 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32 Message-ID: <20080407215448.EE1ED16A2FB@codespeak.net> Author: fijal Date: Mon Apr 7 23:54:48 2008 New Revision: 53552 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Log: attach tokens to constants as well Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/objmodel.py Mon Apr 7 23:54:48 2008 @@ -151,6 +151,7 @@ class Const(GenConst): + token = "x" def __init__(self, value): self.value = value @@ -189,6 +190,7 @@ class IntConst(Const): SIZE = 1 + token = "i" def newvar(self, builder): return builder.returnintvar(self.operand(builder)) @@ -204,6 +206,7 @@ # XXX hack for annotator buf = lltype.nullptr(FLOATBUF.TO) is_pbc = False + token = "f" def __init__(self, floatval): if we_are_translated(): @@ -253,6 +256,7 @@ class BoolConst(Const): SIZE = 1 + token = "b" def operand(self, builder): return imm8(self.value) @@ -272,6 +276,7 @@ class AddrConst(IntConst): SIZE = 1 + token = "a" def __init__(self, addr): self.addr = addr From pedronis at codespeak.net Tue Apr 8 00:03:59 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 8 Apr 2008 00:03:59 +0200 (CEST) Subject: [pypy-svn] r53554 - in pypy/branch/ctypes-stable/pypy/rlib: . test Message-ID: <20080407220359.DF9B016A308@codespeak.net> Author: pedronis Date: Tue Apr 8 00:03:58 2008 New Revision: 53554 Modified: pypy/branch/ctypes-stable/pypy/rlib/libffi.py pypy/branch/ctypes-stable/pypy/rlib/test/test_libffi.py Log: try to allocate closure memory through codebuf, libffi and _rawffi tests still pass but needs more testing and translation checking Modified: pypy/branch/ctypes-stable/pypy/rlib/libffi.py ============================================================================== --- pypy/branch/ctypes-stable/pypy/rlib/libffi.py (original) +++ pypy/branch/ctypes-stable/pypy/rlib/libffi.py Tue Apr 8 00:03:58 2008 @@ -49,6 +49,8 @@ ('type', rffi.USHORT), ('elements', FFI_TYPE_PP)]) + ffi_closure = rffi_platform.Struct('ffi_closure', []) + def add_simple_type(type_name): for name in ['size', 'alignment', 'type']: setattr(CConfig, type_name + '_' + name, @@ -119,8 +121,7 @@ FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=CConfig. _compilation_info_) -FFI_CLOSUREP = rffi.COpaquePtr('ffi_closure', compilation_info=CConfig. - _compilation_info_) +FFI_CLOSUREP = lltype.Ptr(cConfig.ffi_closure) VOIDPP = rffi.CArrayPtr(rffi.VOIDP) @@ -209,6 +210,39 @@ userdata = rffi.cast(USERDATA_P, ll_userdata) userdata.callback(ll_args, ll_res, userdata) +# heap for closures +from pypy.jit.codegen.i386 import codebuf_posix + +CHUNK = 4096 +CLOSURES = rffi.CArrayPtr(FFI_CLOSUREP.TO) + +class ClosureHeap(object): + + def __init__(self): + self.free_list = lltype.nullptr(rffi.VOIDP.TO) + + def _more(self): + chunk = rffi.cast(CLOSURES, codebuf_posix.alloc(CHUNK)) + count = CHUNK//rffi.sizeof(FFI_CLOSUREP.TO) + for i in range(count): + rffi.cast(rffi.VOIDPP, chunk)[0] = self.free_list + self.free_list = rffi.cast(rffi.VOIDP, chunk) + chunk = rffi.ptradd(chunk, 1) + + def alloc(self): + if not self.free_list: + self._more() + p = self.free_list + self.free_list = rffi.cast(rffi.VOIDPP, p)[0] + return rffi.cast(FFI_CLOSUREP, p) + + def free(self, p): + rffi.cast(rffi.VOIDPP, p)[0] = self.free_list + self.free_list = rffi.cast(rffi.VOIDP, p) + +closureHeap = ClosureHeap() + + class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) @@ -246,7 +280,7 @@ # it cannot be any kind of movable gc reference def __init__(self, argtypes, restype, func, additional_arg=0): AbstractFuncPtr.__init__(self, "callback", argtypes, restype) - self.ll_closure = lltype.malloc(FFI_CLOSUREP.TO, flavor='raw') + self.ll_closure = closureHeap.alloc() self.ll_userdata = lltype.malloc(USERDATA_P.TO, flavor='raw') self.ll_userdata.callback = rffi.llhelper(CALLBACK_TP, func) self.ll_userdata.addarg = additional_arg @@ -259,7 +293,7 @@ def __del__(self): AbstractFuncPtr.__del__(self) if self.ll_closure: - lltype.free(self.ll_closure, flavor='raw') + closureHeap.free(self.ll_closure) self.ll_closure = lltype.nullptr(FFI_CLOSUREP.TO) if self.ll_userdata: lltype.free(self.ll_userdata, flavor='raw') Modified: pypy/branch/ctypes-stable/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/branch/ctypes-stable/pypy/rlib/test/test_libffi.py (original) +++ pypy/branch/ctypes-stable/pypy/rlib/test/test_libffi.py Tue Apr 8 00:03:58 2008 @@ -109,6 +109,36 @@ del libc assert not ALLOCATED + def test_closure_heap(self): + ch = ClosureHeap() + + assert not ch.free_list + a = ch.alloc() + assert ch.free_list + b = ch.alloc() + + chunks = [a, b] + p = ch.free_list + while p: + chunks.append(p) + p = rffi.cast(rffi.VOIDPP, p)[0] + closure_size = rffi.sizeof(FFI_CLOSUREP.TO) + assert len(chunks) == CHUNK//closure_size + for i in range(len(chunks) -1 ): + s = rffi.cast(rffi.UINT, chunks[i+1]) + e = rffi.cast(rffi.UINT, chunks[i]) + assert (e-s) >= rffi.sizeof(FFI_CLOSUREP.TO) + + ch.free(a) + assert ch.free_list == rffi.cast(rffi.VOIDP, a) + snd = rffi.cast(rffi.VOIDPP, a)[0] + assert snd == chunks[2] + + ch.free(b) + assert ch.free_list == rffi.cast(rffi.VOIDP, b) + snd = rffi.cast(rffi.VOIDPP, b)[0] + assert snd == rffi.cast(rffi.VOIDP, a) + def test_callback(self): libc = CDLL('libc.so.6') qsort = libc.getpointer('qsort', [ffi_type_pointer, ffi_type_slong, From fijal at codespeak.net Tue Apr 8 00:06:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Apr 2008 00:06:10 +0200 (CEST) Subject: [pypy-svn] r53555 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080407220610.0091F16A307@codespeak.net> Author: fijal Date: Tue Apr 8 00:06:10 2008 New Revision: 53555 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Log: Complain louder than silent NotImplementedError Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Tue Apr 8 00:06:10 2008 @@ -6,6 +6,9 @@ from pypy.rpython.lltypesystem import lloperation debug_print = lloperation.llop.debug_print +class NotConstInAVlist(Exception): + pass + def TypeDesc(RGenOp, rtyper, exceptiondesc, LIST): if rtyper.type_system.name == 'lltypesystem': return LLTypeListTypeDesc(RGenOp, rtyper, exceptiondesc, LIST) @@ -60,8 +63,11 @@ box = item_boxes[i] if box is not None: gv_value = box_gv_reader(box) - v = gv_value.revealconst(LIST.ITEM) - l.ll_setitem_fast(i, v) + if gv_value.is_const: + v = gv_value.revealconst(LIST.ITEM) + l.ll_setitem_fast(i, v) + else: + raise NotConstInAVlist("Cannot put variable to a vlist") self.allocate = allocate self.populate = populate From cami at codespeak.net Tue Apr 8 00:46:35 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 8 Apr 2008 00:46:35 +0200 (CEST) Subject: [pypy-svn] r53556 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080407224635.5CF2116A0D0@codespeak.net> Author: cami Date: Tue Apr 8 00:46:33 2008 New Revision: 53556 Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Log: added separated register testfile improved tests added more flag tests completed several empty tests fixed opCode assignment bug in cpu fixed useCycles bug in registers call and handlePendingInterrupts still non working Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Tue Apr 8 00:46:33 2008 @@ -13,7 +13,7 @@ def set(self, value, useCycles=True): self.value = value & 0xFF - if (useCycles): + if useCycles: self.cpu.cycles -= 1 def get(self, useCycles=True): @@ -25,7 +25,7 @@ def sub(self, value, useCycles=True): self.set(self.get(useCycles)-value, useCycles) -# ___________________________________________________________________________ +# ------------------------------------------------------------------------------ class DoubleRegister(Register): def __init__(self, cpu, hi=None, lo=None, resetValue=None): @@ -54,7 +54,7 @@ self.setLo(lo, useCycles) def reset(self): - self.set(self.resetValue, None, False) + self.set(self.resetValue, None, useCycles=False) def setHi(self, hi=0, useCycles=True): self.hi.set(hi, useCycles) @@ -63,27 +63,31 @@ self.lo.set(lo, useCycles) def get(self, useCycles=True): - return (self.hi.get()<<8) + self.lo.get() + return (self.hi.get(useCycles)<<8) + self.lo.get(useCycles) def getHi(self, useCycles=True): - return self.hi.get() + return self.hi.get(useCycles) def getLo(self, useCycles=True): - return self.lo.get() + return self.lo.get(useCycles) def inc(self, useCycles=True): - self.set(self.get() +1) - self.cpu.cycles -= 1 + self.set(self.get(useCycles) +1, None, useCycles) + if useCycles: + self.cpu.cycles -= 1 def dec(self, useCycles=True): - self.set(self.get() - 1) - self.cpu.cycles -= 1 + self.set(self.get(useCycles) - 1, None, useCycles) + if useCycles: + self.cpu.cycles -= 1 def add(self, n=2, useCycles=True): - self.set(self.get() + n) - self.cpu.cycles -= 2 - + self.set(self.get(useCycles) + n, None, useCycles) + if useCycles: + self.cpu.cycles -= 2 +# ------------------------------------------------------------------------------ + class ImmediatePseudoRegister(object): def __init__(self, cpu, hl): self.cpu = cpu @@ -98,7 +102,9 @@ if not useCycles: self.cpu.cycles += 1 return self.cpu.read(self.hl.get(useCycles)) - + +# ------------------------------------------------------------------------------ + class FlagRegister(Register): def __init__(self, cpu): @@ -108,7 +114,7 @@ def reset(self, keepZ=False, keepN=False, keepH=False, keepC=False,\ keepP=False, keepS=False): if not keepZ: - self.zFlag = True + self.zFlag = False if not keepN: self.nFlag = False if not keepH: @@ -138,12 +144,12 @@ if useCycles: self.cpu.cycles -= 1 - def zeroFlagAdd(self, a, reset=False): + def zFlagCompare(self, a, reset=False): if (reset): self.reset() if isinstance(a, (Register)): a = a.get() - self.zFlag = (a==0) + self.zFlag = ((a & 0xFF) == 0) def cFlagAdd(self, s, compareAnd=0x01, reset=False): if (reset): @@ -167,7 +173,7 @@ if a < b: self.cFlag = True -# ___________________________________________________________________________ +# # ------------------------------------------------------------------------------ class CPU(object): """ @@ -207,6 +213,7 @@ def reset(self): self.resetRegisters() self.f.reset() + self.f.zFlag = True self.ime = False self.halted = False self.cycles = 0 @@ -329,8 +336,9 @@ def lowerPendingInterrupt(self): for flag in self.interrupt.interruptFlags: if flag.isPending(): - self.call(flag.callCode, disableIme=True) + self.call(flag.callCode, disableIME=True, useCycles=False) flag.setPending(False) + return # Execution def fetchExecute(self): @@ -371,14 +379,14 @@ self.popDoubleRegister(CPU.fetch, register) # Stack, 2 cycles - def push(self, data): - self.sp.dec() # 2 cycles - self.memory.write(self.sp.get(), data) + def push(self, data, useCycles=True): + self.sp.dec(useCycles) # 2 cycles + self.memory.write(self.sp.get(useCycles), data) # PUSH rr 4 cycles - def pushDoubleRegister(self, register): - self.push(register.getHi()) # 2 cycles - self.push(register.getLo()) # 2 cycles + def pushDoubleRegister(self, register, useCycles=True): + self.push(register.getHi(), useCycles) # 2 cycles + self.push(register.getLo(), useCycles) # 2 cycles # 1 cycle def pop(self): @@ -398,13 +406,14 @@ self.cycles += 1 # 4 cycles - def call(self, address, disableIME=False): + def call(self, address, disableIME=False, useCycles=True): if disableIME: self.ime = False - self.push(self.pc.getHi()) # 2 cycles - self.push(self.pc.getLo()) # 2 cycles - self.pc.set(address) # 1 cycle - self.cycles += 1 + self.push(self.pc.getHi(useCycles), useCycles) # 2 cycles + self.push(self.pc.getLo(useCycles), useCycles) # 2 cycles + self.pc.set(address, useCycles) # 1 cycle + if useCycles: + self.cycles += 2 # 1 cycle def ld(self, getter, setter): @@ -423,7 +432,7 @@ # ALU, 1 cycle def addA(self, getter, setter=None): added = (self.a.get() + getter()) & 0xFF - self.f.zeroFlagAdd(added, reset=True) + self.f.zFlagCompare(added, reset=True) self.f.hFlagCompare(added, self.a) self.f.cFlagCompare(added, self.a) self.a.set(added) # 1 cycle @@ -439,29 +448,30 @@ # 1 cycle def addWithCarry(self, getter, setter=None): - s = self.a.get() + getter(); + data = getter() + s = self.a.get() + data if self.f.cFlag: s +=1 - self.carryFlagFinish(getter, 0x10) - if s >= 0x100: - self.f.cFlag= True + self.carryFlagFinish(s,data) # 1 cycle def subtractWithCarry(self, getter, setter=None): - s = self.a.get() - getter(); + data = getter() + s = self.a.get() - data if self.f.cFlag: s -= 1 - self.carryFlagFinish(getter, 0x10) - if (s & 0xFF00) != 0: - self.f.cFlag = True + self.carryFlagFinish(s, data) self.f.nFlag = True - def carryFlagFinish(self, getter): + def carryFlagFinish(self, s, data): self.f.reset() - self.f.zeroFlagAdd(s) - if ((s ^ self.a.get() ^ getter()) & 0x10) != 0: + # set the hfalg if the 0x10 bit was affected + if ((s ^ self.a.get() ^ data) & 0x10) != 0: self.f.hFlag = True - self.a.set(s & 0xFF) # 1 cycle + if s >= 0x100: + self.f.cFlag= True + self.f.zFlagCompare(s) + self.a.set(s) # 1 cycle # 1 cycle def subtract(self, getter, setter=None): @@ -473,7 +483,7 @@ s = (self.a.get() - getter()) & 0xFF self.f.reset() self.f.nFlag = True - self.f.zeroFlagAdd(s) + self.f.zFlagCompare(s) self.hcFlagFinish(s) self.cycles -= 1 @@ -485,17 +495,17 @@ # 1 cycle def AND(self, getter, setter=None): self.a.set(self.a.get() & getter()) # 1 cycle - self.f.zeroFlagAdd(self.a, reset=True) + self.f.zFlagCompare(self.a, reset=True) # 1 cycle def XOR(self, getter, setter=None): self.a.set( self.a.get() ^ getter()) # 1 cycle - self.f.zeroFlagAdd(self.a, reset=True) + self.f.zFlagCompare(self.a, reset=True) # 1 cycle def OR(self, getter, setter=None): self.a.set(self.a.get() | getter()) # 1 cycle - self.f.zeroFlagAdd(self.a, reset=True) + self.f.zFlagCompare(self.a, reset=True) def incDoubleRegister(self, doubleRegister): doubleRegister.inc() @@ -516,7 +526,7 @@ def decIncFlagFinish(self, data, setter, compare): self.f.reset(keepC=True) - self.f.zeroFlagAdd(data) + self.f.zFlagCompare(data) if (data & 0x0F) == compare: self.f.hFlag = True setter(data) # 1 cycle @@ -579,14 +589,14 @@ # 2 cycles def flagsAndSetterFinish(self, s, setter, compareAnd=0x01): s &= 0xFF - self.f.zeroFlagAdd(s, reset=True) + self.f.zFlagCompare(s, reset=True) self.f.cFlagAdd(s, compareAnd) setter(s) # 1 cycle # 1 cycle def swap(self, getter, setter): s = ((getter() << 4) + (getter() >> 4)) & 0xFF - self.f.zeroFlagAdd(s, reset=True) + self.f.zFlagCompare(s, reset=True) setter(s) # 2 cycles @@ -709,7 +719,7 @@ self.f.reset(keepN=True) if delta >= 0x60: self.f.cFlag = True - self.f.zeroFlagAdd(self.a) + self.f.zFlagCompare(self.a) # INC rr def incDoubleRegister(self, register): @@ -812,8 +822,7 @@ # RETI 4 cycles def returnFormInterrupt(self): self.ret() # 4 cycles - self.enableInterrupts() - self.cycles += 1 + self.enableInterrupts() # 1 cycle # RST nn 4 cycles def restart(self, nn): @@ -827,8 +836,7 @@ # 1 cycle def enableInterrupts(self): self.ime = True - self.cycles -= 1 - self.execute(self.fetch()) + self.execute(self.fetch()) # 1 self.handlePendingInterrupt() # HALT/STOP @@ -875,7 +883,8 @@ opCode = 0x40 for storeRegister in GROUPED_REGISTERS: for loadRegister in GROUPED_REGISTERS: - opCodes.append((opCode, load_group_lambda(storeRegister, loadRegister))) + if loadRegister != CPU.getHLi or storeRegister != CPU.getHLi: + opCodes.append((opCode, load_group_lambda(storeRegister, loadRegister))) opCode += 1 return opCodes @@ -983,8 +992,7 @@ (0xA8, 0x01, CPU.XOR), (0xB0, 0x01, CPU.OR), (0xB8, 0x01, CPU.compareA), - (0x06, 0x08, CPU.fetchLoad), - (0x40, 0x01, CPU.resetBit, range(0, 8)) + (0x06, 0x08, CPU.fetchLoad) ] @@ -1013,8 +1021,8 @@ (0x28, 0x01, CPU.shiftRightArithmetic), (0x30, 0x01, CPU.swap), (0x38, 0x01, CPU.shiftWordRightLogical), - (0x40, 0x01, CPU.testBit, range(0, 8)), - (0xC0, 0x01, CPU.setBit, range(0, 8)), + (0x40, 0x01, CPU.testBit, range(0, 8)), + (0xC0, 0x01, CPU.setBit, range(0, 8)), (0x80, 0x01, CPU.resetBit, range(0, 8)) ] Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Tue Apr 8 00:46:33 2008 @@ -15,7 +15,7 @@ def isPending(self): return self._isPending - def setPending(self, _isPending): + def setPending(self, _isPending=True): self._isPending = _isPending Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Tue Apr 8 00:46:33 2008 @@ -2,6 +2,7 @@ from pypy.lang.gameboy.cpu import * from pypy.lang.gameboy.ram import * from pypy.lang.gameboy import * +from pypy.lang.gameboy.interrupt import * class Memory(object): def __init__(self): @@ -13,136 +14,24 @@ def read(self, address): return self.memory[address] -def get_cpu(): - cpu = CPU(None, Memory()) - cpu.setROM([0]*0xFFFF); - return cpu +global TEST_CPU -# ------------------------------------------------------------ -# TEST REGISTER -def test_register_constructor(): - register = Register(get_cpu()) - assert register.get() == 0 - value = 10 - register = Register(get_cpu(), value) - assert register.get() == value - -def test_register(): - register = Register(get_cpu()) - value = 2 - oldCycles = register.cpu.cycles - register.set(value) - assert register.get() == value - assert oldCycles-register.cpu.cycles == 1 - -def test_register_bounds(): - register = Register(get_cpu()) - value = 0x1234FF - register.set(value) - assert register.get() == 0xFF - -def test_reset(): - value = 0x12 - register = Register(get_cpu(), value) - register.set(value+1) - assert register.get() == value+1 - register.reset() - assert register.get() == value - -# ------------------------------------------------------------ -# TEST DOUBLE REGISTER +TEST_CPU = None +def get_cpu(new=False): + if new: + cpu = CPU(Interrupt(), Memory()) + cpu.setROM([0]*0xFFFF); + return cpu + global TEST_CPU + if TEST_CPU == None: + TEST_CPU = get_cpu(True) + TEST_CPU.reset() + return TEST_CPU -def test_double_register_constructor(): - cpu = get_cpu() - register = DoubleRegister(cpu) - assert register.get() == 0 - assert register.getHi() == 0 - assert register.getLo() == 0 - value = 0x1234 - reg1 = Register(cpu) - reg1.set(0x12) - reg2 = Register(cpu) - reg2.set(0x34) - register = DoubleRegister(cpu, reg1, reg2) - assert register.hi == reg1 - assert register.lo == reg2 - assert register.getHi() == reg1.get() - assert register.getLo() == reg2.get() - -def test_double_register(): - register = DoubleRegister(get_cpu()) - value = 0x1234 - oldCycles = register.cpu.cycles - register.set(value) - assert oldCycles-register.cpu.cycles == 1 - assert register.get() == value - -def test_double_register_bounds(): - register = DoubleRegister(get_cpu()) - value = 0xFFFF1234 - register.set(value) - assert register.get() == 0x1234 - -def test_double_register_hilo(): - register = DoubleRegister(get_cpu()) - value = 0x1234 - valueHi = 0x12 - valueLo = 0x34 - oldCycles = register.cpu.cycles - register.set(valueHi, valueLo) - assert oldCycles-register.cpu.cycles == 2 - assert register.getHi() == valueHi - assert register.getLo() == valueLo - assert register.get() == value - - valueHi = 0x56 - oldCycles = register.cpu.cycles - register.setHi(valueHi) - assert oldCycles-register.cpu.cycles == 1 - assert register.getHi() == valueHi - assert register.getLo() == valueLo - - valueLo = 0x78 - oldCycles = register.cpu.cycles - register.setLo(valueLo) - assert oldCycles-register.cpu.cycles == 1 - assert register.getHi() == valueHi - assert register.getLo() == valueLo - - -def test_double_register_methods(): - value = 0x1234 - register = DoubleRegister(get_cpu()) - register.set(value) - - oldCycles = register.cpu.cycles - register.inc() - assert oldCycles-register.cpu.cycles == 2 - assert register.get() == value+1 - - oldCycles = register.cpu.cycles - register.dec() - assert oldCycles-register.cpu.cycles == 2 - assert register.get() == value - - addValue = 0x1001 - oldCycles = register.cpu.cycles - register.add(addValue) - assert oldCycles-register.cpu.cycles == 3 - assert register.get() == value+addValue - - -def test_double_register_reset(): - value = 0x1234; - - register = DoubleRegister(get_cpu(), value) - register.set(value+1) - assert register.get() == value+1; - register.reset() - assert register.get() == value # ------------------------------------------------------------ # TEST CPU + def test_getters(): cpu = get_cpu() assert_default_registers(cpu) @@ -350,6 +239,13 @@ pc += 1 cpu.rom[pc] = value & 0xFF cpu.memory.write(pc, value & 0xFF) + +def test_prepare_for_fetch(): + cpu = get_cpu() + value = 0x12 + prepare_for_fetch(cpu, value+1, value) + assert cpu.fetch() == value + assert cpu.fetch() == value+1 def prepare_for_pop(cpu, value, valueLo=None): sp = cpu.sp.get() @@ -357,6 +253,13 @@ cpu.memory.write(sp, valueLo & 0xFF) sp += 1 cpu.memory.write(sp, value & 0xFF) + +def test_prepare_for_pop(): + cpu = get_cpu() + value = 0x12 + prepare_for_pop(cpu, value+1, value) + assert cpu.pop() == value + assert cpu.pop() == value+1 def set_registers(registers, value): #if registers is not list: @@ -794,6 +697,8 @@ cpu = get_cpu() value = 0x12 fValue = cpu.f.get() + cpu.f.nFlag = False + cpu.f.hFlag = False cpu.a.set(value) cycle_test(cpu, 0x2F, 1) assert_default_registers(cpu, a=value^0xFF, f=None) @@ -827,10 +732,11 @@ # halt def test_0x76(): - py.test.skip("test not completed yet") cpu = get_cpu() + cpu.cycles = 0xFF + cpu.ime = True assert cpu.halted == False - cycle_test(cpu, 0x76, 0) + cycle_test(cpu, 0x76, cpu.cycles) assert cpu.halted == True assert_default_registers(cpu) @@ -857,6 +763,21 @@ opCode += 0x01 +def test_add_flags(): + cpu = get_cpu() + + cpu.a.set(0) + cpu.b.set(0) + cpu.addA(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=True, hFlag=False) + + cpu.reset() + cpu.a.set(0x0F) + cpu.b.set(0x01) + cpu.addA(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=False, hFlag=True) + + # add_A_B to add_A_A def test_0x80_to_0x87(): cpu = get_cpu() @@ -879,9 +800,44 @@ value += 3 opCode += 0x01 + +def test_adc_flags(): + cpu = get_cpu() + b = cpu.b + a = cpu.a + + cpu.reset() + a.set(0) + b.set(0) + cpu.addWithCarry(b.get, b.set) + assert_default_registers(cpu, a=0, f=None) + assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False) + + cpu.reset() + a.set(0) + b.set(0) + cpu.f.cFlag = True + cpu.addWithCarry(b.get, b.set) + assert_default_registers(cpu, a=1, f=None) + assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=False) + + cpu.reset() + a.set(0xF0) + b.set(0xFF) + cpu.addWithCarry(b.get, b.set) + # overflow for a + assert_default_registers(cpu, a=0xEF, bc=None, f=None) + assert_default_flags(cpu, zFlag=False, cFlag=True, hFlag=False) + + cpu.reset() + a.set(0x0F) + b.set(0x01) + cpu.addWithCarry(b.get, b.set) + assert_default_registers(cpu, a=0x10, f=None, bc=None) + assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=True) + # adc_A_B to adx_A_A def test_0x88_to_0x8F(): - py.test.skip("need a full flag checker imlementation") cpu = get_cpu() opCode = 0x88 value = 0x12 @@ -891,10 +847,24 @@ cpu.a.set(value) register.set(value) numCycles= 1 - if add == cpu.hli: + if register == cpu.hli: numCycles = 2 cycle_test(cpu, opCode, numCycles) assert cpu.a.get() == 2*value + + cpu.reset() + cpu.f.cFlag = True + cpu.a.set(value-1) + register.set(value) + numCycles= 1 + if register == cpu.hli: + numCycles = 2 + cycle_test(cpu, opCode, numCycles) + if register == cpu.a: + assert cpu.a.get() == 2*value+1 + else: + assert cpu.a.get() == 2*value + value += 3 opCode += 0x01 @@ -916,10 +886,82 @@ value += 3 opCode += 0x01 +def test_sbc_flags(): + cpu = get_cpu() + b = cpu.b + a = cpu.a + value = 0xFF + + cpu.reset() + a.set(value) + b.set(value) + cpu.subtractWithCarry(b.get, b.set) + assert_default_registers(cpu, a=0, bc=None, f=None) + assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False, nFlag=True) + + cpu.reset() + a.set(value) + b.set(value-1) + cpu.f.cFlag = True + cpu.subtractWithCarry(b.get, b.set) + assert_default_registers(cpu, a=0, bc=None, f=None) + assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False, nFlag=True) + + cpu.reset() + a.set(0x20) + b.set(0x01) + cpu.subtractWithCarry(b.get, b.set) + # overflow for a + assert_default_registers(cpu, a=0x1F, bc=None, f=None) + assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=True, nFlag=True) + + # sbc_A_B to sbc_A_A -def test_0x98(): - pass +def test_0x98_0x9F(): + cpu = get_cpu() + opCode = 0x98 + value = 0x12 + registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] + for register in registers: + cpu.reset() + cpu.a.set(value) + register.set(value) + numCycles= 1 + if register == cpu.hli: + numCycles = 2 + cycle_test(cpu, opCode, numCycles) + assert cpu.a.get() == 0 + + cpu.reset() + cpu.f.cFlag = True + cpu.a.set(value+1) + register.set(value) + numCycles= 1 + if register == cpu.hli: + numCycles = 2 + cycle_test(cpu, opCode, numCycles) + if register == cpu.a: + assert cpu.a.get() == 0xFF + else: + assert cpu.a.get() == 0 + + value += 3 + opCode += 0x01 +def test_and_flags(): + cpu = get_cpu() + value = 0x12 + cpu.a.set(value) + cpu.b.set(value) + cpu.AND(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=False) + + cpu.reset() + cpu.a.set(value) + cpu.b.set(0) + cpu.AND(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=True) + # and_A_B to and_A_A def test_0xA0_to_0xA7(): cpu = get_cpu() @@ -946,6 +988,21 @@ value += 1 opCode += 0x01 + +def test_xor_flags(): + cpu = get_cpu() + value = 0x12 + cpu.a.set(value) + cpu.b.set(value) + cpu.XOR(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=True) + + cpu.reset() + cpu.a.set(value) + cpu.b.set(value+1) + cpu.XOR(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=False) + # xor_A_B to xor_A_A def test_0xA8_to_0xAF(): cpu = get_cpu() @@ -972,6 +1029,20 @@ value += 1 opCode += 0x01 +def test_or_flags(): + cpu = get_cpu() + value = 0x12 + cpu.a.set(value) + cpu.b.set(value) + cpu.OR(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=False) + + cpu.reset() + cpu.a.set(0) + cpu.b.set(0) + cpu.OR(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=True) + # or_A_B to or_A_A def test_0xB0_to_0xB7(): cpu = get_cpu() @@ -998,6 +1069,27 @@ value += 1 opCode += 0x01 +def test_cp_flags(): + cpu = get_cpu() + value = 0x12 + cpu.a.set(value) + cpu.b.set(value) + cpu.compareA(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=True, nFlag=True) + + cpu.reset() + cpu.a.set(value) + cpu.b.set(0) + cpu.compareA(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=False, nFlag=True) + + cpu.reset() + cpu.a.set(0xF0) + cpu.b.set(0x01) + cpu.compareA(cpu.b.get, cpu.b.set) + assert_default_flags(cpu, zFlag=False, hFlag=True, nFlag=True) + + # cp_A_B to cp_A_A def test_0xB8_to_0xBF(): cpu = get_cpu() @@ -1136,20 +1228,23 @@ prepare_for_pop(cpu, value >> 8, value & 0xFF) cycle_test(cpu, 0xC9, 4) assert_default_registers(cpu, pc=value, sp=valueSp+2) - # reti -def test_0xD9(): - py.test.skip("deeper knowledge necessary") +def test_0xD9_returnFormInterrupt(): + py.test.skip("cycle bug in cpu") cpu = get_cpu() value = 0x1234 + cpu.sp.set(0) prepare_for_pop(cpu, value >> 8, value & 0xFF) prepare_for_fetch(cpu, 0x00) pc = cpu.pc.get() - cycle_test(cpu, 0xD9, 4+1) - assert_default_registers(cpu, pc=pc+value) + cycle_test(cpu, 0xD9, 4+2) + assert_default_registers(cpu, pc=value+1, sp=2) + +def test_0xD9_handleInterrupt(): + py.test.skip("figuring out how to do it") -# ld_PC_HL +# ld_PC_HL def test_0xE9(): cpu = get_cpu() value = 0x1234 @@ -1187,7 +1282,6 @@ assert_default_registers(cpu, f=~flags[i] & 0xFF, pc=pc+2) value += 3 opCode += 0x08 - # ldh_Ci_A def test_0xE2(): @@ -1210,9 +1304,6 @@ cycle_test(cpu, 0xF2, 2) assert_default_registers(cpu, a=valueA, bc=valueC) - - - # jp_nnnn def test_0xC3(): cpu = get_cpu() @@ -1230,12 +1321,26 @@ # ei def test_0xFB(): - py.test.skip("interupt error") + py.test.skip("cycle bug in cpu") cpu = get_cpu() + cpu.sp.set(0) cpu.ime = False + cpu.halted = False prepare_for_fetch(cpu, 0x00) cycle_test(cpu, 0xFB, 1+1) assert cpu.ime == True + + cpu.reset() + cpu.sp.set(0) + cpu.ime = True + cpu.halted = False + cpu.interrupt.vBlank.setPending() + cpu.interrupt.setInterruptEnable(True) + assert cpu.interrupt.isPending() == True + prepare_for_fetch(cpu, 0x00) + cycle_test(cpu, 0xFB, 1+1+4) + assert cpu.interrupt.isPending() == False + assert cpu.ime == True # call_NZ_nnnn def test_0xC4(): @@ -1303,6 +1408,7 @@ # rst(0x00) to rst(0x38) def test_0xC7_to_0xFF(): + py.test.skip("cycle bug in cpu") cpu = get_cpu() opCode = 0xC7 rstValue = 0x00 Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Tue Apr 8 00:46:33 2008 @@ -0,0 +1,158 @@ +from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy.ram import * +from pypy.lang.gameboy import * +from pypy.lang.gameboy.interrupt import * + +class Memory(object): + def __init__(self): + self.memory = [0xFF]*0xFFFFF + + def write(self, address, data): + self.memory[address] = data + + def read(self, address): + return self.memory[address] + +global TEST_CPU + +TEST_CPU = None +def get_cpu(new=False): + if new: + cpu = CPU(Interrupt(), Memory()) + cpu.setROM([0]*0xFFFF); + return cpu + global TEST_CPU + if TEST_CPU == None: + TEST_CPU = get_cpu(True) + TEST_CPU.reset() + return TEST_CPU + +# ------------------------------------------------------------ +# TEST REGISTER +def test_register_constructor(): + register = Register(get_cpu()) + assert register.get() == 0 + value = 10 + register = Register(get_cpu(), value) + assert register.get() == value + +def test_register(): + register = Register(get_cpu()) + value = 2 + oldCycles = register.cpu.cycles + register.set(value) + assert register.get() == value + assert oldCycles-register.cpu.cycles == 1 + +def test_register_bounds(): + register = Register(get_cpu()) + value = 0x1234FF + register.set(value) + assert register.get() == 0xFF + +def test_reset(): + value = 0x12 + register = Register(get_cpu(), value) + register.set(value+1) + assert register.get() == value+1 + register.reset() + assert register.get() == value + +# ------------------------------------------------------------ +# TEST DOUBLE REGISTER + +def test_double_register_constructor(): + cpu = get_cpu() + register = DoubleRegister(cpu) + assert register.get() == 0 + assert register.getHi() == 0 + assert register.getLo() == 0 + value = 0x1234 + reg1 = Register(cpu) + reg1.set(0x12) + reg2 = Register(cpu) + reg2.set(0x34) + register = DoubleRegister(cpu, reg1, reg2) + assert register.hi == reg1 + assert register.lo == reg2 + assert register.getHi() == reg1.get() + assert register.getLo() == reg2.get() + +def test_double_register(): + register = DoubleRegister(get_cpu()) + value = 0x1234 + oldCycles = register.cpu.cycles + register.set(value) + assert oldCycles-register.cpu.cycles == 1 + assert register.get() == value + +def test_double_register_bounds(): + register = DoubleRegister(get_cpu()) + value = 0xFFFF1234 + register.set(value) + assert register.get() == 0x1234 + +def test_double_register_hilo(): + register = DoubleRegister(get_cpu()) + value = 0x1234 + valueHi = 0x12 + valueLo = 0x34 + oldCycles = register.cpu.cycles + register.set(valueHi, valueLo) + assert oldCycles-register.cpu.cycles == 2 + assert register.getHi() == valueHi + assert register.getLo() == valueLo + assert register.get() == value + + valueHi = 0x56 + oldCycles = register.cpu.cycles + register.setHi(valueHi) + assert oldCycles-register.cpu.cycles == 1 + assert register.getHi() == valueHi + assert register.getLo() == valueLo + + valueLo = 0x78 + oldCycles = register.cpu.cycles + register.setLo(valueLo) + assert oldCycles-register.cpu.cycles == 1 + assert register.getHi() == valueHi + assert register.getLo() == valueLo + + +def test_double_register_methods(): + print("test_double_register_methods") + value = 0x1234 + register = DoubleRegister(get_cpu()) + register.set(value) + + oldCycles = register.cpu.cycles + register.inc(False) + assert oldCycles-register.cpu.cycles == 0 + assert register.get() == value+1 + + register.set(value) + oldCycles = register.cpu.cycles + register.inc(True) + assert oldCycles-register.cpu.cycles == 2 + assert register.get() == value+1 + + oldCycles = register.cpu.cycles + register.dec() + assert oldCycles-register.cpu.cycles == 2 + assert register.get() == value + + addValue = 0x1001 + oldCycles = register.cpu.cycles + register.add(addValue) + assert oldCycles-register.cpu.cycles == 3 + assert register.get() == value+addValue + + +def test_double_register_reset(): + value = 0x1234; + + register = DoubleRegister(get_cpu(), value) + register.set(value+1) + assert register.get() == value+1; + register.reset() + assert register.get() == value \ No newline at end of file From fijal at codespeak.net Tue Apr 8 00:58:19 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Apr 2008 00:58:19 +0200 (CEST) Subject: [pypy-svn] r53557 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080407225819.4D2CF16A34B@codespeak.net> Author: fijal Date: Tue Apr 8 00:58:18 2008 New Revision: 53557 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: this makes sense I suppose Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Tue Apr 8 00:58:18 2008 @@ -145,8 +145,8 @@ graph2 = t.graphs[0] else: graph2 = graphof(t, portal) - self.graph = graph2 - self.maingraph = graphof(rtyper.annotator.translator, func) + self.graph = graph2 + self.maingraph = graphof(rtyper.annotator.translator, func) writer = self.create_writer(t, hannotator, self.RGenOp) jitcode = writer.make_bytecode(graph2) # the bytecode writer can ask for llhelpers about lists and dicts From fijal at codespeak.net Tue Apr 8 00:59:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Apr 2008 00:59:06 +0200 (CEST) Subject: [pypy-svn] r53558 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080407225906.609F016A365@codespeak.net> Author: fijal Date: Tue Apr 8 00:59:05 2008 New Revision: 53558 Added: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py (contents, props changed) Log: Some test, just because Added: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py ============================================================================== --- (empty file) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py Tue Apr 8 00:59:05 2008 @@ -0,0 +1,28 @@ +from pypy.rpython.module.support import LLSupport +from pypy.jit.rainbow.test.test_portal import PortalTest +from pypy.jit.rainbow.test.test_vlist import P_OOPSPEC +from pypy.tool.sourcetools import func_with_new_name +from pypy.jit.conftest import Benchmark + +from pypy.jit.tl import tiny3_hotpath as tiny3 +from pypy.jit.tl.targettiny3hotpath import MyHintAnnotatorPolicy + + +class TestTL(PortalTest): + type_system = "lltype" + + def test_tl(self): + def main(bytecode, arg1, arg2, arg3): + if bytecode == 0: + bytecode = "{ #1 1 SUB ->#1 #1 }" + elif bytecode == 1: + bytecode = "{ 1.2 ->#2 1.3 ->#3 #1 1 SUB ->#1 #1 } #1 #2 #3" + else: + assert 0 + bytecode = [s for s in bytecode.split(' ') if s != ''] + args = [tiny3.IntBox(arg1), tiny3.IntBox(arg3), tiny3.IntBox(arg3)] + return tiny3.repr(tiny3.interpret(bytecode, args)) + + res = self.timeshift_from_portal(main, tiny3.interpret, [1, 5, 0, 0], + policy=MyHintAnnotatorPolicy()) + assert "".join(res.chars._obj.items) == "0 1.200000 1.300000" From fijal at codespeak.net Tue Apr 8 03:44:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Apr 2008 03:44:07 +0200 (CEST) Subject: [pypy-svn] r53560 - pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test Message-ID: <20080408014407.0EA4316A3A5@codespeak.net> Author: fijal Date: Tue Apr 8 03:44:05 2008 New Revision: 53560 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py Log: Skip this test. This is broken, but should be re-enabled at some point. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py Tue Apr 8 03:44:05 2008 @@ -97,4 +97,5 @@ # for the individual tests see # ====> ../../../rainbow/test/test_portal.py - pass + def test_simple_recursive_portal_call_with_exc(self): + py.test.skip("FIXME") From jared.grubb at codespeak.net Tue Apr 8 04:16:08 2008 From: jared.grubb at codespeak.net (jared.grubb at codespeak.net) Date: Tue, 8 Apr 2008 04:16:08 +0200 (CEST) Subject: [pypy-svn] r53561 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080408021608.6469716A6E5@codespeak.net> Author: jared.grubb Date: Tue Apr 8 04:16:06 2008 New Revision: 53561 Modified: pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Log: Test_pcre_regtest.py: removed the failing tests (they use syntax and expectations not supported by our regex implementation); enabled the tests as part of the regression test runs Modified: pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py (original) +++ pypy/dist/pypy/rlib/parsing/test/pcre_test_7.py Tue Apr 8 04:16:06 2008 @@ -1,3 +1,16 @@ +# The following file was auto-generated, but has been edited to remove tests that +# do not pass; we have verified that they should NOT pass, due to our interpretation +# of regex formats. The tests were removed for the following reasons (which were not +# easily recognizable during the parsing and creation of this file): +# 1) In PCRE, '.' matches any character except \n. We define '.' as matching any +# character at all. +# 2) In PCRE, '\n' at the end of a line is ignored for matches on regex like 'a$'. +# Our implementation does not actually implement $ or ^, but we fake it by +# restricting the substrings that we test. Therefore, we cannot properly fake +# these cases. +# 3) The expression "^a|b" contains two tests "^a" or "b". The ^ only binds to +# the first group; we fake $ and ^ as it is, so we will not pass this test. + # Auto-generated file of regular expressions from PCRE library # The PCRE library is distributed under the BSD license. We have borrowed some @@ -81,8 +94,8 @@ suite.append(['x\\dy\\Dz', '', [('x9yzz', 'x9yzz'), ('x0y+z', 'x0y+z'), ('*** Failers', None), ('xyz', None), ('xxy0z', None)]]) suite.append(['x\\sy\\Sz', '', [('x yzz', 'x yzz'), ('x y+z', 'x y+z'), ('*** Failers', None), ('xyz', None), ('xxyyz', None)]]) suite.append(['x\\wy\\Wz', '', [('xxy+z', 'xxy+z'), ('*** Failers', None), ('xxy0z', None), ('x+y+z', None)]]) -suite.append(['x.y', '', [('x+y', 'x+y'), ('x-y', 'x-y'), ('*** Failers', None), ('x\ny', None)]]) -suite.append(['a\\d$', '', [('ba0', 'a0'), ('ba0\n', 'a0'), ('*** Failers', None), ('ba0\ncd', None)]]) +suite.append(['x.y', '', [('x+y', 'x+y'), ('x-y', 'x-y')]]) # MANUALLY REMOVED TESTS: , ('*** Failers', None), ('x\ny', None)]]) +suite.append(['a\\d$', '', [('ba0', 'a0')]]) # MANUALLY REMOVED TESTS: , ('ba0\n', 'a0'), ('*** Failers', None), ('ba0\ncd', None)]]) suite.append(['[^a]', '', [('abcd', 'b')]]) suite.append(['ab?\\w', '', [('abz', 'abz'), ('abbz', 'abb'), ('azz', 'az')]]) suite.append(['x{0,3}yz', '', [('ayzq', 'yz'), ('axyzq', 'xyz'), ('axxyz', 'xxyz'), ('axxxyzq', 'xxxyz'), ('axxxxyzq', 'xxxyz'), ('*** Failers', None), ('ax', None), ('axx', None)]]) @@ -115,7 +128,7 @@ suite.append(['^(a*\\w|ab)=(a*\\w|ab)', '', [('ab=ab', 'ab=ab')]]) suite.append(['^abc', '', [('abcdef', 'abc'), ('*** Failers', None)]]) suite.append(['^(a*|xyz)', '', [('bcd', ''), ('aaabcd', 'aaa'), ('xyz', 'xyz'), ('*** Failers', '')]]) -suite.append(['xyz$', '', [('xyz', 'xyz'), ('xyz\n', 'xyz'), ('*** Failers', None)]]) +suite.append(['xyz$', '', [('xyz', 'xyz')]]) # MANUALLY REMOVED TESTS: , ('xyz\n', 'xyz'), ('*** Failers', None)]]) suite.append(['^abcdef', '', [('*** Failers', None)]]) suite.append(['^a{2,4}\\d+z', '', [('*** Failers', None)]]) suite.append(['the quick brown fox', '', [('the quick brown fox', 'the quick brown fox'), ('The quick brown FOX', None), ('What do you know about the quick brown fox?', 'the quick brown fox'), ('What do you know about THE QUICK BROWN FOX?', None)]]) @@ -172,7 +185,7 @@ suite.append(['ab{3,cd', '', [('ab{3,cd', 'ab{3,cd')]]) suite.append(['ab{3,4a}cd', '', [('ab{3,4a}cd', 'ab{3,4a}cd')]]) suite.append(['{4,5a}bc', '', [('{4,5a}bc', '{4,5a}bc')]]) -suite.append(['abc$', '', [('abc', 'abc'), ('abc\n', 'abc'), ('*** Failers', None), ('abc\ndef', None)]]) +suite.append(['abc$', '', [('abc', 'abc')]]) # MANUALLY REMOVED TESTS: ('abc\n', 'abc'), ('*** Failers', None), ('abc\ndef', None)]]) suite.append(['(abc)\\223', '', [('abc\x93', 'abc\x93')]]) suite.append(['(abc)\\323', '', [('abc\xd3', 'abc\xd3')]]) suite.append(['ab\\idef', '', [('abidef', 'abidef')]]) @@ -206,11 +219,11 @@ suite.append(['^(a){1,2}', '', [('bcd', None), ('abc', 'a'), ('aab', 'aa')]]) suite.append(['^(a){1,3}', '', [('bcd', None), ('abc', 'a'), ('aab', 'aa'), ('aaa', 'aaa')]]) suite.append(['^(a){1,}', '', [('bcd', None), ('abc', 'a'), ('aab', 'aa'), ('aaa', 'aaa'), ('aaaaaaaa', 'aaaaaaaa')]]) -suite.append(['.*\\.gif', '', [('borfle\nbib.gif\nno', 'bib.gif')]]) -suite.append(['.{0,}\\.gif', '', [('borfle\nbib.gif\nno', 'bib.gif')]]) -suite.append(['.*$', '', [('borfle\nbib.gif\nno', 'no')]]) -suite.append(['.*$', '', [('borfle\nbib.gif\nno\n', 'no')]]) -suite.append(['^.*B', '', [('**** Failers', None), ('abc\nB', None)]]) +# MANUALLY REMOVED TESTS: suite.append(['.*\\.gif', '', [('borfle\nbib.gif\nno', 'bib.gif')]]) +# MANUALLY REMOVED TESTS: suite.append(['.{0,}\\.gif', '', [('borfle\nbib.gif\nno', 'bib.gif')]]) +# MANUALLY REMOVED TESTS: suite.append(['.*$', '', [('borfle\nbib.gif\nno', 'no')]]) +# MANUALLY REMOVED TESTS: suite.append(['.*$', '', [('borfle\nbib.gif\nno\n', 'no')]]) +# MANUALLY REMOVED TESTS: suite.append(['^.*B', '', [('**** Failers', None), ('abc\nB', None)]]) suite.append(['^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]', '', [('123456654321', '123456654321')]]) suite.append(['^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d', '', [('123456654321', '123456654321')]]) suite.append(['^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]', '', [('123456654321', '123456654321')]]) @@ -225,7 +238,7 @@ suite.append(['ab\\d{0}e', '', [('abe', 'abe'), ('*** Failers', None), ('ab1e', None)]]) suite.append(['"([^\\\\"]+|\\\\.)*"', '', [('the "quick" brown fox', '"quick"'), ('"the \\"quick\\" brown fox"', '"the \\"quick\\" brown fox"')]]) suite.append(['a[^a]b', '', [('acb', 'acb'), ('a\nb', 'a\nb')]]) -suite.append(['a.b', '', [('acb', 'acb'), ('*** Failers', None), ('a\nb', None)]]) +suite.append(['a.b', '', [('acb', 'acb')]]) # MANUALLY REMOVED TESTS: , ('*** Failers', None), ('a\nb', None)]]) suite.append(['\\x00{ab}', '', [('\x00{ab}', '\x00{ab}')]]) suite.append(['(A|B)*CD', '', [('CD', 'CD')]]) suite.append(['(\\d+)(\\w)', '', [('12345a', '12345a'), ('12345+', '12345')]]) @@ -317,7 +330,7 @@ suite.append(['(ab|a)b*c', '', [('abc', 'abc')]]) suite.append(['((a)(b)c)(d)', '', [('abcd', 'abcd')]]) suite.append(['[a-zA-Z_][a-zA-Z0-9_]*', '', [('alpha', 'alpha')]]) -suite.append(['^a(bc+|b[eh])g|.h$', '', [('abh', 'bh')]]) +# MANUALLY REMOVED TESTS: suite.append(['^a(bc+|b[eh])g|.h$', '', [('abh', 'bh')]]) suite.append(['(bc+d$|ef*g.|h?i(j|k))', '', [('effgz', 'effgz'), ('ij', 'ij'), ('reffgz', 'effgz'), ('*** Failers', None), ('effg', None), ('bcdd', None)]]) suite.append(['((((((((((a))))))))))', '', [('a', 'a')]]) suite.append(['(((((((((a)))))))))', '', [('a', 'a')]]) @@ -367,4 +380,4 @@ suite.append(['^(a()*)*', '', [('aaaa', 'aaaa')]]) suite.append(['^(a()+)+', '', [('aaaa', 'aaaa')]]) suite.append(['(a|)*\\d', '', [('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', None), ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4')]]) -suite.append(['.+foo', '', [('afoo', 'afoo'), ('** Failers', None), ('\r\nfoo', None), ('\nfoo', None)]]) +suite.append(['.+foo', '', [('afoo', 'afoo')]]) # MANUALLY REMOVED TESTS:, ('** Failers', None), ('\r\nfoo', None), ('\nfoo', None)]]) Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Tue Apr 8 04:16:06 2008 @@ -85,7 +85,7 @@ import string import re -py.test.skip("Still in progress") +#py.test.skip("Still in progress") # Dumper's are objects that can dump/load the suite class Dumper(object): From fijal at codespeak.net Tue Apr 8 04:43:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Apr 2008 04:43:23 +0200 (CEST) Subject: [pypy-svn] r53562 - in pypy/branch/jit-hotpath/pypy: config translator Message-ID: <20080408024323.4797F16A726@codespeak.net> Author: fijal Date: Tue Apr 8 04:43:19 2008 New Revision: 53562 Modified: pypy/branch/jit-hotpath/pypy/config/translationoption.py pypy/branch/jit-hotpath/pypy/translator/driver.py Log: add --jit-backend to force backend choice Modified: pypy/branch/jit-hotpath/pypy/config/translationoption.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/config/translationoption.py (original) +++ pypy/branch/jit-hotpath/pypy/config/translationoption.py Tue Apr 8 04:43:19 2008 @@ -35,6 +35,9 @@ "js": [("translation.type_system", "ootype")], }, cmdline="-b --backend"), + ChoiceOption("jitbackend", "Backent to use for JIT code generation", + ["ia32", "i386", "ppc"], cmdline="--jit-backend", + default=None), BoolOption("llvm_via_c", "compile llvm via C", default=False, cmdline="--llvm-via-c", requires=[("translation.backend", "llvm")]), Modified: pypy/branch/jit-hotpath/pypy/translator/driver.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/driver.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/driver.py Tue Apr 8 04:43:19 2008 @@ -417,8 +417,10 @@ "Hint-annotate") def task_rainbow_lltype(self): - from pypy.jit.codegen import detect_cpu - cpu = detect_cpu.autodetect() + cpu = self.config.translation.jitbackend + if cpu is None: + from pypy.jit.codegen import detect_cpu + cpu = detect_cpu.autodetect() if cpu == 'i386': from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp RGenOp.MC_SIZE = 32 * 1024 * 1024 From pedronis at codespeak.net Tue Apr 8 12:02:23 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 8 Apr 2008 12:02:23 +0200 (CEST) Subject: [pypy-svn] r53564 - in pypy/dist/pypy: lib/_ctypes lib/app_test/ctypes_tests rlib rlib/test Message-ID: <20080408100223.164C616A9C9@codespeak.net> Author: pedronis Date: Tue Apr 8 12:02:21 2008 New Revision: 53564 Modified: pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/app_test/ctypes_tests/test_parameters.py pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/test/test_libffi.py Log: merging back to trunk fixes and changes done on the ctypes-stable branch Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Tue Apr 8 12:02:21 2008 @@ -106,12 +106,6 @@ contents = property(getcontents, setcontents) - def __eq__(self, other): - return self._buffer[0] == other - - def __ne__(self, other): - return not self == other - def _cast_addr(obj, _, tp): if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()): raise TypeError("cast() argument 2 must be a pointer type, not %s" Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_parameters.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/test_parameters.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/test_parameters.py Tue Apr 8 12:02:21 2008 @@ -100,7 +100,7 @@ assert x.contents.value == 42 assert LPINT(c_int(42)).contents.value == 42 - assert LPINT.from_param(None) == 0 + assert not LPINT.from_param(None) if c_int != c_long: raises(TypeError, LPINT.from_param, pointer(c_long(42))) Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Tue Apr 8 12:02:21 2008 @@ -49,6 +49,8 @@ ('type', rffi.USHORT), ('elements', FFI_TYPE_PP)]) + ffi_closure = rffi_platform.Struct('ffi_closure', []) + def add_simple_type(type_name): for name in ['size', 'alignment', 'type']: setattr(CConfig, type_name + '_' + name, @@ -119,8 +121,7 @@ FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=CConfig. _compilation_info_) -FFI_CLOSUREP = rffi.COpaquePtr('ffi_closure', compilation_info=CConfig. - _compilation_info_) +FFI_CLOSUREP = lltype.Ptr(cConfig.ffi_closure) VOIDPP = rffi.CArrayPtr(rffi.VOIDP) @@ -209,6 +210,39 @@ userdata = rffi.cast(USERDATA_P, ll_userdata) userdata.callback(ll_args, ll_res, userdata) +# heap for closures +from pypy.jit.codegen.i386 import codebuf_posix + +CHUNK = 4096 +CLOSURES = rffi.CArrayPtr(FFI_CLOSUREP.TO) + +class ClosureHeap(object): + + def __init__(self): + self.free_list = lltype.nullptr(rffi.VOIDP.TO) + + def _more(self): + chunk = rffi.cast(CLOSURES, codebuf_posix.alloc(CHUNK)) + count = CHUNK//rffi.sizeof(FFI_CLOSUREP.TO) + for i in range(count): + rffi.cast(rffi.VOIDPP, chunk)[0] = self.free_list + self.free_list = rffi.cast(rffi.VOIDP, chunk) + chunk = rffi.ptradd(chunk, 1) + + def alloc(self): + if not self.free_list: + self._more() + p = self.free_list + self.free_list = rffi.cast(rffi.VOIDPP, p)[0] + return rffi.cast(FFI_CLOSUREP, p) + + def free(self, p): + rffi.cast(rffi.VOIDPP, p)[0] = self.free_list + self.free_list = rffi.cast(rffi.VOIDP, p) + +closureHeap = ClosureHeap() + + class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) @@ -246,7 +280,7 @@ # it cannot be any kind of movable gc reference def __init__(self, argtypes, restype, func, additional_arg=0): AbstractFuncPtr.__init__(self, "callback", argtypes, restype) - self.ll_closure = lltype.malloc(FFI_CLOSUREP.TO, flavor='raw') + self.ll_closure = closureHeap.alloc() self.ll_userdata = lltype.malloc(USERDATA_P.TO, flavor='raw') self.ll_userdata.callback = rffi.llhelper(CALLBACK_TP, func) self.ll_userdata.addarg = additional_arg @@ -259,7 +293,7 @@ def __del__(self): AbstractFuncPtr.__del__(self) if self.ll_closure: - lltype.free(self.ll_closure, flavor='raw') + closureHeap.free(self.ll_closure) self.ll_closure = lltype.nullptr(FFI_CLOSUREP.TO) if self.ll_userdata: lltype.free(self.ll_userdata, flavor='raw') Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Tue Apr 8 12:02:21 2008 @@ -109,6 +109,36 @@ del libc assert not ALLOCATED + def test_closure_heap(self): + ch = ClosureHeap() + + assert not ch.free_list + a = ch.alloc() + assert ch.free_list + b = ch.alloc() + + chunks = [a, b] + p = ch.free_list + while p: + chunks.append(p) + p = rffi.cast(rffi.VOIDPP, p)[0] + closure_size = rffi.sizeof(FFI_CLOSUREP.TO) + assert len(chunks) == CHUNK//closure_size + for i in range(len(chunks) -1 ): + s = rffi.cast(rffi.UINT, chunks[i+1]) + e = rffi.cast(rffi.UINT, chunks[i]) + assert (e-s) >= rffi.sizeof(FFI_CLOSUREP.TO) + + ch.free(a) + assert ch.free_list == rffi.cast(rffi.VOIDP, a) + snd = rffi.cast(rffi.VOIDPP, a)[0] + assert snd == chunks[2] + + ch.free(b) + assert ch.free_list == rffi.cast(rffi.VOIDP, b) + snd = rffi.cast(rffi.VOIDPP, b)[0] + assert snd == rffi.cast(rffi.VOIDP, a) + def test_callback(self): libc = CDLL('libc.so.6') qsort = libc.getpointer('qsort', [ffi_type_pointer, ffi_type_slong, From pedronis at codespeak.net Tue Apr 8 12:04:39 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 8 Apr 2008 12:04:39 +0200 (CEST) Subject: [pypy-svn] r53565 - pypy/dist/pypy/doc Message-ID: <20080408100439.195BD16A9C9@codespeak.net> Author: pedronis Date: Tue Apr 8 12:04:38 2008 New Revision: 53565 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: the number of passing tests varies a little bit because of test_find depending on which OpenGL libraries are around Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Tue Apr 8 12:04:38 2008 @@ -120,7 +120,7 @@ $ cd ../.. # back to pypy/ $ ./translator/goal/pypy-c test_all.py lib/app_test/ctypes_tests -There should be 255 passed and 36 skipped tests. +There should be 36 skipped tests and all other tests should pass. Running application examples ============================== From pedronis at codespeak.net Tue Apr 8 12:06:39 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 8 Apr 2008 12:06:39 +0200 (CEST) Subject: [pypy-svn] r53566 - pypy/dist/pypy/doc Message-ID: <20080408100639.08B7516A9C9@codespeak.net> Author: pedronis Date: Tue Apr 8 12:06:38 2008 New Revision: 53566 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: remove the last XXX Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Tue Apr 8 12:06:38 2008 @@ -93,7 +93,7 @@ A stable revision of PyPy containing the ctypes implementation can be checked out with subversion from the tag: -http://codespeak.net/svn/pypy/tag/ctypes-stable XXX make the tag +http://codespeak.net/svn/pypy/tag/ctypes-stable The various tests and later examples can be run on x86-32 Linux. We tried them on an up-to-date Ubuntu 7.10 x86-32 system. From arigo at codespeak.net Tue Apr 8 12:10:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 12:10:57 +0200 (CEST) Subject: [pypy-svn] r53567 - pypy/dist/pypy/lib Message-ID: <20080408101057.DB7FC16A7FA@codespeak.net> Author: arigo Date: Tue Apr 8 12:10:57 2008 New Revision: 53567 Modified: pypy/dist/pypy/lib/readline.py Log: Add an __all__. Modified: pypy/dist/pypy/lib/readline.py ============================================================================== --- pypy/dist/pypy/lib/readline.py (original) +++ pypy/dist/pypy/lib/readline.py Tue Apr 8 12:10:57 2008 @@ -7,6 +7,30 @@ ENCODING = 'latin1' # XXX hard-coded +__all__ = ['add_history', + 'clear_history', + 'get_begidx', + 'get_completer', + 'get_completer_delims', + 'get_current_history_length', + 'get_endidx', + 'get_history_item', + 'get_history_length', + 'get_line_buffer', + 'insert_text', + 'parse_and_bind', + 'read_history_file', + 'read_init_file', + 'redisplay', + 'remove_history_item', + 'replace_history_item', + 'set_completer', + 'set_completer_delims', + 'set_history_length', + 'set_pre_input_hook', + 'set_startup_hook', + 'write_history_file'] + # ____________________________________________________________ class _ReaderMixin(object): From arigo at codespeak.net Tue Apr 8 12:23:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 12:23:26 +0200 (CEST) Subject: [pypy-svn] r53569 - pypy/dist/pypy/lib Message-ID: <20080408102326.1DC0E16A9DB@codespeak.net> Author: arigo Date: Tue Apr 8 12:23:25 2008 New Revision: 53569 Added: pypy/dist/pypy/lib/readline.py Modified: pypy/dist/pypy/lib/_pypy_interact.py Log: Move this logic into pyrepl itself. Modified: pypy/dist/pypy/lib/_pypy_interact.py ============================================================================== --- pypy/dist/pypy/lib/_pypy_interact.py (original) +++ pypy/dist/pypy/lib/_pypy_interact.py Tue Apr 8 12:23:25 2008 @@ -4,18 +4,18 @@ def interactive_console(mainmodule=None): - import code - if mainmodule is None: - import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) try: - from readline import multiline_input + from pyrepl.simple_interact import run_multiline_interactive_console except ImportError: - run_simple_interactive_console(console) + run_simple_interactive_console(mainmodule) else: - run_multiline_interactive_console(console) + run_multiline_interactive_console(mainmodule) -def run_simple_interactive_console(console): +def run_simple_interactive_console(mainmodule): + import code + if mainmodule is None: + import __main__ as mainmodule + console = code.InteractiveConsole(mainmodule.__dict__) # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner @@ -38,37 +38,6 @@ console.resetbuffer() more = 0 -def run_multiline_interactive_console(console): - from readline import multiline_input - - def more_lines(unicodetext): - # ooh, look at the hack: - src = "#coding:utf-8\n"+unicodetext.encode('utf-8') - try: - code = console.compile(src, '', 'single') - except (OverflowError, SyntaxError, ValueError): - return False - else: - return code is None - - while 1: - try: - ps1 = getattr(sys, 'ps1', '>>> ') - ps2 = getattr(sys, 'ps2', '... ') - try: - statement = multiline_input(more_lines, ps1, ps2) - except EOFError: - break - # XXX with Alt-Enter we can actually enter more than one - # statement, and compile() ignores everything after the - # first statement in 'single' mode... We should either - # find some obscure workaround or tweak PyPy's compiler. - more = console.push(statement) - assert not more - except KeyboardInterrupt: - console.write("\nKeyboardInterrupt\n") - console.resetbuffer() - # ____________________________________________________________ if __name__ == '__main__': # for testing Added: pypy/dist/pypy/lib/readline.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/readline.py Tue Apr 8 12:23:25 2008 @@ -0,0 +1,8 @@ +"""readline - Importing this module enables command line editing using +the pyrepl library. The API is a subset of the GNU readline library. +It also contains extensions for multiline input. + +Note that some of the functions present in the CPython module 'readline' +are only stubs at the moment. +""" +from pyrepl.readline import * From cami at codespeak.net Tue Apr 8 12:25:55 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 8 Apr 2008 12:25:55 +0200 (CEST) Subject: [pypy-svn] r53570 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080408102555.9B77316A053@codespeak.net> Author: cami Date: Tue Apr 8 12:25:54 2008 New Revision: 53570 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Log: fixed cycle bug for call added register test Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Tue Apr 8 12:25:54 2008 @@ -51,7 +51,7 @@ self.cpu.cycles += 1 else: self.setHi(hi, useCycles) - self.setLo(lo, useCycles) + self.setLo(lo, useCycles) def reset(self): self.set(self.resetValue, None, useCycles=False) @@ -94,14 +94,14 @@ self.hl = hl def set(self, value, useCycles=True): - self.cpu.write(self.hl.get(useCycles), value) + self.cpu.write(self.hl.get(useCycles), value) # 2 + 0 if not useCycles: self.cpu.cycles += 2 def get(self, useCycles=True): if not useCycles: self.cpu.cycles += 1 - return self.cpu.read(self.hl.get(useCycles)) + return self.cpu.read(self.hl.get(useCycles)) # 1 # ------------------------------------------------------------------------------ @@ -336,7 +336,8 @@ def lowerPendingInterrupt(self): for flag in self.interrupt.interruptFlags: if flag.isPending(): - self.call(flag.callCode, disableIME=True, useCycles=False) + self.ime = False + self.call(flag.callCode, useCycles=False) flag.setPending(False) return @@ -406,14 +407,12 @@ self.cycles += 1 # 4 cycles - def call(self, address, disableIME=False, useCycles=True): - if disableIME: - self.ime = False + def call(self, address, useCycles=True): self.push(self.pc.getHi(useCycles), useCycles) # 2 cycles self.push(self.pc.getLo(useCycles), useCycles) # 2 cycles - self.pc.set(address, useCycles) # 1 cycle + self.pc.set(address, None, useCycles) # 1 cycle if useCycles: - self.cycles += 2 + self.cycles += 1 # 1 cycle def ld(self, getter, setter): @@ -531,12 +530,13 @@ self.f.hFlag = True setter(data) # 1 cycle - # 1 cycle + # RLC 1 cycle def rotateLeftCircular(self, getter, setter): - s = (getter() << 1) + (getter() >> 7) + data = getter() + s = (data << 1) + (data >> 7) self.flagsAndSetterFinish(s, setter, 0x80) - # rotateLeftCircularA 1 cycle + # RLCA rotateLeftCircularA 1 cycle def rotateLeftCircularA(self): self.rotateLeftCircular(self.a.get, self.a.set) @@ -551,7 +551,7 @@ def rotateLeftA(self): self.rotateLeft(self.a.get, self.a.set) - # 1 cycle + # RRC 1 cycle def rotateRightCircular(self, getter, setter): s = (getter() >> 1) + (getter() << 7) self.flagsAndSetterFinish(s, setter) # 1 cycle @@ -822,7 +822,8 @@ # RETI 4 cycles def returnFormInterrupt(self): self.ret() # 4 cycles - self.enableInterrupts() # 1 cycle + self.enableInterrupts() # 1 cycle + others + self.cycles += 1 # RST nn 4 cycles def restart(self, nn): @@ -834,7 +835,7 @@ self.cycles -= 1; # 1 cycle - def enableInterrupts(self): + def enableInterrupts(self): self.ime = True self.execute(self.fetch()) # 1 self.handlePendingInterrupt() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Tue Apr 8 12:25:54 2008 @@ -1231,7 +1231,6 @@ # reti def test_0xD9_returnFormInterrupt(): - py.test.skip("cycle bug in cpu") cpu = get_cpu() value = 0x1234 cpu.sp.set(0) @@ -1241,8 +1240,10 @@ cycle_test(cpu, 0xD9, 4+2) assert_default_registers(cpu, pc=value+1, sp=2) -def test_0xD9_handleInterrupt(): +def test_handleInterrupt(): py.test.skip("figuring out how to do it") + cpu = get_cpu() + # ld_PC_HL def test_0xE9(): @@ -1321,12 +1322,11 @@ # ei def test_0xFB(): - py.test.skip("cycle bug in cpu") cpu = get_cpu() cpu.sp.set(0) cpu.ime = False cpu.halted = False - prepare_for_fetch(cpu, 0x00) + prepare_for_fetch(cpu, 0x00) # nop 1 cycle cycle_test(cpu, 0xFB, 1+1) assert cpu.ime == True @@ -1334,13 +1334,18 @@ cpu.sp.set(0) cpu.ime = True cpu.halted = False + prepare_for_fetch(cpu, 0x00) # nop 1 cycle cpu.interrupt.vBlank.setPending() + cpu.interrupt.serial.setPending() cpu.interrupt.setInterruptEnable(True) assert cpu.interrupt.isPending() == True - prepare_for_fetch(cpu, 0x00) - cycle_test(cpu, 0xFB, 1+1+4) + assert cpu.halted == False + assert cpu.ime == True + cycle_test(cpu, 0xFB, 1+1) assert cpu.interrupt.isPending() == False - assert cpu.ime == True + assert cpu.interrupt.vBlank.isPending() == False + assert cpu.pc.get() == cpu.interrupt.vBlank.callCode + assert cpu.ime == False # call_NZ_nnnn def test_0xC4(): @@ -1408,7 +1413,6 @@ # rst(0x00) to rst(0x38) def test_0xC7_to_0xFF(): - py.test.skip("cycle bug in cpu") cpu = get_cpu() opCode = 0xC7 rstValue = 0x00 @@ -1427,9 +1431,22 @@ def test_0xCB(): pass +def test_rotateLeftCircular_flags(): + cpu = get_cpu() + a = cpu.a + a.set(0x01) + cpu.rotateLeftA() + assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_registers(cpu, a=0x02, f=None) + + cpu.reset() + a.set(0x40) + cpu.rotateLeftA() + assert_default_flags(cpu, zFlag=False, cFlag=True) + assert_default_registers(cpu, a=0x80, f=None) + # rlc_B to rlc_A -def test_0x00_to_0x07(): - py.test.skip("Bug in cpu") +def test_0x00_to_0x07_rotateLeftCircular(): cpu = get_cpu() registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] opCode = 0x00 @@ -1442,9 +1459,9 @@ cycles = 4 fetch_execute_cycle_test(cpu, opCode, cycles) rlc = ((value & 0x7F) << 1) + ((value & 0x80) >> 7) - assert register.get() == rcl + assert register.get() == rlc opCode += 0x01 - vaue += 1 + value += 1 # rrc_B to rrc_F def test_0x08_to_0x0F(): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Tue Apr 8 12:25:54 2008 @@ -91,6 +91,8 @@ value = 0xFFFF1234 register.set(value) assert register.get() == 0x1234 + register.set(0) + assert register.get() == 0 def test_double_register_hilo(): register = DoubleRegister(get_cpu()) @@ -120,7 +122,6 @@ def test_double_register_methods(): - print("test_double_register_methods") value = 0x1234 register = DoubleRegister(get_cpu()) register.set(value) From cami at codespeak.net Tue Apr 8 14:03:05 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 8 Apr 2008 14:03:05 +0200 (CEST) Subject: [pypy-svn] r53576 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080408120305.4E07B16AA03@codespeak.net> Author: cami Date: Tue Apr 8 14:03:04 2008 New Revision: 53576 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py Log: added serial test updated serial added cpu test fixed some bugs in cpu Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Tue Apr 8 14:03:04 2008 @@ -325,7 +325,7 @@ # Interrupts def handlePendingInterrupt(self): if self.halted: - if (self.interrupt.isPending()): + if self.interrupt.isPending(): self.halted = False self.cycles -= 4 elif (self.cycles > 0): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Tue Apr 8 14:03:04 2008 @@ -88,8 +88,8 @@ def getInterruptEnable(self): return int(self.enable) - def setInterruptEnable(self, data): - self.enable = bool(data) + def setInterruptEnable(self, isEnabled=True): + self.enable = bool(isEnabled) def getInterruptFlag(self): flag = 0x00 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Tue Apr 8 14:03:04 2008 @@ -15,14 +15,14 @@ self.sb = 0x00 self.sc = 0x00 - def cycles(self): + def getCycles(self): return self.cycles def emulate(self, ticks): - if ((self.sc & 0x81) != 0x81): + if (self.sc & 0x81) != 0x81: return self.cycles -= ticks - if (self.cycles <= 0): + if self.cycles <= 0: self.sb = 0xFF self.sc &= 0x7F self.cycles = constants.SERIAL_IDLE_CLOCK Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Tue Apr 8 14:03:04 2008 @@ -1241,9 +1241,39 @@ assert_default_registers(cpu, pc=value+1, sp=2) def test_handleInterrupt(): - py.test.skip("figuring out how to do it") cpu = get_cpu() + cpu.halted = True + cpu.cycles = 0xFF + cpu.handlePendingInterrupt() + assert cpu.cycles == 0 + cpu.reset() + cpu.halted = True + cpu.interrupt.setInterruptEnable() + cpu.interrupt.vBlank.setPending() + assert cpu.interrupt.isPending() == True + cpu.cycles = 4 + cpu.handlePendingInterrupt() + assert cpu.cycles == 0 + assert cpu.halted == False + + cpu.reset() + cpu.halted = False + cpu.ime = True + cpu.pc.set(0x1234) + cpu.sp.set(0x02) + sp = cpu.sp.get() + cpu.interrupt.setInterruptEnable() + cpu.interrupt.vBlank.setPending() + cpu.interrupt.lcd.setPending() + assert cpu.interrupt.isPending() == True + cpu.cycles = 0 + cpu.handlePendingInterrupt() + assert cpu.cycles == 0 + assert cpu.halted == False + assert_default_registers(cpu, pc=cpu.interrupt.vBlank.callCode, sp=sp-2) + assert cpu.pop() == 0x34 + assert cpu.pop() == 0x12 # ld_PC_HL def test_0xE9(): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py Tue Apr 8 14:03:04 2008 @@ -0,0 +1,55 @@ + +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.serial import * + + +def get_serial(): + return Serial(Interrupt()) + +def test_reset(): + serial = get_serial() + serial.cycles = 12 + serial.sb = 12 + serial.sc = 12 + serial.reset() + assert serial.cycles == constants.SERIAL_CLOCK + assert serial.sb == 0 + assert serial.sc == 0 + + +def test_setSerialControl(): + serial = get_serial() + value = 0x12 + serial.setSerialControl(value) + assert serial.getSerialControl() == value + assert serial.cycles == constants.SERIAL_IDLE_CLOCK + constants.SERIAL_CLOCK + + +def test_emulate(): + serial = get_serial() + serial.sc = 0x00 + serial.emulate(20) + assert serial.cycles == constants.SERIAL_CLOCK + assert serial.sb == 0 + assert serial.sc == 0 + + serial.reset() + serial.sc = 0x81 + serial.cycles = 10 + cycles = serial.cycles + serial.emulate(2) + assert serial.cycles > 0 + assert cycles-serial.cycles == 2 + assert serial.sb == 0 + assert serial.sc == 0x81 + assert serial.interrupt.serial.isPending() == False + + serial.reset() + serial.sc = 0x81 + serial.cycles = 0 + serial.emulate(2) + assert serial.sb == 0xFF + assert serial.sc == 0x81 & 0x7F + assert serial.cycles == constants.SERIAL_IDLE_CLOCK + assert serial.interrupt.serial.isPending() == True \ No newline at end of file From cami at codespeak.net Tue Apr 8 14:11:51 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 8 Apr 2008 14:11:51 +0200 (CEST) Subject: [pypy-svn] r53577 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080408121151.1C0C916A9D1@codespeak.net> Author: cami Date: Tue Apr 8 14:11:50 2008 New Revision: 53577 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py Log: completed serial completed serial tests Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Tue Apr 8 14:11:50 2008 @@ -42,3 +42,16 @@ def getSerialControl(self): return self.sc + def write(self, address, data): + if address == constants.SB: + self.setSerialData(data) + elif address == constants.SC: + self.setSerialControl(data) + + def read(self, address): + if address == constants.SB: + return self.getSerialData() + elif address == constants.SC: + return self.getSerialControl() + else: + return 0xFF \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py Tue Apr 8 14:11:50 2008 @@ -52,4 +52,19 @@ assert serial.sb == 0xFF assert serial.sc == 0x81 & 0x7F assert serial.cycles == constants.SERIAL_IDLE_CLOCK - assert serial.interrupt.serial.isPending() == True \ No newline at end of file + assert serial.interrupt.serial.isPending() == True + + +def test_read_write(): + serial = get_serial() + value = 0x12 + serial.write(constants.SB, value) + assert serial.read(constants.SB) == value + assert serial.sb == value + + value += 1 + serial.write(constants.SC, value) + assert serial.read(constants.SC) == value + assert serial.sc == value + + assert serial.read(0) == 0xFF \ No newline at end of file From arigo at codespeak.net Tue Apr 8 15:12:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 15:12:30 +0200 (CEST) Subject: [pypy-svn] r53581 - pypy/dist/pypy/doc Message-ID: <20080408131230.15AF916A7F5@codespeak.net> Author: arigo Date: Tue Apr 8 15:12:28 2008 New Revision: 53581 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: Typo. Expand description of the ctypes subclasses issue. Mention the callback segfaults (remove it again when it's fixed). Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Tue Apr 8 15:12:28 2008 @@ -56,16 +56,16 @@ pluggable garbage collectors, some of them are moving collectors, this means that the strategy of passing direct references inside Python objects to an external library is not feasible (unless the GCs -support pinning, which not the case right now). The consequence of +support pinning, which is not the case right now). The consequence of this is that sometimes copying instead of sharing is required, this may result in some semantics differences. C objects created with _rawffi itself are allocated outside of the GC heap, so they can be passed to external functions without worries. Porting the implementation to interpreter-level should likely improve -its speed, Further the current layering and the current _rawffi +its speed. Furthermore the current layering and the current _rawffi interface require more object allocations and copying than strictly -necessary, this too could be improved. +necessary; this too could be improved. The implementation was developed and has only been tested on x86-32 Linux. @@ -86,7 +86,13 @@ - callbacks accepting by-value structures - - expected semantics when ctypes types are subclassed + - slight semantic differences that ctypes makes + between its primitive types and user subclasses + of its primitive types + + - on Linux systems where heap memory is by default not + executable, callbacks segfault at the moment. This + should be fixed soon. Getting the code and test suites ================================= From arigo at codespeak.net Tue Apr 8 15:17:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 15:17:22 +0200 (CEST) Subject: [pypy-svn] r53582 - pypy/dist/pypy/doc Message-ID: <20080408131722.A64ED16A9B4@codespeak.net> Author: arigo Date: Tue Apr 8 15:17:22 2008 New Revision: 53582 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: Sorry, this was fixed in r53564 already. Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Tue Apr 8 15:17:22 2008 @@ -90,10 +90,6 @@ between its primitive types and user subclasses of its primitive types - - on Linux systems where heap memory is by default not - executable, callbacks segfault at the moment. This - should be fixed soon. - Getting the code and test suites ================================= From arigo at codespeak.net Tue Apr 8 17:08:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 17:08:57 +0200 (CEST) Subject: [pypy-svn] r53584 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080408150857.35A9D169EAD@codespeak.net> Author: arigo Date: Tue Apr 8 17:08:55 2008 New Revision: 53584 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: Hard to know which sense r53557 used to make, but it definitely broke many tests (e.g. test_hp_vlist). Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Tue Apr 8 17:08:55 2008 @@ -145,8 +145,8 @@ graph2 = t.graphs[0] else: graph2 = graphof(t, portal) - self.graph = graph2 - self.maingraph = graphof(rtyper.annotator.translator, func) + self.graph = graph2 + self.maingraph = graphof(rtyper.annotator.translator, func) writer = self.create_writer(t, hannotator, self.RGenOp) jitcode = writer.make_bytecode(graph2) # the bytecode writer can ask for llhelpers about lists and dicts From arigo at codespeak.net Tue Apr 8 17:10:00 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 17:10:00 +0200 (CEST) Subject: [pypy-svn] r53585 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080408151000.44E3716A077@codespeak.net> Author: arigo Date: Tue Apr 8 17:09:59 2008 New Revision: 53585 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Log: Use ll_assert(). Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py Tue Apr 8 17:09:59 2008 @@ -2,13 +2,11 @@ from pypy.jit.timeshifter.rcontainer import VirtualContainer, FrozenContainer from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, rvirtualizable, oop +from pypy.rlib.debug import ll_assert from pypy.rpython.lltypesystem import lloperation debug_print = lloperation.llop.debug_print -class NotConstInAVlist(Exception): - pass - def TypeDesc(RGenOp, rtyper, exceptiondesc, LIST): if rtyper.type_system.name == 'lltypesystem': return LLTypeListTypeDesc(RGenOp, rtyper, exceptiondesc, LIST) @@ -63,11 +61,9 @@ box = item_boxes[i] if box is not None: gv_value = box_gv_reader(box) - if gv_value.is_const: - v = gv_value.revealconst(LIST.ITEM) - l.ll_setitem_fast(i, v) - else: - raise NotConstInAVlist("Cannot put variable to a vlist") + ll_assert(gv_value.is_const, "vlist.populate() got a var") + v = gv_value.revealconst(LIST.ITEM) + l.ll_setitem_fast(i, v) self.allocate = allocate self.populate = populate From arigo at codespeak.net Tue Apr 8 17:14:42 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 17:14:42 +0200 (CEST) Subject: [pypy-svn] r53586 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080408151442.ED81016A978@codespeak.net> Author: arigo Date: Tue Apr 8 17:14:42 2008 New Revision: 53586 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py Log: The test for tiny3_hotpath.py must use the HotPathTest base class. The PortalTest base class is only for non-hotpath tests. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py Tue Apr 8 17:14:42 2008 @@ -1,15 +1,10 @@ -from pypy.rpython.module.support import LLSupport -from pypy.jit.rainbow.test.test_portal import PortalTest -from pypy.jit.rainbow.test.test_vlist import P_OOPSPEC -from pypy.tool.sourcetools import func_with_new_name -from pypy.jit.conftest import Benchmark +from pypy.jit.rainbow.test.test_hotpath import HotPathTest from pypy.jit.tl import tiny3_hotpath as tiny3 from pypy.jit.tl.targettiny3hotpath import MyHintAnnotatorPolicy -class TestTL(PortalTest): - type_system = "lltype" +class TestTL(HotPathTest): def test_tl(self): def main(bytecode, arg1, arg2, arg3): @@ -23,6 +18,6 @@ args = [tiny3.IntBox(arg1), tiny3.IntBox(arg3), tiny3.IntBox(arg3)] return tiny3.repr(tiny3.interpret(bytecode, args)) - res = self.timeshift_from_portal(main, tiny3.interpret, [1, 5, 0, 0], - policy=MyHintAnnotatorPolicy()) + res = self.run(main, [1, 5, 0, 0], threshold=2, + policy=MyHintAnnotatorPolicy()) assert "".join(res.chars._obj.items) == "0 1.200000 1.300000" From arigo at codespeak.net Tue Apr 8 17:17:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 17:17:50 +0200 (CEST) Subject: [pypy-svn] r53587 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080408151750.9869716A984@codespeak.net> Author: arigo Date: Tue Apr 8 17:17:50 2008 New Revision: 53587 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py Log: Fix. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_3tl.py Tue Apr 8 17:17:50 2008 @@ -15,7 +15,7 @@ else: assert 0 bytecode = [s for s in bytecode.split(' ') if s != ''] - args = [tiny3.IntBox(arg1), tiny3.IntBox(arg3), tiny3.IntBox(arg3)] + args = [tiny3.IntBox(arg1), tiny3.IntBox(arg2), tiny3.IntBox(arg3)] return tiny3.repr(tiny3.interpret(bytecode, args)) res = self.run(main, [1, 5, 0, 0], threshold=2, From arigo at codespeak.net Tue Apr 8 17:39:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 17:39:43 +0200 (CEST) Subject: [pypy-svn] r53588 - pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph Message-ID: <20080408153943.CB4C916A839@codespeak.net> Author: arigo Date: Tue Apr 8 17:39:42 2008 New Revision: 53588 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py Log: Check index against negative values. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py Tue Apr 8 17:39:42 2008 @@ -813,6 +813,7 @@ def read_frame_var(T, base, info, index): vars = info._obj.info.args + assert index >= 0 v = vars[index] if isinstance(v, flowmodel.Constant): val = v.value @@ -833,6 +834,7 @@ def write_frame_var(base, info, index, value): vars = info._obj.info.args + assert index >= 0 v = vars[index] assert isinstance(v, flowmodel.Variable) llframe = base.ptr From arigo at codespeak.net Tue Apr 8 17:57:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 17:57:59 +0200 (CEST) Subject: [pypy-svn] r53589 - in pypy/branch/jit-hotpath/pypy/jit/codegen: ia32 test Message-ID: <20080408155759.5F59516A8E2@codespeak.net> Author: arigo Date: Tue Apr 8 17:57:58 2008 New Revision: 53589 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Log: Don't return the input list directly as a result of get_frame_info(), in case the caller continues to mutate the list. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/rgenop.py Tue Apr 8 17:57:58 2008 @@ -318,7 +318,7 @@ return self.returnintvar(eax) def get_frame_info(self, vars_gv): - return vars_gv + return vars_gv[:] def genop_setfield(self, (offset, fieldsize, kt), gv_ptr, gv_value): assert fieldsize != 2 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py Tue Apr 8 17:57:58 2008 @@ -1747,7 +1747,12 @@ place = builder1.alloc_frame_place(signed_kind, rgenop.genconst(0)) v6 = builder1.genop_get_frame_base() c_seven = rgenop.genconst(7) - frameinfo = builder1.get_frame_info([v3, v4, c_seven, v5]) + lst = [v3, v4, c_seven, v5] + frameinfo = builder1.get_frame_info(lst) + assert frameinfo is not lst # it's ok for the backend to return any + # opaque object, but if it returns 'lst' + # it should make a copy so that the + # frontend doesn't mutate it afterwards # here would be a call v8 = builder1.genop_absorb_place(place) args_gv = [v3, v4, v5, v8] From arigo at codespeak.net Tue Apr 8 19:21:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 19:21:53 +0200 (CEST) Subject: [pypy-svn] r53593 - pypy/dist/pypy/lib/logic Message-ID: <20080408172153.04DA216A8DE@codespeak.net> Author: arigo Date: Tue Apr 8 19:21:53 2008 New Revision: 53593 Removed: pypy/dist/pypy/lib/logic/ Log: Remove old stuff. From arigo at codespeak.net Tue Apr 8 19:45:48 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 19:45:48 +0200 (CEST) Subject: [pypy-svn] r53594 - pypy/dist/pypy/rpython/memory/gctransform Message-ID: <20080408174548.C5DF516A939@codespeak.net> Author: arigo Date: Tue Apr 8 19:45:46 2008 New Revision: 53594 Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py Log: Fix the CollectAnalyzer to find all operations marked "I can collect" in lloperation.py. (The name of the flag is slightly obscure, though.) Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Tue Apr 8 19:45:46 2008 @@ -17,19 +17,18 @@ from pypy.rpython.memory.gctypelayout import convert_weakref_to, WEAKREFPTR from pypy.rpython.memory.gctransform.log import log from pypy.tool.sourcetools import func_with_new_name -from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.lltypesystem.lloperation import llop, LL_OPERATIONS import sys class CollectAnalyzer(graphanalyze.GraphAnalyzer): def operation_is_true(self, op): - if op.opname == 'gc__collect': - return True if op.opname in ('malloc', 'malloc_varsize'): flags = op.args[1].value return flags['flavor'] == 'gc' and not flags.get('nocollect', False) - if op.opname in ('coalloc', 'coalloc_varsize'): - return True + else: + return (op.opname in LL_OPERATIONS and + LL_OPERATIONS[op.opname].canunwindgc) def find_initializing_stores(collect_analyzer, graph): from pypy.objspace.flow.model import mkentrymap From arigo at codespeak.net Tue Apr 8 22:01:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 22:01:05 +0200 (CEST) Subject: [pypy-svn] r53595 - pypy/dist/pypy/module/_minimal_curses/test Message-ID: <20080408200105.6708816AE71@codespeak.net> Author: arigo Date: Tue Apr 8 22:00:59 2008 New Revision: 53595 Modified: pypy/dist/pypy/module/_minimal_curses/test/test_curses.py Log: Fix test. Modified: pypy/dist/pypy/module/_minimal_curses/test/test_curses.py ============================================================================== --- pypy/dist/pypy/module/_minimal_curses/test/test_curses.py (original) +++ pypy/dist/pypy/module/_minimal_curses/test/test_curses.py Tue Apr 8 22:00:59 2008 @@ -1,7 +1,7 @@ from pypy.translator.c.test.test_genc import compile -from pypy.module._curses import interp_curses -from pypy.module._curses import fficurses +from pypy.module._minimal_curses import interp_curses +from pypy.module._minimal_curses import fficurses from pypy.conftest import gettestobjspace from pypy.tool.autopath import pypydir from pypy.tool.udir import udir @@ -38,39 +38,39 @@ def test_setupterm(self): source = py.code.Source(""" - import _curses + import _minimal_curses try: - _curses.tigetstr('cup') - except _curses.error: + _minimal_curses.tigetstr('cup') + except _minimal_curses.error: print 'ok!' """) f = udir.join("test_setupterm.py") f.write(source) - child = self.spawn(['--withmod-_curses', str(f)]) + child = self.spawn(['--withmod-_minimal_curses', str(f)]) child.expect('ok!') def test_tigetstr(self): source = py.code.Source(""" - import _curses - _curses.setupterm() - assert _curses.tigetstr('cup') == '\x1b[%i%p1%d;%p2%dH' + import _minimal_curses + _minimal_curses.setupterm() + assert _minimal_curses.tigetstr('cup') == '\x1b[%i%p1%d;%p2%dH' print 'ok!' """) f = udir.join("test_tigetstr.py") f.write(source) - child = self.spawn(['--withmod-_curses', str(f)]) + child = self.spawn(['--withmod-_minimal_curses', str(f)]) child.expect('ok!') def test_tparm(self): source = py.code.Source(""" - import _curses - _curses.setupterm() - assert _curses.tparm(_curses.tigetstr('cup'), 5, 3) == '\033[6;4H' + import _minimal_curses + _minimal_curses.setupterm() + assert _minimal_curses.tparm(_minimal_curses.tigetstr('cup'), 5, 3) == '\033[6;4H' print 'ok!' """) f = udir.join("test_tparm.py") f.write(source) - child = self.spawn(['--withmod-_curses', str(f)]) + child = self.spawn(['--withmod-_minimal_curses', str(f)]) child.expect('ok!') @@ -79,7 +79,7 @@ """ def test_csetupterm(self): from pypy.translator.c.test.test_genc import compile - from pypy.module._curses import interp_curses + from pypy.module._minimal_curses import interp_curses def runs_setupterm(): interp_curses._curses_setupterm_null(1) @@ -88,7 +88,7 @@ def test_ctgetstr(self): from pypy.translator.c.test.test_genc import compile - from pypy.module._curses import interp_curses + from pypy.module._minimal_curses import interp_curses def runs_ctgetstr(): interp_curses._curses_setupterm("xterm", 1) return interp_curses._curses_tigetstr('cup') @@ -99,7 +99,7 @@ def test_ctparm(self): from pypy.translator.c.test.test_genc import compile - from pypy.module._curses import interp_curses + from pypy.module._minimal_curses import interp_curses def runs_tparm(): interp_curses._curses_setupterm("xterm", 1) cup = interp_curses._curses_tigetstr('cup') From arigo at codespeak.net Tue Apr 8 22:48:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 22:48:28 +0200 (CEST) Subject: [pypy-svn] r53596 - in pypy/dist/pypy: rlib rpython rpython/lltypesystem rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/memory/test translator/c translator/c/src translator/c/test Message-ID: <20080408204828.39D3C16AF98@codespeak.net> Author: arigo Date: Tue Apr 8 22:48:25 2008 New Revision: 53596 Modified: pypy/dist/pypy/rlib/rgc.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/llheap.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/semispace.py pypy/dist/pypy/rpython/memory/gctransform/framework.py pypy/dist/pypy/rpython/memory/gcwrapper.py pypy/dist/pypy/rpython/memory/test/snippet.py pypy/dist/pypy/translator/c/gc.py pypy/dist/pypy/translator/c/src/mem.h pypy/dist/pypy/translator/c/test/test_boehm.py Log: Add and implement rlib.rgc.{disable,enable}_finalizers(). Modified: pypy/dist/pypy/rlib/rgc.py ============================================================================== --- pypy/dist/pypy/rlib/rgc.py (original) +++ pypy/dist/pypy/rlib/rgc.py Tue Apr 8 22:48:25 2008 @@ -11,6 +11,15 @@ """ pass +def disable_finalizers(): + """Prevent __del__ methods from running. + Calls to disable_finalizers/enable_finalizers can be nested. + """ + gc.disable() # rough approximation on top of CPython + +def enable_finalizers(): + gc.enable() # rough approximation on top of CPython + # ____________________________________________________________ # Framework GC features @@ -162,3 +171,14 @@ [v_nbytes] = hop.inputargs(lltype.Signed) return hop.genop('gc_set_max_heap_size', [v_nbytes], resulttype=lltype.Void) + +class CollectEntry(ExtRegistryEntry): + _about_ = (disable_finalizers, enable_finalizers) + + def compute_result_annotation(self): + from pypy.annotation import model as annmodel + return annmodel.s_None + + def specialize_call(self, hop): + opname = 'gc__' + self.instance.__name__ + return hop.genop(opname, [], resulttype=hop.r_result) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue Apr 8 22:48:25 2008 @@ -753,6 +753,12 @@ def op_gc__collect(self): self.heap.collect() + def op_gc__disable_finalizers(self): + self.heap.disable_finalizers() + + def op_gc__enable_finalizers(self): + self.heap.enable_finalizers() + def op_gc_free(self, addr): # what can you do? pass @@ -836,7 +842,7 @@ def op_raw_malloc(self, size): assert lltype.typeOf(size) == lltype.Signed - return self.heap.raw_malloc(size) + return llmemory.raw_malloc(size) op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc @@ -848,20 +854,20 @@ def op_raw_malloc_usage(self, size): assert lltype.typeOf(size) == lltype.Signed - return self.heap.raw_malloc_usage(size) + return llmemory.raw_malloc_usage(size) def op_raw_free(self, addr): checkadr(addr) - self.heap.raw_free(addr) + llmemory.raw_free(addr) def op_raw_memclear(self, addr, size): checkadr(addr) - self.heap.raw_memclear(addr, size) + llmemory.raw_memclear(addr, size) def op_raw_memcopy(self, fromaddr, toaddr, size): checkadr(fromaddr) checkadr(toaddr) - self.heap.raw_memcopy(fromaddr, toaddr, size) + llmemory.raw_memcopy(fromaddr, toaddr, size) def op_raw_load(self, addr, typ, offset): checkadr(addr) Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llheap.py Tue Apr 8 22:48:25 2008 @@ -1,14 +1,11 @@ # only for the LLInterpreter. Don't use directly. from pypy.rpython.lltypesystem.lltype import pyobjectptr, malloc, free, typeOf -from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free -from pypy.rpython.lltypesystem.llmemory import raw_memclear, raw_memcopy -from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage, \ - weakref_create, weakref_deref +from pypy.rpython.lltypesystem.llmemory import weakref_create, weakref_deref setfield = setattr from operator import setitem as setarrayitem -from gc import collect +from pypy.rlib.rgc import collect, disable_finalizers, enable_finalizers def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue): assert typeOf(newvalue) == INNERTYPE Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Tue Apr 8 22:48:25 2008 @@ -387,6 +387,8 @@ # __________ GC operations __________ 'gc__collect': LLOp(canunwindgc=True), + 'gc__disable_finalizers': LLOp(), + 'gc__enable_finalizers': LLOp(canunwindgc=True), 'gc_free': LLOp(), 'gc_fetch_exception': LLOp(), 'gc_restore_exception': LLOp(), Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Tue Apr 8 22:48:25 2008 @@ -114,6 +114,12 @@ def x_clone(self, clonedata): raise RuntimeError("no support for x_clone in the GC") + def disable_finalizers(self): + pass # xxx this should really be implemented by all subclasses + + def enable_finalizers(self): + pass # xxx this should really be implemented by all subclasses + def trace(self, obj, callback, arg): """Enumerate the locations inside the given obj that can contain GC pointers. For each such location, callback(pointer, arg) is Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/dist/pypy/rpython/memory/gc/semispace.py Tue Apr 8 22:48:25 2008 @@ -524,17 +524,18 @@ self.run_finalizers = new_run_finalizer def execute_finalizers(self): - if self.finalizer_lock_count > 0: - return # the outer invocation of execute_finalizers() will do it - self.finalizer_lock_count = 1 + self.finalizer_lock_count += 1 try: while self.run_finalizers.non_empty(): #print "finalizer" + if self.finalizer_lock_count > 1: + # the outer invocation of execute_finalizers() will do it + break obj = self.run_finalizers.popleft() finalizer = self.getfinalizer(self.get_type_id(obj)) finalizer(obj) finally: - self.finalizer_lock_count = 0 + self.finalizer_lock_count -= 1 STATISTICS_NUMBERS = 0 Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Tue Apr 8 22:48:25 2008 @@ -217,6 +217,10 @@ + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref) self.collect_ptr = getfn(GCClass.collect.im_func, [s_gc], annmodel.s_None) + self.disable_finalizers_ptr = getfn(GCClass.disable_finalizers.im_func, + [s_gc], annmodel.s_None) + self.enable_finalizers_ptr = getfn(GCClass.enable_finalizers.im_func, + [s_gc], annmodel.s_None) # in some GCs we can inline the common case of # malloc_fixedsize(typeid, size, True, False, False) @@ -526,6 +530,21 @@ resultvar=op.result) self.pop_roots(hop, livevars) + def gct_gc__disable_finalizers(self, hop): + # cannot collect() + op = hop.spaceop + hop.genop("direct_call", [self.disable_finalizers_ptr, + self.c_const_gc], + resultvar=op.result) + + def gct_gc__enable_finalizers(self, hop): + # can collect() because it typically calls pending finalizers + op = hop.spaceop + livevars = self.push_roots(hop) + hop.genop("direct_call", [self.enable_finalizers_ptr, self.c_const_gc], + resultvar=op.result) + self.pop_roots(hop, livevars) + def gct_gc_x_swap_pool(self, hop): op = hop.spaceop [v_malloced] = op.args Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/dist/pypy/rpython/memory/gcwrapper.py Tue Apr 8 22:48:25 2008 @@ -81,6 +81,12 @@ def collect(self): self.gc.collect() + def disable_finalizers(self): + self.gc.disable_finalizers() + + def enable_finalizers(self): + self.gc.enable_finalizers() + def weakref_create_getlazy(self, objgetter): # we have to be lazy in reading the llinterp variable containing # the 'obj' pointer, because the gc.malloc() call below could Modified: pypy/dist/pypy/rpython/memory/test/snippet.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/snippet.py (original) +++ pypy/dist/pypy/rpython/memory/test/snippet.py Tue Apr 8 22:48:25 2008 @@ -1,9 +1,15 @@ +import os +from pypy.tool.udir import udir from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop class SemiSpaceGCTests: large_tests_ok = False + def run_ok(self, f): + res = self.run(f) + assert res == 'ok' + def test_finalizer_order(self): import random from pypy.tool.algo import graphlib @@ -119,3 +125,53 @@ print summary print msg py.test.fail(msg) + + def test_disable_finalizers(self): + from pypy.rlib import rgc + if self.large_tests_ok: + MULTIPLY = 50 + else: + MULTIPLY = 1 + + tmpfilepath = udir.join('test_disable_finalizers') + + class State: + pass + state = State() + state.tmpfilename = str(tmpfilepath) + state.fd = -1 + + class X(object): + def __init__(self, x): + self.x = str(x) + def __del__(self): + if state.fd >= 0: + os.write(state.fd, self.x) + + def do_stuff(): + lst = [X(n) for n in range(7*MULTIPLY)] + return len(lst) + + def f(): + fd = os.open(state.tmpfilename, + os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + 0644) + state.fd = fd + for i in range(10*MULTIPLY): + do_stuff() + rgc.disable_finalizers() + os.write(fd, '-') + do_stuff() + os.write(fd, '+') + rgc.enable_finalizers() + state.fd = -1 + os.close(fd) + return 'ok' + + self.run_ok(f) + buf = tmpfilepath.read() + assert buf.count('-') == buf.count('+') + assert buf.count('-') + buf.count('+') < len(buf) + for i in range(len(buf)): + if buf[i] == '-': + assert buf[i+1] == '+' Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Tue Apr 8 22:48:25 2008 @@ -134,6 +134,12 @@ def OP_GC__COLLECT(self, funcgen, op): return '' + def OP_GC__DISABLE_FINALIZERS(self, funcgen, op): + return '' + + def OP_GC__ENABLE_FINALIZERS(self, funcgen, op): + return '' + class RefcountingRuntimeTypeInfo_OpaqueNode(ContainerNode): nodekind = 'refcnt rtti' Modified: pypy/dist/pypy/translator/c/src/mem.h ============================================================================== --- pypy/dist/pypy/translator/c/src/mem.h (original) +++ pypy/dist/pypy/translator/c/src/mem.h Tue Apr 8 22:48:25 2008 @@ -131,20 +131,29 @@ else \ GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) +extern int boehm_gc_finalizer_lock; void boehm_gc_startup_code(void); +void boehm_gc_finalizer_notifier(void); + +#define OP_GC__DISABLE_FINALIZERS(r) boehm_gc_finalizer_lock++ +#define OP_GC__ENABLE_FINALIZERS(r) (boehm_gc_finalizer_lock--, \ + boehm_gc_finalizer_notifier()) #ifndef PYPY_NOT_MAIN_FILE -static void boehm_gc_finalizer_notifier(void) +int boehm_gc_finalizer_lock = 0; +void boehm_gc_finalizer_notifier(void) { - static int recursing = 0; - if (recursing) - return; /* GC_invoke_finalizers() will be done by the - boehm_gc_finalizer_notifier() that is - currently in the C stack, when we return there */ - recursing = 1; - while (GC_should_invoke_finalizers()) + boehm_gc_finalizer_lock++; + while (GC_should_invoke_finalizers()) { + if (boehm_gc_finalizer_lock > 1) { + /* GC_invoke_finalizers() will be done by the + boehm_gc_finalizer_notifier() that is + currently in the C stack, when we return there */ + break; + } GC_invoke_finalizers(); - recursing = 0; + } + boehm_gc_finalizer_lock--; } void boehm_gc_startup_code(void) { Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Tue Apr 8 22:48:25 2008 @@ -1,6 +1,7 @@ import py from pypy.translator.translator import TranslationContext from pypy.rpython.lltypesystem import lltype +from pypy.rpython.memory.test import snippet from pypy.translator.tool.cbuild import check_boehm_presence from pypy.translator.c.genc import CExtModuleBuilder from pypy import conftest @@ -365,3 +366,16 @@ c_fn = self.getcompiled(fn, [int]) res = c_fn(10000) assert res == 0 + + # reusing some tests from pypy.rpython.memory.test.snippet + large_tests_ok = True + + def run_ok(self, f): + def wrapper(): + return int(f() == 'ok') + c_fn = self.getcompiled(wrapper, []) + res = c_fn() + assert res == 1 + + test_disable_finalizers = ( + snippet.SemiSpaceGCTests.test_disable_finalizers.im_func) From arigo at codespeak.net Tue Apr 8 22:48:42 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 22:48:42 +0200 (CEST) Subject: [pypy-svn] r53597 - in pypy/dist/pypy/module/gc: . test Message-ID: <20080408204842.75EAB16AF9D@codespeak.net> Author: arigo Date: Tue Apr 8 22:48:41 2008 New Revision: 53597 Modified: pypy/dist/pypy/module/gc/__init__.py pypy/dist/pypy/module/gc/app_gc.py pypy/dist/pypy/module/gc/interp_gc.py pypy/dist/pypy/module/gc/test/test_gc.py Log: App-level interface to {disable,enable}_finalizers(). Modified: pypy/dist/pypy/module/gc/__init__.py ============================================================================== --- pypy/dist/pypy/module/gc/__init__.py (original) +++ pypy/dist/pypy/module/gc/__init__.py Tue Apr 8 22:48:41 2008 @@ -8,5 +8,7 @@ } interpleveldefs = { 'collect': 'interp_gc.collect', + 'enable_finalizers': 'interp_gc.enable_finalizers', + 'disable_finalizers': 'interp_gc.disable_finalizers', 'estimate_heap_size': 'interp_gc.estimate_heap_size', } Modified: pypy/dist/pypy/module/gc/app_gc.py ============================================================================== --- pypy/dist/pypy/module/gc/app_gc.py (original) +++ pypy/dist/pypy/module/gc/app_gc.py Tue Apr 8 22:48:41 2008 @@ -1,6 +1,6 @@ def isenabled(): - "Not implemented." + return True def enable(): "Not implemented." Modified: pypy/dist/pypy/module/gc/interp_gc.py ============================================================================== --- pypy/dist/pypy/module/gc/interp_gc.py (original) +++ pypy/dist/pypy/module/gc/interp_gc.py Tue Apr 8 22:48:41 2008 @@ -1,14 +1,36 @@ from pypy.interpreter.gateway import ObjSpace from pypy.interpreter.error import OperationError -from pypy.rlib import rgc # Force registration of gc.collect -import gc +from pypy.rlib import rgc def collect(space): "Run a full collection." - gc.collect() + rgc.collect() collect.unwrap_spec = [ObjSpace] +class State: + def __init__(self, space): + self.finalizers_lock_count = 0 +def getstate(space): + return space.fromcache(State) + +def enable_finalizers(space): + state = getstate(space) + if state.finalizers_lock_count == 0: + raise OperationError(space.w_ValueError, + space.wrap("finalizers are already enabled")) + state.finalizers_lock_count -= 1 + rgc.enable_finalizers() +enable_finalizers.unwrap_spec = [ObjSpace] + +def disable_finalizers(space): + state = getstate(space) + rgc.disable_finalizers() + state.finalizers_lock_count += 1 +disable_finalizers.unwrap_spec = [ObjSpace] + +# ____________________________________________________________ + import sys platform = sys.platform Modified: pypy/dist/pypy/module/gc/test/test_gc.py ============================================================================== --- pypy/dist/pypy/module/gc/test/test_gc.py (original) +++ pypy/dist/pypy/module/gc/test/test_gc.py Tue Apr 8 22:48:41 2008 @@ -3,6 +3,20 @@ import gc gc.collect() # mostly a "does not crash" kind of test + def test_disable_finalizers(self): + # on top of PyPy we can't easily test this, except by using + # obsure hacks, so for now we'll live with a "does not crash" + # kind of test + import gc + gc.disable_finalizers() + gc.enable_finalizers() + # we can test that nesting appears to work + gc.disable_finalizers() + gc.disable_finalizers() + gc.enable_finalizers() + gc.enable_finalizers() + raises(ValueError, gc.enable_finalizers) + def test_estimate_heap_size(self): import sys, gc if sys.platform == "linux2": From arigo at codespeak.net Tue Apr 8 22:52:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Apr 2008 22:52:10 +0200 (CEST) Subject: [pypy-svn] r53598 - pypy/dist/pypy/module/posix Message-ID: <20080408205210.22BAA16AFC7@codespeak.net> Author: arigo Date: Tue Apr 8 22:52:09 2008 New Revision: 53598 Modified: pypy/dist/pypy/module/posix/app_posix.py Log: Use gc.disable_finalizers() in the implementation of os.popen() in order to fix the warnings about invalid file descriptors in file.__del__. Probably fixes other subtle destructor issues related to this usage of os.fork(). Modified: pypy/dist/pypy/module/posix/app_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/app_posix.py (original) +++ pypy/dist/pypy/module/posix/app_posix.py Tue Apr 8 22:52:09 2008 @@ -91,7 +91,7 @@ Open a pipe to/from a command returning a file object.""" from popen2 import MAXFD - import os + import os, gc def try_close(fd): try: @@ -103,22 +103,26 @@ raise ValueError("invalid mode %r" % (mode,)) read_end, write_end = os.pipe() try: - childpid = os.fork() - if childpid == 0: - # in the child - try: - if mode.startswith('r'): - os.dup2(write_end, 1) - os.close(read_end) - else: - os.dup2(read_end, 0) - os.close(write_end) - for i in range(3, MAXFD): # XXX this loop can be slow - try_close(i) - cmd = ['/bin/sh', '-c', command] - os.execvp(cmd[0], cmd) - finally: - os._exit(1) + gc.disable_finalizers() + try: + childpid = os.fork() + if childpid == 0: + # in the child + try: + if mode.startswith('r'): + os.dup2(write_end, 1) + os.close(read_end) + else: + os.dup2(read_end, 0) + os.close(write_end) + for i in range(3, MAXFD): # XXX this loop can be slow + try_close(i) + cmd = ['/bin/sh', '-c', command] + os.execvp(cmd[0], cmd) + finally: + os._exit(1) + finally: + gc.enable_finalizers() if mode.startswith('r'): os.close(write_end) From pypy-svn at codespeak.net Wed Apr 9 10:54:25 2008 From: pypy-svn at codespeak.net (pypy-svn at codespeak.net) Date: Wed, 9 Apr 2008 10:54:25 +0200 (CEST) Subject: [pypy-svn] Gucci 9756947 Message-ID: <20080409135313.2885.qmail@magistr-neruhomist.dp.sovam.net.ua> An HTML attachment was scrubbed... URL: From cfbolz at codespeak.net Wed Apr 9 11:23:37 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Apr 2008 11:23:37 +0200 (CEST) Subject: [pypy-svn] r53601 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409092337.BD8B439B6D9@codespeak.net> Author: cfbolz Date: Wed Apr 9 11:23:36 2008 New Revision: 53601 Added: pypy/extradoc/talk/rupy2008/notes.txt (contents, props changed) Modified: pypy/extradoc/talk/rupy2008/bio.txt Log: my bio, some notes Modified: pypy/extradoc/talk/rupy2008/bio.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/bio.txt (original) +++ pypy/extradoc/talk/rupy2008/bio.txt Wed Apr 9 11:23:36 2008 @@ -5,3 +5,10 @@ for several tasks in the PyPy EU research project. He gave talks at international European and US Python community conferences. +Carl Friedrich Bolz is one of the core developers of PyPy. He is studying +computer science at the University of D?sseldorf. Currently he is working on +his Master's thesis, which is about making PyPy as fast as possible and proving +that dynamic languages can be almost as fast as static ones. In his spare time +he plays the bassoon. + + Added: pypy/extradoc/talk/rupy2008/notes.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/rupy2008/notes.txt Wed Apr 9 11:23:36 2008 @@ -0,0 +1,41 @@ + +Introduction: + + - A flexible toolkit for writing interpreters + - gives you lots of amenities, GC, multiplatform, JIT, common libraries + + - Containing a full Python interpreter + - cool extra features, lazy evaluation, stackless, ... + + + +Status: + + - Last year's developments: + - cleanups: + - getting rid of unmaintainable features + - unicode support in RPython + + - a much better GC, generational + - started a ctypes implementation + - .NET integration + - tons of performance tweaks + + - GCs: + + + +Next Goals: + + - JIT + - overview + - rewrite currently happening + - a Master thesis and a Ph.D. about this in progress + - we are starting to hit the hard bits that need real research + + - some imaginable performance tweaks missing + - approaching real-world usefulness + - + + + From arigo at codespeak.net Wed Apr 9 11:30:00 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 11:30:00 +0200 (CEST) Subject: [pypy-svn] r53602 - in pypy/dist/lib-python: . modified-2.4.1 Message-ID: <20080409093000.6263D169F73@codespeak.net> Author: arigo Date: Wed Apr 9 11:29:58 2008 New Revision: 53602 Added: pypy/dist/lib-python/modified-2.4.1/popen2.py - copied, changed from r53592, pypy/dist/lib-python/2.4.1/popen2.py pypy/dist/lib-python/modified-2.4.1/subprocess.py - copied, changed from r53592, pypy/dist/lib-python/2.4.1/subprocess.py Modified: pypy/dist/lib-python/conftest.py Log: Use gc.disable_finalizers() around the fork() calls in the standard library. Modified: pypy/dist/lib-python/conftest.py ============================================================================== --- pypy/dist/lib-python/conftest.py (original) +++ pypy/dist/lib-python/conftest.py Wed Apr 9 11:29:58 2008 @@ -681,7 +681,7 @@ RegrTest('test_struct.py', enabled=True, dumbtest=1, usemodules='struct'), RegrTest('test_structseq.py', enabled=False, dumbtest=1), - RegrTest('test_subprocess.py', enabled=False), + RegrTest('test_subprocess.py', enabled=False, usemodules='signal'), RegrTest('test_sunaudiodev.py', enabled=False, dumbtest=1), RegrTest('test_sundry.py', enabled=False, dumbtest=1), # test_support is not a test From arigo at codespeak.net Wed Apr 9 11:53:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 11:53:37 +0200 (CEST) Subject: [pypy-svn] r53603 - in pypy/dist/pypy/module/posix: . test Message-ID: <20080409095337.A82D5169F9A@codespeak.net> Author: arigo Date: Wed Apr 9 11:53:37 2008 New Revision: 53603 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: Implement os.abort(). Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Wed Apr 9 11:53:37 2008 @@ -60,6 +60,7 @@ interpleveldefs['unsetenv'] = 'interp_posix.unsetenv' if hasattr(os, 'kill'): interpleveldefs['kill'] = 'interp_posix.kill' + interpleveldefs['abort'] = 'interp_posix.abort' if hasattr(os, 'getpid'): interpleveldefs['getpid'] = 'interp_posix.getpid' if hasattr(os, 'link'): 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 Wed Apr 9 11:53:37 2008 @@ -408,6 +408,13 @@ raise wrap_oserror(space, e) kill.unwrap_spec = [ObjSpace, int, int] +def abort(space): + """Abort the interpreter immediately. This 'dumps core' or otherwise fails +in the hardest way possible on the hosting operating system.""" + import signal + os.kill(os.getpid(), signal.SIGABRT) +abort.unwrap_spec = [ObjSpace] + def link(space, src, dst): "Create a hard link to a file." try: 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 Wed Apr 9 11:53:37 2008 @@ -6,6 +6,7 @@ import os import py import sys +import signal def setup_module(mod): mod.space = gettestobjspace(usemodules=['posix']) @@ -42,6 +43,7 @@ cls.w_sysconf_name = space.wrap(sysconf_name) cls.w_sysconf_value = space.wrap(os.sysconf_names[sysconf_name]) cls.w_sysconf_result = space.wrap(os.sysconf(sysconf_name)) + cls.w_SIGABRT = space.wrap(signal.SIGABRT) def setup_method(self, meth): if getattr(meth, 'need_sparse_files', False): @@ -189,7 +191,8 @@ os._exit(4) pid1, status1 = os.waitpid(pid, 0) assert pid1 == pid - # XXX check status1 + assert os.WIFEXITED(status1) + assert os.WEXITSTATUS(status1) == 4 pass # <- please, inspect.getsource(), don't crash if hasattr(__import__(os.name), "execv"): @@ -362,6 +365,19 @@ assert data == 'X' os.close(fd) + if hasattr(__import__(os.name), "fork"): + def test_abort(self): + os = self.posix + pid = os.fork() + if pid == 0: + os.abort() + pid1, status1 = os.waitpid(pid, 0) + assert pid1 == pid + assert os.WIFSIGNALED(status1) + assert os.WTERMSIG(status1) == self.SIGABRT + pass # <- please, inspect.getsource(), don't crash + + class AppTestEnvironment(object): def setup_class(cls): cls.space = space From arigo at codespeak.net Wed Apr 9 12:17:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 12:17:38 +0200 (CEST) Subject: [pypy-svn] r53605 - pypy/branch/jit-hotpath/pypy/jit/codegen/i386 Message-ID: <20080409101738.C5E962A00E2@codespeak.net> Author: arigo Date: Wed Apr 9 12:17:38 2008 New Revision: 53605 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/operation.py pypy/branch/jit-hotpath/pypy/jit/codegen/i386/regalloc.py pypy/branch/jit-hotpath/pypy/jit/codegen/i386/rgenop.py Log: Add the missing getkind() methods to the GenVar subclasses. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/operation.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/i386/operation.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/i386/operation.py Wed Apr 9 12:17:38 2008 @@ -9,7 +9,7 @@ from pypy.objspace.std.multimethod import FailedToImplement from pypy.jit.codegen.i386.ri386 import * from pypy.jit.codegen.i386.ri386setup import Conditions -from pypy.jit.codegen.model import GenVar +from pypy.jit.codegen import model as codegenmodel WORD = 4 # bytes @@ -19,7 +19,11 @@ CALL_ALIGN = 1 -class Operation(GenVar): +class GenVar386(codegenmodel.GenVar): + def getkind(self): + return None + +class Operation(GenVar386): clobbers_cc = True side_effects = True Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/regalloc.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/i386/regalloc.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/i386/regalloc.py Wed Apr 9 12:17:38 2008 @@ -553,7 +553,7 @@ def generate(self, allocator): pass dead_operation = DeadOperation() -gv_frame_base = GenVar() +gv_frame_base = GenVar386() class Place(Operation): """Place of a variable that must live in the stack. Its position is Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/i386/rgenop.py Wed Apr 9 12:17:38 2008 @@ -3,7 +3,7 @@ from pypy.rlib.objectmodel import specialize, we_are_translated 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.model import GenConst, CodeGenSwitch from pypy.jit.codegen.model import ReplayBuilder, dummy_var from pypy.jit.codegen.i386.codebuf import CodeBlockOverflow from pypy.jit.codegen.i386.operation import * @@ -251,7 +251,7 @@ self.graphctx.ensure_stack_vars(allocator.nstackmax) del self.operations[:] if renaming: - self.inputargs_gv = [GenVar() for v in final_vars_gv] + self.inputargs_gv = [GenVar386() for v in final_vars_gv] else: # just keep one copy of each Variable that is alive self.inputargs_gv = final_vars_gv @@ -617,7 +617,7 @@ inputargs_gv = [] inputoperands = [] for i in range(numargs): - inputargs_gv.append(GenVar()) + inputargs_gv.append(GenVar386()) ofs = WORD * (GraphCtx.PROLOGUE_FIXED_WORDS+i) inputoperands.append(mem(ebp, ofs)) builder = Builder(self, graphctx, inputargs_gv, inputoperands) From cfbolz at codespeak.net Wed Apr 9 16:02:01 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Apr 2008 16:02:01 +0200 (CEST) Subject: [pypy-svn] r53614 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409140201.BC68116A178@codespeak.net> Author: cfbolz Date: Wed Apr 9 16:02:00 2008 New Revision: 53614 Added: pypy/extradoc/talk/rupy2008/Makefile pypy/extradoc/talk/rupy2008/Pypy architecture.odp - copied unchanged from r53237, pypy/extradoc/talk/roadshow-google/Pypy architecture.odp pypy/extradoc/talk/rupy2008/beamerouterthememy.sty - copied unchanged from r53237, pypy/extradoc/talk/dyla2007/beamerouterthememy.sty pypy/extradoc/talk/rupy2008/beamerthemeWarsaw.sty - copied unchanged from r53237, pypy/extradoc/talk/dyla2007/beamerthemeWarsaw.sty pypy/extradoc/talk/rupy2008/talk.tex Modified: pypy/extradoc/talk/rupy2008/notes.txt Log: first draft of the slides Added: pypy/extradoc/talk/rupy2008/Makefile ============================================================================== --- (empty file) +++ pypy/extradoc/talk/rupy2008/Makefile Wed Apr 9 16:02:00 2008 @@ -0,0 +1,11 @@ +%.pdf: %.eps + epstopdf $< + +viewtalk: talk.pdf + evince talk.pdf & + +clean: + rm dyla.pdf talk.pdf + +talk.pdf: talk.tex beamerouterthememy.sty beamerthemeWarsaw.sty + pdflatex talk Modified: pypy/extradoc/talk/rupy2008/notes.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/notes.txt (original) +++ pypy/extradoc/talk/rupy2008/notes.txt Wed Apr 9 16:02:00 2008 @@ -1,12 +1,11 @@ -Introduction: - - A flexible toolkit for writing interpreters - - gives you lots of amenities, GC, multiplatform, JIT, common libraries - - - Containing a full Python interpreter - - cool extra features, lazy evaluation, stackless, ... +Overview Slides +Demos: + - simple pypy-c prompt + - pypy-cli windows forms demo + - reflective object space (test_add) Status: @@ -17,25 +16,62 @@ - unicode support in RPython - a much better GC, generational - - started a ctypes implementation + - a ctypes implementation - .NET integration - - tons of performance tweaks - - - GCs: - + - cleanups: + - over the EU project a lot of features accumulated that were required by our proposal + - not all of them were implemented well + - all of them were unmaintained + - they were preventing progress in other areas + - so we killed them + - many other improvements on all levels, e.g. RPython support for Unicode + + - ctypes: + - CTypes is a libffi wrapper for CPython + - implemented in C + - can be used to wrap C libraries rather effortlessly + - CTypes implementation for PyPy: + - two parts + - a very thin wrapper around libffi + - normal Python code for all the CTypes logic + - some things missing but already very useful + - ... demo -Next Goals: - - - JIT - - overview - - rewrite currently happening - - a Master thesis and a Ph.D. about this in progress - - we are starting to hit the hard bits that need real research - - - some imaginable performance tweaks missing - - approaching real-world usefulness - - - + - GCs: + - completely written in Python + - similar to the MMTK toolkit of Jikes RVM + - two fast GCs: semispace, generational + - lots of care to get the semantics right, e.g. of weakrefs and finalizers + - performance pretty good, memory-bound benchmarks faster than CPython + despite our bigger memory needs + - demo (id(x)) + + - Currently Working on: JIT Generation + - writing good JITs for dynamic languages is hard work + - not really many good JITs around: + - Psyco (unmaintained) + - LuaJit (slightly simpler language, genius at work) + - Tamarin (company support, who knows how good it is) + + - keeping up with new language features is hard + - compilers are a bad encoding for languag semantics + - idea: automatically generate the JIT from an interpreter + + - JIT Generation Ideas + - partial evaluation: old idea from CS research + - usually in a static compiler context + - never worked well on real-life examples + - key insight: things become *easier* if you generate JITs instead of static compilers + + - JIT Generation: Current Status + - a working prototype at the end of the EU project + - speeds up simple arithmetic functions *a lot* + - had limitations that were hard to fix with the design + - refactoring happened in the last two months to improve the situation + - still in progress, but already allows experimentation + - starting to hit the hard bits + - we hope to get really good results for more general code in a few months + - demo Added: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/rupy2008/talk.tex Wed Apr 9 16:02:00 2008 @@ -0,0 +1,296 @@ +\documentclass[utf8x]{beamer} + +\mode +{ + \usetheme{Warsaw} + + %\setbeamercovered{transparent} +} + + +\usepackage[english]{babel} + +\usepackage[utf8x]{inputenc} + +\usepackage{times} +\usepackage[T1]{fontenc} + +\title{PyPy ? status and next goals} + +\author{Carl Friedrich Bolz} + +\institute[Heinrich-Heine-Universit?t D?sseldorf] +{ + Institut f?r Informatik\\ + Heinrich-Heine-Universit?t D?sseldorf +} + +\date{Ruby \& Python Conference, April 12th 2008, Pozna?} + +%\pgfdeclareimage[height=0.5cm]{pypy-logo}{image/py-web.png} +%\logo{\pgfuseimage{pypy-logo}} + + + +% Delete this, if you do not want the table of contents to pop up at +% the beginning of each subsection: +%\AtBeginSubsection[] +%{ +% \begin{frame} +% \frametitle{Outline} +% \tableofcontents[currentsection,currentsubsection] +% \end{frame} +%} + + +% If you wish to uncover everything in a step-wise fashion, uncomment +% the following command: + +%\beamerdefaultoverlayspecification{<+->} + + +\begin{document} + +\begin{frame} + \titlepage +\end{frame} + +%\begin{frame} +% \frametitle{Outline} +% \tableofcontents + % You might wish to add the option [pausesections] +%\end{frame} + +\begin{frame} + \frametitle{What is PyPy?} + \begin{itemize} + \item + A flexible toolkit for writing interpreters + \begin{itemize} + \item + giving you lots of ameninities + \item + translation to lots of environments + \item + a mostly good GC + \item + libraries + \item + a JIT + \end{itemize} + \pause + \item + the biggest implemented interpreter is a full Python interpreter + \begin{itemize} + \item + implementing Python 2.4 semantics fully + \item + extra features + \item + lazy evaluation + \item + stackless + \item + various introspection enhancements + \end{itemize} + \item + Open Source project (MIT licenced) + \end{itemize} +\end{frame} + + +\begin{frame} + \frametitle{What is PyPy} + ... pretty pictures and demos +\end{frame} + + + + +\begin{frame} + \frametitle{Last year's developments} + \begin{itemize} + \item + cleanups + \item + implementing ctypes + \item + .NET integration + \item + GC improvements + \item + JIT improvements + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Cleanups} + \begin{itemize} + \item PyPy got EU funding for 2.5 years + \item in that time many features were added because the proposal required them + \item not all of them were implemented well + \item many of them were unmaintained + \item some of them were preventing progress in other areas + \item so we killed those + \item improvements and cleanups everywhere, to get ready for the next round of features + \item example: better implementation for unicode strings + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{CTypes} + \begin{itemize} + \item CTypes is a libffi wrapper for CPython + \item implemented in C + \item can be used to wrap C libraries rather effortlessly + \item no need to write C code to interface with libraries + + \end{itemize} + \pause + \begin{block}{ + CTypes implementation for PyPy} + \begin{itemize} + \item two parts + \item a very thin wrapper around libffi + \item normal Python code for all the CTypes logic + \item some things missing but already very useful + \item ... demo + \end{itemize} + \end{block} +\end{frame} + + +\begin{frame} + \frametitle{.NET Integration} + \begin{itemize} + \item giving PyPy.NET similar capabilities as CPython + \item accessing .NET libraries seamlessly from PyPy + \item ... demo + \end{itemize} +\end + + +\begin{frame} + \frametitle{Garbage Collection} + \begin{itemize} + \item RPython itself is garbage collected + \item when translating to C, a GC is woven into the program + \item GCs are completely written in Python + \item similar to the MMTK toolkit of Jikes RVM + \item two fast GCs: semispace, generational + \item lots of care to get the semantics right: + \begin{itemize} + \item finalizers, weakrefs + \item id function + \item identity hashes + \end{itemize} + \item performance pretty good + \item memory-bound benchmarks faster than CPython + \item demo (id(x)) + \end{itemize} +\end{frame} + + +\begin{frame} + \frametitle{Currently Working on: Just-in-Time Compiler} + Problems: + \begin{itemize} + \item writing good JITs for dynamic languages is hard work + \item keeping up with new language features is hard + \item compilers are a bad encoding for languag semantics + \pause + \begin{block}{ + Existing hand-written JITs} + \begin{itemize} + \item Psyco (mostly unmaintained) + \item LuaJit (slightly simpler language, genius at work) + \item Tamarin (company support, who knows how good it is) + \end{itemize} + \end{block} + \end{itemize} + \pause +\end{frame} + +\begin{frame} + \frametitle{If you cannot write them, grow your own} + \begin{itemize} + \item If you cannot write a JIT, don't do that then + \pause + \item Idea: Automatically Generate the JIT from the interpreter + \pause + \end{itemize} + \begin{block}{ + Partial Evaluation} + \begin{itemize} + \item old idea from CS research + \item transforms an interpreter into a static compiler + \item never worked well for real-life examples + \item key insight: generating a JIT is \emph{easier} + \end{itemize} + \end{block} + +\end{frame} + +\begin{frame} + \frametitle{Advantages of JIT Generation} + Writing a JIT generator is hard, but: + \begin{itemize} + \item You only need to do it once + \item the effort of writing a JIT generator is independent of the size of the language + \item can keep up with language evolution + \item XXX + \item it's fun too + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{JIT Generation: Current Status} + \begin{itemize} + \item we had a working prototype at the end of the EU project + \item speeds up simple arithmetic functions \emph{a lot} + \item had limitations that were hard to fix with + \pause + \item refactoring happened in the last two months to improve the situation + \item still in progress, but already allows experimentation + \item we used the new flexibility to try new, advanced things + \item goes into the direction of a tracing JIT + \item right now we are starting to hit the hard bits + \item we hope to get really good results for more general code in a few months + \item ... demo + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Conclusion} + \begin{itemize} + \item PyPy approaching real world usefulness + \item using CTypes to interface with the outside + \item hopefully with a JIT soon + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Help Wanted!} + we are looking for new contributors! + \begin{itemize} + \item try out your own apps that don't require extension modules + \item use CTypes to implement missing modules + \item experiment with extending Python (logic, distribution, what suits you) + \item write a new JIT backend (x86-64 anyone?) + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Questions?} + \begin{block}{ + PyPy} + \bigskip + \hskip 1cm \url{http://codespeak.net/pypy/} + \bigskip + \end{block} +\end{frame} + + +\end{document} + + From arigo at codespeak.net Wed Apr 9 16:26:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 16:26:45 +0200 (CEST) Subject: [pypy-svn] r53616 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409142645.60C3916A1F9@codespeak.net> Author: arigo Date: Wed Apr 9 16:26:44 2008 New Revision: 53616 Modified: pypy/extradoc/talk/rupy2008/talk.tex Log: Typos. Minor clarification. Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Wed Apr 9 16:26:44 2008 @@ -167,7 +167,7 @@ \item accessing .NET libraries seamlessly from PyPy \item ... demo \end{itemize} -\end +\end{frame} \begin{frame} @@ -197,7 +197,7 @@ \begin{itemize} \item writing good JITs for dynamic languages is hard work \item keeping up with new language features is hard - \item compilers are a bad encoding for languag semantics + \item compilers are a bad encoding for language semantics \pause \begin{block}{ Existing hand-written JITs} @@ -225,7 +225,7 @@ \item old idea from CS research \item transforms an interpreter into a static compiler \item never worked well for real-life examples - \item key insight: generating a JIT is \emph{easier} + \item key insight: generating a JIT is \emph{easier} than a static compiler \end{itemize} \end{block} @@ -248,7 +248,7 @@ \begin{itemize} \item we had a working prototype at the end of the EU project \item speeds up simple arithmetic functions \emph{a lot} - \item had limitations that were hard to fix with + \item had limitations that were hard to fix \pause \item refactoring happened in the last two months to improve the situation \item still in progress, but already allows experimentation From cfbolz at codespeak.net Wed Apr 9 16:32:27 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Apr 2008 16:32:27 +0200 (CEST) Subject: [pypy-svn] r53617 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409143227.90FF92D800A@codespeak.net> Author: cfbolz Date: Wed Apr 9 16:32:26 2008 New Revision: 53617 Modified: pypy/extradoc/talk/rupy2008/talk.tex Log: mention anto, more advantages Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Wed Apr 9 16:32:26 2008 @@ -238,7 +238,8 @@ \item You only need to do it once \item the effort of writing a JIT generator is independent of the size of the language \item can keep up with language evolution - \item XXX + \item retargetting the JIT is possible (e.g. to .NET, as Antonio Cuni is doing right now) + \item make the JIT behave radically different is much easier with a generator \item it's fun too \end{itemize} \end{frame} From arigo at codespeak.net Wed Apr 9 16:34:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 16:34:22 +0200 (CEST) Subject: [pypy-svn] r53618 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409143422.6900A2D8006@codespeak.net> Author: arigo Date: Wed Apr 9 16:34:21 2008 New Revision: 53618 Modified: pypy/extradoc/talk/rupy2008/talk.tex Log: Typo Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Wed Apr 9 16:34:21 2008 @@ -239,7 +239,7 @@ \item the effort of writing a JIT generator is independent of the size of the language \item can keep up with language evolution \item retargetting the JIT is possible (e.g. to .NET, as Antonio Cuni is doing right now) - \item make the JIT behave radically different is much easier with a generator + \item make the JIT behave radically differently is much easier with a generator \item it's fun too \end{itemize} \end{frame} From cami at codespeak.net Wed Apr 9 18:28:07 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 9 Apr 2008 18:28:07 +0200 (CEST) Subject: [pypy-svn] r53619 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080409162807.C5F6D2D8006@codespeak.net> Author: cami Date: Wed Apr 9 18:28:05 2008 New Revision: 53619 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: restructuring added stubs for sound generater classes Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Wed Apr 9 18:28:05 2008 @@ -12,11 +12,11 @@ self.ram = RAM() self.cartridge = Cartridge(storeDriver, clockDriver) self.interrupt = Interrupt() - self.cpu = CPU(self.interrupt, this) + self.cpu = CPU(self.interrupt, self) self.serial = Serial(self.interrupt) self.timer = Timer(self.interrupt) self.joypad = Joypad(joypadDriver, self.interrupt) - self.video = Video(videoDriver, self.interrupt, this) + self.video = Video(videoDriver, self.interrupt, self) self.sound = Sound(soundDriver) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Wed Apr 9 18:28:05 2008 @@ -5,8 +5,7 @@ """ from pypy.lang.gameboy import constants - - + class Channel(object): # Audio Channel 1 int @@ -22,6 +21,16 @@ def __init__(self): pass +class SquareWaveGenerator(Channel): + pass + +class VoluntaryWaveGenerator(Channel): + pass + +class NoiseGenerator(Channel): + pass + + class Sound(object): @@ -149,13 +158,17 @@ while (self.cycles <= 0): self.updateAudio() if self.driver.isEnabled(): - self.frames += self.driver.getSampleRate() - length = (self.frames / constants.SOUND_CLOCK) << 1 - self.mixAudio(self.buffer, length) - self.driver.write(self.buffer, length) - self.frames %= constants.SOUND_CLOCK + self.mixDownAudio() self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK + + def mixDownAudio(self): + self.frames += self.driver.getSampleRate() + length = (self.frames / constants.SOUND_CLOCK) << 1 + self.mixAudio(self.buffer, length) + self.driver.write(self.buffer, length) + self.frames %= constants.SOUND_CLOCK + def read(self, address): if address==constants.NR10: return self.getAudio1Sweep() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Wed Apr 9 18:28:05 2008 @@ -6,13 +6,13 @@ from pypy.lang.gameboy import constants class Video(object): - frames = 0 - frameSkip = 0 + #frames = 0 + #frameSkip = 0 # Line Buffer, constants.OAM Cache and Color Palette - line = []#= new int[8 + 160 + 8] - objects = []#= new int[OBJECTS_PER_LINE] - palette = []#= new int[1024] + #line = []#= new int[8 + 160 + 8] + #objects = []#= new int[OBJECTS_PER_LINE] + #palette = []#= new int[1024] def __init__(self, videDriver, interrupt, memory): @@ -49,6 +49,13 @@ self.vram = [0]*constants.VRAM_SIZE self.oam = [0]*constants.OAM_SIZE + + self.line = [0]* (8+160+8) + self.objects = [0] * constants.OBJECTS_PER_LINE + self.palette = [0] * 1024 + + self.frames = 0 + self.frameSkip = 0 def write(self, address, data): # assert data >= 0x00 and data <= 0xFF @@ -78,13 +85,14 @@ elif address == constants.WX: self.setWindowX(data) else: - if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): - #TODO convert to byte - self.oam[address - constants.OAM_ADDR] = data - elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): - #TODO convert to byte - self.vram[address - constants.VRAM_ADDR] =data + self.writeOAM(address, data) + def writeOAM(self, address, data): + if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): + self.oam[address - constants.OAM_ADDR] = data & 0xFF + elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): + self.vram[address - constants.VRAM_ADDR] = data & 0xFF + def read(self, address): if address == constants.LCDC: return self.getControl() @@ -111,67 +119,48 @@ elif address == constants.WX: return self.getWindowX() else: - if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): - return self.oam[address - constants.OAM_ADDR] & 0xFF - elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): - return self.vram[address - constants.VRAM_ADDR] & 0xFF + return self.readOAM(address) + + + def readOAM(self, address): + if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): + return self.oam[address - constants.OAM_ADDR] + elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): + return self.vram[address - constants.VRAM_ADDR] return 0xFF - def cycles(self): + def getCycles(self): return self.cycles def emulate(self, ticks): if (self.control & 0x80) != 0: self.cycles -= ticks - while (self.cycles <= 0): - if self.stat == 0: - self.emulateHBlank() - elif self.stat == 1: - self.emulateVBlank() - elif self.stat == 2: - self.emulateOAM() - else: - self.emulateTransfer() + self.consumeCycles() + + def consumeCycles(self): + while (self.cycles <= 0): + if self.stat == 0: + self.emulateHBlank() + elif self.stat == 1: + self.emulateVBlank() + elif self.stat == 2: + self.emulateOAM() + else: + self.emulateTransfer() def getControl(self): return self.control - def getStatus(self): - return 0x80 | self.stat - - def getScrollY(self): - return self.scrollY - - def getScrollX(self): - return self.scrollX - - def getLineY(self): - return self.lineY - - def getLineYCompare(self): - return self.lineYCompare - - def getDMA(self): - return self.dma - - def getBackgroundPalette(self): - return self.backgroundPalette - - def getObjectPalette0(self): - return self.objectPalette0 - - def getObjectPalette1(self): - return self.objectPalette1 - - def getWindowY(self): - return self.windowY - - def getWindowX(self): - return self.windowX - def setControl(self, data): if (self.control & 0x80) != (data & 0x80): + self.resetControl(data) + # don't draw window if it was not enabled and not being drawn before + if ((self.control & 0x20) == 0 and (data & 0x20) != 0 and self.wlineY == 0 and self.lineY > self.windowY): + self.wlineY = 144 + self.control = data + + def resetControl(self, data): # NOTE: do not reset constants.LY=LYC flag (bit 2) of the STAT register (Mr. Do!) if (data & 0x80) != 0: self.stat = (self.stat & 0xFC) | 0x02 @@ -183,10 +172,9 @@ self.cycles = constants.MODE_1_TICKS self.lineY = 0 self.clearFrame() - # don't draw window if it was not enabled and not being drawn before - if ((self.control & 0x20) == 0 and (data & 0x20) != 0 and self.wlineY == 0 and self.lineY > self.windowY): - self.wlineY = 144 - self.control = data + + def getStatus(self): + return 0x80 | self.stat def setStatus(self, data): self.stat = (self.stat & 0x87) | (data & 0x78) @@ -194,11 +182,23 @@ if ((self.control & 0x80) != 0 and (self.stat & 0x03) == 0x01 and (self.stat & 0x44) != 0x44): self.interrupt.raiseInterrupt(constants.LCD) + def getScrollY(self): + return self.scrollY + def setScrollY(self, data): self.scrollY = data + + def getScrollX(self): + return self.scrollX def setScrollX(self, data): self.scrollX = data + + def getLineY(self): + return self.lineY + + def getLineYCompare(self): + return self.lineYCompare def setLYCompare(self, data): self.lineYCompare = data @@ -212,29 +212,48 @@ self.interrupt.raiseInterrupt(constants.LCD) else: self.stat &= 0xFB + + def getDMA(self): + return self.dma def setDMA(self, data): self.dma = data for index in range(0, constants.OAM_SIZE): self.oam[index] = self.memory.read((self.dma << 8) + index) + + def getBackgroundPalette(self): + return self.backgroundPalette + def setBackgroundPalette(self, data): if (self.backgroundPalette != data): self.backgroundPalette = data self.dirty = True + def getObjectPalette0(self): + return self.objectPalette0 + def setObjectPalette0(self, data): if (self.objectPalette0 != data): self.objectPalette0 = data self.dirty = True + def getObjectPalette1(self): + return self.objectPalette1 + def setObjectPalette1(self, data): if (self.objectPalette1 != data): self.objectPalette1 = data self.dirty = True + def getWindowY(self): + return self.windowY + def setWindowY(self, data): self.windowY = data + + def getWindowX(self): + return self.windowX def setWindowX(self, data): self.windowX = data From fijal at codespeak.net Wed Apr 9 19:11:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 19:11:28 +0200 (CEST) Subject: [pypy-svn] r53620 - pypy/branch/io-improvements Message-ID: <20080409171128.F05072D800A@codespeak.net> Author: fijal Date: Wed Apr 9 19:11:27 2008 New Revision: 53620 Added: pypy/branch/io-improvements/ - copied from r53619, pypy/dist/ Log: Create a branch to experiment with I/O and C-level communication From fijal at codespeak.net Wed Apr 9 20:07:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 20:07:01 +0200 (CEST) Subject: [pypy-svn] r53622 - in pypy/branch/io-improvements/pypy: rlib rlib/test rpython rpython/lltypesystem Message-ID: <20080409180701.00269498005@codespeak.net> Author: fijal Date: Wed Apr 9 20:07:01 2008 New Revision: 53622 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Log: First stub for rgc.can_move. Right now it always returns True Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Wed Apr 9 20:07:01 2008 @@ -171,6 +171,20 @@ [v_nbytes] = hop.inputargs(lltype.Signed) return hop.genop('gc_set_max_heap_size', [v_nbytes], resulttype=lltype.Void) +def can_move(P): + return True +can_move._annspecialcase_ = 'specialize:arg(0)' + +class CanMoveEntry(ExtRegistryEntry): + _about_ = can_move + + def compute_result_annotation(self, s_TP): + from pypy.annotation import model as annmodel + return annmodel.SomeBool() + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + return hop.genop('gc_can_move', [], resulttype=lltype.Bool) class CollectEntry(ExtRegistryEntry): _about_ = (disable_finalizers, enable_finalizers) @@ -182,3 +196,4 @@ def specialize_call(self, hop): opname = 'gc__' + self.instance.__name__ return hop.genop(opname, [], resulttype=hop.r_result) + Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Wed Apr 9 20:07:01 2008 @@ -1,4 +1,5 @@ from pypy.rpython.test.test_llinterp import gengraph, interpret +from pypy.rpython.lltypesystem import lltype from pypy.rlib import rgc # Force registration of gc.collect import gc @@ -17,3 +18,21 @@ assert res is None +def test_can_move(): + T0 = lltype.GcStruct('T') + T1 = lltype.GcArray(lltype.Float) + def f(i): + if i: + return rgc.can_move(T0) + else: + return rgc.can_move(T1) + + t, typer, graph = gengraph(f, [int]) + ops = list(graph.iterblockops()) + res = [op for op in ops if op[1].opname == 'gc_can_move'] + assert len(res) == 2 + + res = interpret(f, [1]) + + assert res == True + Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Wed Apr 9 20:07:01 2008 @@ -753,6 +753,9 @@ def op_gc__collect(self): self.heap.collect() + def op_gc_can_move(self): + return True + def op_gc__disable_finalizers(self): self.heap.disable_finalizers() Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Wed Apr 9 20:07:01 2008 @@ -399,6 +399,7 @@ 'gc_reload_possibly_moved': LLOp(), 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False), 'gc_set_max_heap_size': LLOp(), + 'gc_can_move' : LLOp(canfold=True, sideeffects=False), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), From arigo at codespeak.net Wed Apr 9 20:12:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 20:12:55 +0200 (CEST) Subject: [pypy-svn] r53623 - pypy/dist/pypy/rlib Message-ID: <20080409181255.B091B498005@codespeak.net> Author: arigo Date: Wed Apr 9 20:12:55 2008 New Revision: 53623 Modified: pypy/dist/pypy/rlib/rgc.py Log: The usual forgotten hop.exception_cannot_occur(). Modified: pypy/dist/pypy/rlib/rgc.py ============================================================================== --- pypy/dist/pypy/rlib/rgc.py (original) +++ pypy/dist/pypy/rlib/rgc.py Wed Apr 9 20:12:55 2008 @@ -157,6 +157,7 @@ return annmodel.s_None def specialize_call(self, hop): + hop.exception_cannot_occur() return hop.genop('gc__collect', [], resulttype=hop.r_result) class SetMaxHeapSizeEntry(ExtRegistryEntry): @@ -169,6 +170,7 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype [v_nbytes] = hop.inputargs(lltype.Signed) + hop.exception_cannot_occur() return hop.genop('gc_set_max_heap_size', [v_nbytes], resulttype=lltype.Void) @@ -181,4 +183,5 @@ def specialize_call(self, hop): opname = 'gc__' + self.instance.__name__ + hop.exception_cannot_occur() return hop.genop(opname, [], resulttype=hop.r_result) From arigo at codespeak.net Wed Apr 9 20:17:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Apr 2008 20:17:33 +0200 (CEST) Subject: [pypy-svn] r53624 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080409181733.A4FA6498005@codespeak.net> Author: arigo Date: Wed Apr 9 20:17:33 2008 New Revision: 53624 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py Log: Drop some hop.exception_cannot_occur() in the branch too. Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Wed Apr 9 20:17:33 2008 @@ -157,6 +157,7 @@ return annmodel.s_None def specialize_call(self, hop): + hop.exception_cannot_occur() return hop.genop('gc__collect', [], resulttype=hop.r_result) class SetMaxHeapSizeEntry(ExtRegistryEntry): @@ -169,6 +170,7 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype [v_nbytes] = hop.inputargs(lltype.Signed) + hop.exception_cannot_occur() return hop.genop('gc_set_max_heap_size', [v_nbytes], resulttype=lltype.Void) def can_move(P): @@ -184,6 +186,7 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype + hop.exception_cannot_occur() return hop.genop('gc_can_move', [], resulttype=lltype.Bool) class CollectEntry(ExtRegistryEntry): @@ -195,5 +198,5 @@ def specialize_call(self, hop): opname = 'gc__' + self.instance.__name__ + hop.exception_cannot_occur() return hop.genop(opname, [], resulttype=hop.r_result) - From fijal at codespeak.net Wed Apr 9 20:28:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 20:28:06 +0200 (CEST) Subject: [pypy-svn] r53625 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409182806.E6F26498005@codespeak.net> Author: fijal Date: Wed Apr 9 20:28:04 2008 New Revision: 53625 Modified: pypy/extradoc/talk/rupy2008/talk.tex Log: drop few XXXs Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Wed Apr 9 20:28:04 2008 @@ -69,6 +69,8 @@ \begin{itemize} \item giving you lots of ameninities + XXX don't use such words IMO, try to be more understandable + XXX audience is mostly students \item translation to lots of environments \item @@ -88,6 +90,7 @@ extra features \item lazy evaluation + XXX I don't like advertising features that don't work \item stackless \item @@ -144,6 +147,7 @@ \item implemented in C \item can be used to wrap C libraries rather effortlessly \item no need to write C code to interface with libraries + XXX ctypes demo maybe... \end{itemize} \pause @@ -174,8 +178,11 @@ \frametitle{Garbage Collection} \begin{itemize} \item RPython itself is garbage collected + XXX this is the first time you mention RPython, that's + XXX either too late, or not mention it at all \item when translating to C, a GC is woven into the program - \item GCs are completely written in Python + XXX another hard word + \item GCs are completely written in Python (XXX RPython) \item similar to the MMTK toolkit of Jikes RVM \item two fast GCs: semispace, generational \item lots of care to get the semantics right: From antocuni at codespeak.net Wed Apr 9 20:43:15 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 9 Apr 2008 20:43:15 +0200 (CEST) Subject: [pypy-svn] r53626 - in pypy/branch/jit-hotpath/pypy/rpython/ootypesystem: . test Message-ID: <20080409184315.577EA16A051@codespeak.net> Author: antocuni Date: Wed Apr 9 20:43:13 2008 New Revision: 53626 Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py Log: a failing test and the corresponding fix Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Wed Apr 9 20:43:13 2008 @@ -731,7 +731,12 @@ def __eq__(self, other): if not isinstance(other, _object): raise TypeError("comparing an _object with %r" % other) - return self.obj == other.obj + if self.obj is None: + return other.obj is None + elif other.obj is None: + return self.obj is None + else: + return self.obj == other.obj def __ne__(self, other): return not (self == other) Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py Wed Apr 9 20:43:13 2008 @@ -577,3 +577,11 @@ assert obj1 == obj2 assert cast_from_object(A, obj1) == a assert cast_from_object(B, obj2) == b + +def test_cast_object_compare_null(): + A = Instance("Foo", ROOT) + a = new(A) + obj1 = cast_to_object(a) + assert NULL != obj1 + assert obj1 != NULL + From cfbolz at codespeak.net Wed Apr 9 20:56:47 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Apr 2008 20:56:47 +0200 (CEST) Subject: [pypy-svn] r53627 - pypy/extradoc/talk/rupy2008 Message-ID: <20080409185647.A97E916A063@codespeak.net> Author: cfbolz Date: Wed Apr 9 20:56:47 2008 New Revision: 53627 Modified: pypy/extradoc/talk/rupy2008/talk.tex Log: try to fix the XXXs Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Wed Apr 9 20:56:47 2008 @@ -68,9 +68,7 @@ A flexible toolkit for writing interpreters \begin{itemize} \item - giving you lots of ameninities - XXX don't use such words IMO, try to be more understandable - XXX audience is mostly students + giving you lots of help \item translation to lots of environments \item @@ -89,12 +87,11 @@ \item extra features \item - lazy evaluation - XXX I don't like advertising features that don't work - \item stackless \item various introspection enhancements + \item + experimental things like lazy evaluation \end{itemize} \item Open Source project (MIT licenced) @@ -147,7 +144,6 @@ \item implemented in C \item can be used to wrap C libraries rather effortlessly \item no need to write C code to interface with libraries - XXX ctypes demo maybe... \end{itemize} \pause @@ -178,11 +174,11 @@ \frametitle{Garbage Collection} \begin{itemize} \item RPython itself is garbage collected - XXX this is the first time you mention RPython, that's - XXX either too late, or not mention it at all - \item when translating to C, a GC is woven into the program - XXX another hard word - \item GCs are completely written in Python (XXX RPython) +% XXX this is the first time you mention RPython, that's +% XXX either too late, or not mention it at all +% no, it is mentioned in the pictures part + \item when translating to C, a GC is integrated into the program + \item GCs are completely written in RPython \item similar to the MMTK toolkit of Jikes RVM \item two fast GCs: semispace, generational \item lots of care to get the semantics right: From fijal at codespeak.net Wed Apr 9 20:59:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 20:59:24 +0200 (CEST) Subject: [pypy-svn] r53628 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080409185924.7CAC249801A@codespeak.net> Author: fijal Date: Wed Apr 9 20:59:23 2008 New Revision: 53628 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Log: this is really about pointers, not types Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Wed Apr 9 20:59:23 2008 @@ -173,14 +173,14 @@ hop.exception_cannot_occur() return hop.genop('gc_set_max_heap_size', [v_nbytes], resulttype=lltype.Void) -def can_move(P): +def can_move(p): return True -can_move._annspecialcase_ = 'specialize:arg(0)' +can_move._annspecialcase_ = 'specialize:argtype(0)' class CanMoveEntry(ExtRegistryEntry): _about_ = can_move - def compute_result_annotation(self, s_TP): + def compute_result_annotation(self, s_p): from pypy.annotation import model as annmodel return annmodel.SomeBool() Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Wed Apr 9 20:59:23 2008 @@ -23,9 +23,9 @@ T1 = lltype.GcArray(lltype.Float) def f(i): if i: - return rgc.can_move(T0) + return rgc.can_move(lltype.malloc(T0)) else: - return rgc.can_move(T1) + return rgc.can_move(lltype.malloc(T1, 1)) t, typer, graph = gengraph(f, [int]) ops = list(graph.iterblockops()) From fijal at codespeak.net Wed Apr 9 21:29:16 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 21:29:16 +0200 (CEST) Subject: [pypy-svn] r53629 - in pypy/branch/io-improvements/pypy: rlib rpython Message-ID: <20080409192916.5765516A599@codespeak.net> Author: fijal Date: Wed Apr 9 21:29:14 2008 New Revision: 53629 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rpython/llinterp.py Log: gc_can_move eats argument by now Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Wed Apr 9 21:29:14 2008 @@ -187,7 +187,7 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype hop.exception_cannot_occur() - return hop.genop('gc_can_move', [], resulttype=lltype.Bool) + return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result) class CollectEntry(ExtRegistryEntry): _about_ = (disable_finalizers, enable_finalizers) Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Wed Apr 9 21:29:14 2008 @@ -753,7 +753,7 @@ def op_gc__collect(self): self.heap.collect() - def op_gc_can_move(self): + def op_gc_can_move(self, p): return True def op_gc__disable_finalizers(self): From fijal at codespeak.net Wed Apr 9 21:54:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 21:54:29 +0200 (CEST) Subject: [pypy-svn] r53630 - in pypy/branch/io-improvements/pypy/rpython/memory: gc gctransform test Message-ID: <20080409195429.A937B2A0188@codespeak.net> Author: fijal Date: Wed Apr 9 21:54:27 2008 New Revision: 53630 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: gc_can_move operation in gc transform Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py Wed Apr 9 21:54:27 2008 @@ -38,7 +38,6 @@ POOLNODEPTR = lltype.Ptr(POOLNODE) POOLNODE.become(lltype.Struct('gc_pool_node', ('linkedlist', HDRPTR), ('nextnode', POOLNODEPTR))) - def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096): self.heap_usage = 0 # at the end of the latest collection self.bytes_malloced = 0 # since the latest collection @@ -693,6 +692,8 @@ # reinstall the pool that was current at the beginning of x_clone() clonedata.pool = self.x_swap_pool(curpool) + def can_move(self, addr): + return False class PrintingMarkSweepGC(MarkSweepGC): _alloc_flavor_ = "raw" Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py Wed Apr 9 21:54:27 2008 @@ -537,5 +537,8 @@ finally: self.finalizer_lock_count -= 1 + def can_move(self, addr): + return True + STATISTICS_NUMBERS = 0 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py Wed Apr 9 21:54:27 2008 @@ -221,6 +221,9 @@ [s_gc], annmodel.s_None) self.enable_finalizers_ptr = getfn(GCClass.enable_finalizers.im_func, [s_gc], annmodel.s_None) + self.can_move_ptr = getfn(GCClass.can_move.im_func, + [s_gc, annmodel.SomeAddress()], + annmodel.SomeBool()) # in some GCs we can inline the common case of # malloc_fixedsize(typeid, size, True, False, False) @@ -530,6 +533,13 @@ resultvar=op.result) self.pop_roots(hop, livevars) + def gct_gc_can_move(self, hop): + op = hop.spaceop + v_addr = hop.genop('cast_ptr_to_adr', + [op.args[0]], resulttype=llmemory.Address) + hop.genop("direct_call", [self.can_move_ptr, self.c_const_gc, v_addr], + resultvar=op.result) + def gct_gc__disable_finalizers(self, hop): # cannot collect() op = hop.spaceop Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Wed Apr 9 21:54:27 2008 @@ -37,6 +37,7 @@ class GCTest(object): gcpolicy = None stacklessgc = False + GC_CAN_MOVE = False def runner(self, f, nbargs=0, statistics=False, transformer=False, **extraconfigopts): @@ -447,8 +448,18 @@ res = run([]) assert res == 0 + def test_can_move(self): + TP = lltype.GcArray(lltype.Float) + def func(): + from pypy.rlib import rgc + return rgc.can_move(lltype.malloc(TP, 1)) + run = self.runner(func) + res = run([]) + assert res == self.GC_CAN_MOVE class GenericMovingGCTests(GenericGCTests): + GC_CAN_MOVE = True + def test_many_ids(self): py.test.skip("fails for bad reasons in lltype.py :-(") class A(object): @@ -477,7 +488,6 @@ run = self.runner(f) run([]) - class TestMarkSweepGC(GenericGCTests): gcname = "marksweep" class gcpolicy(gc.FrameworkGcPolicy): From fijal at codespeak.net Wed Apr 9 22:06:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Apr 2008 22:06:28 +0200 (CEST) Subject: [pypy-svn] r53631 - in pypy/branch/io-improvements/pypy: rpython/memory/gctransform translator/c/test Message-ID: <20080409200628.6EFD916857F@codespeak.net> Author: fijal Date: Wed Apr 9 22:06:27 2008 New Revision: 53631 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Log: can_move for boehm Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py Wed Apr 9 22:06:27 2008 @@ -4,6 +4,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython import rmodel class BoehmGCTransformer(GCTransformer): malloc_zero_filled = True @@ -140,6 +141,8 @@ resulttype = lltype.Signed) hop.genop('int_invert', [v_int], resultvar=hop.spaceop.result) + def gct_gc_can_move(self, hop): + return hop.cast_result(rmodel.inputconst(lltype.Bool, False)) ########## weakrefs ########## # Boehm: weakref objects are small structures containing only a Boehm Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Wed Apr 9 22:06:27 2008 @@ -367,6 +367,16 @@ res = c_fn(10000) assert res == 0 + def test_can_move(self): + from pypy.rlib import rgc + class A: + pass + def fn(): + return rgc.can_move(A()) + + c_fn = self.getcompiled(fn, []) + assert c_fn() == False + # reusing some tests from pypy.rpython.memory.test.snippet large_tests_ok = True From antocuni at codespeak.net Wed Apr 9 23:23:23 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 9 Apr 2008 23:23:23 +0200 (CEST) Subject: [pypy-svn] r53633 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080409212323.B3DC62A0192@codespeak.net> Author: antocuni Date: Wed Apr 9 23:23:23 2008 New Revision: 53633 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Log: use PtrRedBox or InstanceRedBox when appropriate Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Wed Apr 9 23:23:23 2008 @@ -79,6 +79,7 @@ firstsubstructdesc = None materialize = None StructFieldDesc = None + PtrRedBox = None def __init__(self, RGenOp, TYPE): self.TYPE = TYPE @@ -220,7 +221,7 @@ vstruct = self.VirtualStructCls(self) vstruct.content_boxes = [desc.makedefaultbox() for desc in self.fielddescs] - box = rvalue.PtrRedBox(known_nonzero=True) + box = self.PtrRedBox(known_nonzero=True) box.content = vstruct vstruct.ownbox = box return box @@ -229,6 +230,7 @@ class StructTypeDesc(AbstractStructTypeDesc): StructFieldDesc = None # patched later with StructFieldDesc + PtrRedBox = rvalue.PtrRedBox _attrs_ = [] @@ -253,6 +255,7 @@ class InstanceTypeDesc(AbstractStructTypeDesc): StructFieldDesc = None # patched later with InstanceFieldDesc + PtrRedBox = rvalue.InstanceRedBox def Ptr(self, TYPE): return TYPE @@ -410,7 +413,7 @@ def factory(self): vstructbox = StructTypeDesc.factory(self) - outsidebox = rvalue.PtrRedBox(self.gv_null) + outsidebox = self.PtrRedBox(self.gv_null) content = vstructbox.content assert isinstance(content, VirtualizableStruct) content.content_boxes.append(outsidebox) @@ -613,7 +616,8 @@ class FieldDesc(object): __metaclass__ = cachedtype _attrs_ = 'structdesc' - + + PtrRedBox = None allow_void = False virtualizable = False gv_default = None @@ -678,7 +682,7 @@ return structbox box = self.redboxcls(gvar) if self.fieldnonnull: - assert isinstance(box, rvalue.PtrRedBox) + assert isinstance(box, rvalue.AbstractPtrRedBox) box.known_nonzero = True return box @@ -713,6 +717,9 @@ def compact_repr(self): # goes in ll helper names return "Fld_%s_in_%s" % (self.fieldname, self.PTRTYPE._short_name()) + def __repr__(self): + return "<%s(%s)>" % (self.__class__.__name__, self.fieldname) + def generate_get(self, jitstate, genvar): builder = jitstate.curbuilder gv_item = builder.genop_getfield(self.fieldtoken, genvar) @@ -729,12 +736,16 @@ class StructFieldDesc(NamedFieldDesc): + PtrRedBox = rvalue.PtrRedBox + def __init__(self, RGenOp, PTRTYPE, name, index): NamedFieldDesc.__init__(self, RGenOp, PTRTYPE, name) self.fieldindex = index class InstanceFieldDesc(NamedFieldDesc): + PtrRedBox = rvalue.InstanceRedBox + def __init__(self, RGenOp, PTRTYPE, name, index): NamedFieldDesc.__init__(self, RGenOp, PTRTYPE, name) self.fieldindex = index @@ -750,6 +761,8 @@ class ArrayFieldDesc(FieldDesc): + + PtrRedBox = rvalue.PtrRedBox allow_void = True def __init__(self, RGenOp, TYPE): Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Wed Apr 9 23:23:23 2008 @@ -568,8 +568,8 @@ jitstate.exc_value_box = box def setexception(jitstate, typebox, valuebox): - assert isinstance(typebox, rvalue.PtrRedBox) - assert isinstance(valuebox, rvalue.PtrRedBox) + assert isinstance(typebox, rvalue.AbstractPtrRedBox) + assert isinstance(valuebox, rvalue.AbstractPtrRedBox) ok1 = typebox .learn_nonzeroness(jitstate, True) ok2 = valuebox.learn_nonzeroness(jitstate, True) assert ok1 & ok2 # probably... maybe it's false but it would be From antocuni at codespeak.net Thu Apr 10 00:15:45 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 00:15:45 +0200 (CEST) Subject: [pypy-svn] r53635 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080409221545.1F02A2A00DC@codespeak.net> Author: antocuni Date: Thu Apr 10 00:15:45 2008 New Revision: 53635 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Log: move rvalue.PtrRedBox to the abstract class instead of None, else the rtyper complains Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Thu Apr 10 00:15:45 2008 @@ -79,7 +79,7 @@ firstsubstructdesc = None materialize = None StructFieldDesc = None - PtrRedBox = None + PtrRedBox = rvalue.PtrRedBox def __init__(self, RGenOp, TYPE): self.TYPE = TYPE @@ -230,7 +230,6 @@ class StructTypeDesc(AbstractStructTypeDesc): StructFieldDesc = None # patched later with StructFieldDesc - PtrRedBox = rvalue.PtrRedBox _attrs_ = [] From antocuni at codespeak.net Thu Apr 10 00:17:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 00:17:56 +0200 (CEST) Subject: [pypy-svn] r53636 - in pypy/branch/jit-hotpath/pypy/jit: rainbow rainbow/test timeshifter Message-ID: <20080409221756.AC7962A0180@codespeak.net> Author: antocuni Date: Thu Apr 10 00:17:55 2008 New Revision: 53636 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Log: Implement red_oosend, to make test_simple_meth & co. working for ootype. The idea is to store jitcodes for each method we need on the InstanceTypeDesc of each type. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Thu Apr 10 00:17:55 2008 @@ -146,7 +146,6 @@ keys = [] values = [] - common_args_r = None for graph, tsgraph in graph2tsgraph: fnptr = codewriter.rtyper.getcallable(graph) keys.append(llmemory.cast_ptr_to_adr(fnptr)) @@ -163,8 +162,6 @@ self.bytecode_for_address = bytecode_for_address - self.graphs = [graph for (graph, tsgraph) in graph2tsgraph] - self.jitcodes = values self.calldesc = CallDesc(codewriter.RGenOp, codewriter.exceptiondesc, lltype.typeOf(fnptr), colororder) @@ -234,6 +231,7 @@ self.calldescs = [] self.indirectcalldescs = [] self.metacalldescs = [] + self.strings = [] self.is_portal = is_portal # mapping constant -> index in constants self.const_positions = {} @@ -271,6 +269,8 @@ self.metacalldesc_positions = {} # mapping fnobjs to index self.indirectcalldesc_positions = {} + # mapping string to index + self.string_positions = {} self.graph = graph self.mergepoint_set = {} @@ -301,6 +301,7 @@ self.sharelist("calldescs"), self.sharelist("metacalldescs"), self.sharelist("indirectcalldescs"), + self.sharelist("strings"), self.is_portal, owncalldesc, gv_ownfnptr) @@ -822,6 +823,14 @@ self.indirectcalldesc_positions[subkey] = result return result + def string_position(self, s): + if s in self.string_positions: + return self.string_positions[s] + result = len(self.strings) + self.strings.append(s) + self.string_positions[s] = result + return result + def interiordesc(self, op, PTRTYPE, nb_offsets): path = [] CONTAINER = PTRTYPE.TO @@ -1420,6 +1429,12 @@ elif spaceop.opname == 'indirect_call': graphs = spaceop.args[-1].value args_v = spaceop.args[1:-1] + elif spaceop.opname == 'oosend': + meth_name = spaceop.args[0].value + v_self = spaceop.args[1] + SELF = v_self.concretetype + graphs = SELF._lookup_graphs(meth_name) + args_v = spaceop.args[1:] else: raise AssertionError(spaceop.opname) return graphs, args_v @@ -1617,14 +1632,15 @@ self.register_redvar(op.result) def serialize_op_oosend(self, op): - if self.hannotator.bookkeeper.is_green_call(op): + kind, withexc = self.guess_call_kind(op) + if kind == 'green': assert False, 'TODO' - withexc = self.can_raise(op) name = op.args[0].value opargs = op.args[1:] SELFTYPE = opargs[0].concretetype if SELFTYPE.oopspec_name is not None: + # we are calling a method like List.ll_getitem or so hasresult = op.result.concretetype != lltype.Void _, meth = SELFTYPE._lookup(name) oopspecdescindex = self.oopspecdesc_position('send', meth, withexc) @@ -1643,9 +1659,53 @@ self.emit(oopspecdescindex) self.emit(deepfrozen) self.emit(*args) + return - else: - assert False, 'TODO' + # normal oosend + # XXX: share code with serialize_op_indirect_call + has_result = (self.varcolor(op.result) != "gray" and + op.result.concretetype != lltype.Void) + assert not self.hannotator.policy.hotpath + emitted_args = [] + for v in op.args[1:]: + if v.concretetype == lltype.Void: + continue + emitted_args.append(self.serialize_oparg("red", v)) + + + if has_result: + self.register_redvar(op.result) + + graph2tsgraph = dict(self.graphs_from(op)) + #type2graph = self.collect_graphs_and_types(op, graph2tsgraph) + self.fill_methodcodes(SELFTYPE, name, graph2tsgraph) + args = graph2tsgraph.values()[0].getargs() + emitted_args = self.args_of_call(op.args[1:], args) + self.emit("red_oosend") + self.emit(*emitted_args) + #setdescindex = self.oosenddesc_position(type2graph) + #self.emit(setdescindex) + methnameindex = self.string_position(name) + self.emit(methnameindex) + if kind == "yellow": + self.emit("yellow_retrieve_result_as_red") + self.emit(self.type_position(op.result.concretetype)) + elif kind in ("gray", "red"): + pass + else: + assert 0, "unknown call kind %s" % (kind, ) + + def fill_methodcodes(self, INSTANCE, methname, graph2tsgraph): + TYPES = [INSTANCE] + INSTANCE._subclasses + for T in TYPES: + descindex = self.structtypedesc_position(T) + desc = self.structtypedescs[descindex] + if methname in desc.methodcodes: + break # we already filled the codes for this type + _, meth = T._lookup(methname) + tsgraph = graph2tsgraph[meth.graph] + jitcode = self.get_jitcode(tsgraph) + desc.methodcodes[methname] = jitcode class GraphTransformer(object): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 10 00:17:55 2008 @@ -8,6 +8,7 @@ from pypy.jit.rainbow import rhotpath from pypy.jit.rainbow import typesystem from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype import py from pypy.tool.ansi_print import ansi_log @@ -37,7 +38,8 @@ interiordescs, exceptioninstances, oopspecdescs, promotiondescs, called_bytecodes, num_mergepoints, graph_color, calldescs, metacalldescs, - indirectcalldescs, is_portal, owncalldesc, gv_ownfnptr): + indirectcalldescs, strings, is_portal, owncalldesc, + gv_ownfnptr): # XXX quite a lot of lists of descs here... At least we # share identical lists between the numberous prebuilt # JitCode instances. @@ -60,6 +62,7 @@ self.calldescs = calldescs self.metacalldescs = metacalldescs self.indirectcalldescs = indirectcalldescs + self.strings = strings self.is_portal = is_portal self.owncalldesc = owncalldesc self.gv_ownfnptr = gv_ownfnptr @@ -165,6 +168,10 @@ index = self.load_int() function = self.getjitcode().indirectcalldescs[index] args += (function, ) + elif argspec == "string": + index = self.load_int() + string = self.getjitcode().strings[index] + args += (string, ) elif argspec == "oopspec": oopspecindex = self.load_int() oopspec = self.getjitcode().oopspecdescs[oopspecindex] @@ -654,6 +661,15 @@ self.run(self.jitstate, bytecode, greenargs, redargs, start_bytecode_loop=False) + @arguments("green_varargs", "red_varargs", "string") + def opimpl_red_oosend(self, greenargs, redargs, methname): + selfbox = redargs[0] + vstruct = selfbox.content + assert isinstance(vstruct, rcontainer.VirtualStruct), 'TODO???' + bytecode = vstruct.typedesc.methodcodes[methname] + self.run(self.jitstate, bytecode, greenargs, redargs, + start_bytecode_loop=False) + @arguments(returns="green") def opimpl_yellow_retrieve_result(self): # XXX all this jitstate.greens business is a bit messy Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 00:17:55 2008 @@ -2332,9 +2332,6 @@ test_red_varsized_struct = _skip test_array_of_voids = _skip test_compile_time_const_tuple = _skip # needs vdict - test_simple_meth = _skip - test_simple_red_meth = _skip - test_simple_red_meth_vars_around = _skip test_simple_indirect_call = _skip test_normalize_indirect_call = _skip test_normalize_indirect_call_more = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Thu Apr 10 00:17:55 2008 @@ -256,6 +256,12 @@ StructFieldDesc = None # patched later with InstanceFieldDesc PtrRedBox = rvalue.InstanceRedBox + _attrs_ = ['methodcodes'] + + def __init__(self, RGenOp, TYPE): + AbstractStructTypeDesc.__init__(self, RGenOp, TYPE) + self.methodcodes = {} # method name --> jitcode + def Ptr(self, TYPE): return TYPE From cfbolz at codespeak.net Thu Apr 10 08:46:16 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 10 Apr 2008 08:46:16 +0200 (CEST) Subject: [pypy-svn] r53643 - pypy/extradoc/talk/rupy2008 Message-ID: <20080410064616.287822A0197@codespeak.net> Author: cfbolz Date: Thu Apr 10 08:46:15 2008 New Revision: 53643 Modified: pypy/extradoc/talk/rupy2008/Pypy architecture.odp pypy/extradoc/talk/rupy2008/talk.tex Log: typo-level fixes Modified: pypy/extradoc/talk/rupy2008/Pypy architecture.odp ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Thu Apr 10 08:46:15 2008 @@ -100,7 +100,7 @@ \begin{frame} - \frametitle{What is PyPy} + \frametitle{What is PyPy?} ... pretty pictures and demos \end{frame} @@ -113,7 +113,7 @@ \item cleanups \item - implementing ctypes + implementing CTypes \item .NET integration \item @@ -165,6 +165,7 @@ \begin{itemize} \item giving PyPy.NET similar capabilities as CPython \item accessing .NET libraries seamlessly from PyPy + \item various improvements \item ... demo \end{itemize} \end{frame} @@ -189,7 +190,7 @@ \end{itemize} \item performance pretty good \item memory-bound benchmarks faster than CPython - \item demo (id(x)) + \item ... demo \end{itemize} \end{frame} @@ -208,10 +209,11 @@ \item Psyco (mostly unmaintained) \item LuaJit (slightly simpler language, genius at work) \item Tamarin (company support, who knows how good it is) + \item Self + \item Smalltalk VMs \end{itemize} \end{block} \end{itemize} - \pause \end{frame} \begin{frame} From cfbolz at codespeak.net Thu Apr 10 08:46:57 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 10 Apr 2008 08:46:57 +0200 (CEST) Subject: [pypy-svn] r53644 - pypy/extradoc/talk/rupy2008 Message-ID: <20080410064657.568A32D8007@codespeak.net> Author: cfbolz Date: Thu Apr 10 08:46:56 2008 New Revision: 53644 Added: pypy/extradoc/talk/rupy2008/PyPy-architecture.odp - copied unchanged from r53643, pypy/extradoc/talk/rupy2008/Pypy architecture.odp Removed: pypy/extradoc/talk/rupy2008/Pypy architecture.odp Log: rename to not contain a space From antocuni at codespeak.net Thu Apr 10 11:14:37 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 11:14:37 +0200 (CEST) Subject: [pypy-svn] r53650 - in pypy/branch/jit-hotpath/pypy/rpython/ootypesystem: . test Message-ID: <20080410091437.6CE0B2A0196@codespeak.net> Author: antocuni Date: Thu Apr 10 11:14:36 2008 New Revision: 53650 Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py Log: add support to call ooidentityhash on ootype.Object values Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Thu Apr 10 11:14:36 2008 @@ -744,6 +744,15 @@ def __hash__(self): return hash(self.obj) + def _identityhash(self): + if self: + try: + return self.obj._identityhash() + except AttributeError: + return intmask(id(self.obj)) + else: + return 0 # for all null objects + def _cast_to_object(self): return self @@ -1677,7 +1686,8 @@ return obj._cast_to(EXPECTED_TYPE) def ooidentityhash(inst): - assert isinstance(typeOf(inst), (Instance, Record)) + T = typeOf(inst) + assert T is Object or isinstance(T, (Instance, Record)) return inst._identityhash() def oohash(inst): Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/test_ootype.py Thu Apr 10 11:14:36 2008 @@ -585,3 +585,18 @@ assert NULL != obj1 assert obj1 != NULL +def test_object_ooidentityhash(): + A = Instance("Foo", ROOT) + a = new(A) + obj1 = cast_to_object(a) + obj2 = cast_to_object(a) + assert ooidentityhash(obj1) == ooidentityhash(obj2) + +def test_object_ooidentityhash_sm(): + M = StaticMethod([Signed], Signed) + def m_(x): + return x + m = static_meth(M, "m", _callable=m_) + obj1 = cast_to_object(m) + obj2 = cast_to_object(m) + assert ooidentityhash(obj1) == ooidentityhash(obj2) From antocuni at codespeak.net Thu Apr 10 11:22:29 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 11:22:29 +0200 (CEST) Subject: [pypy-svn] r53651 - in pypy/branch/jit-hotpath/pypy/jit: codegen/llgraph rainbow rainbow/test Message-ID: <20080410092229.D42CD16A287@codespeak.net> Author: antocuni Date: Thu Apr 10 11:22:27 2008 New Revision: 53651 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: test_simple_indirect_call & co. pass. To compute the greenkey for static methods, we use their ooidentityhash Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py Thu Apr 10 11:22:27 2008 @@ -258,6 +258,10 @@ return ootype._static_meth(T, graph=fn.graph, _callable=fn._callable) else: T1 = lltype.typeOf(value) + if isinstance(T1, ootype.OOType) and T is ootype.Signed: + obj = ootype.cast_to_object(value) + return ootype.ooidentityhash(obj) + if T1 is llmemory.Address: value = llmemory.cast_adr_to_int(value) elif isinstance(T1, lltype.Ptr): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Thu Apr 10 11:22:27 2008 @@ -147,8 +147,9 @@ keys = [] values = [] for graph, tsgraph in graph2tsgraph: - fnptr = codewriter.rtyper.getcallable(graph) - keys.append(llmemory.cast_ptr_to_adr(fnptr)) + fnptr = codewriter.rtyper.getcallable(graph) + fnaddress = codewriter.cast_fnptr_to_root(fnptr) + keys.append(fnaddress) values.append(codewriter.get_jitcode(tsgraph)) # arbitrarily use the last graph to make the colororder - # normalization should ensure that all colors are the same @@ -195,6 +196,9 @@ def create_interpreter(self, RGenOp): raise NotImplementedError + def cast_fnptr_to_root(self, fnptr): + raise NotImplementedError + def sharelist(self, name): lst = getattr(self, name) # 'lst' is typically a list of descs or low-level pointers. @@ -1563,6 +1567,9 @@ ExceptionDesc = exception.LLTypeExceptionDesc StructTypeDesc = rcontainer.StructTypeDesc + def cast_fnptr_to_root(self, fnptr): + return llmemory.cast_ptr_to_adr(fnptr) + def create_interpreter(self, RGenOp): return LLTypeJitInterpreter(self.exceptiondesc, RGenOp) @@ -1596,7 +1603,10 @@ ExceptionDesc = exception.OOTypeExceptionDesc StructTypeDesc = rcontainer.InstanceTypeDesc - + + def cast_fnptr_to_root(self, fnptr): + return ootype.cast_to_object(fnptr) + def create_interpreter(self, RGenOp): return OOTypeJitInterpreter(self.exceptiondesc, RGenOp) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 10 11:22:27 2008 @@ -656,7 +656,7 @@ def opimpl_indirect_call_const(self, greenargs, redargs, funcptrbox, callset): gv = funcptrbox.getgenvar(self.jitstate) - addr = gv.revealconst(llmemory.Address) + addr = gv.revealconst(self.ts.ROOT_TYPE) bytecode = callset.bytecode_for_address(addr) self.run(self.jitstate, bytecode, greenargs, redargs, start_bytecode_loop=False) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 11:22:27 2008 @@ -2332,9 +2332,6 @@ test_red_varsized_struct = _skip test_array_of_voids = _skip test_compile_time_const_tuple = _skip # needs vdict - test_simple_indirect_call = _skip - test_normalize_indirect_call = _skip - test_normalize_indirect_call_more = _skip test_green_char_at_merge = _skip test_self_referential_structures = _skip test_indirect_red_call = _skip From antocuni at codespeak.net Thu Apr 10 11:31:04 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 11:31:04 +0200 (CEST) Subject: [pypy-svn] r53652 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080410093104.AB99016A28D@codespeak.net> Author: antocuni Date: Thu Apr 10 11:31:04 2008 New Revision: 53652 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: Yay! All these tests pass out of the box :-) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 11:31:04 2008 @@ -2334,20 +2334,5 @@ test_compile_time_const_tuple = _skip # needs vdict test_green_char_at_merge = _skip test_self_referential_structures = _skip - test_indirect_red_call = _skip - test_indirect_red_call_with_exc = _skip - test_indirect_gray_call = _skip - test_indirect_residual_red_call = _skip - test_constant_indirect_red_call = _skip - test_constant_indirect_red_call_no_result = _skip - test_indirect_sometimes_residual_pure_red_call = _skip - test_indirect_sometimes_residual_pure_but_fixed_red_call = _skip - test_manual_marking_of_pure_functions = _skip - test_red_int_add_ovf = _skip - test_nonzeroness_assert_while_compiling = _skip - test_segfault_while_compiling = _skip - test_learn_boolvalue = _skip - test_learn_nonzeroness = _skip - test_void_args = _skip test_ptrequality = _skip test_green_ptrequality = _skip From antocuni at codespeak.net Thu Apr 10 15:03:23 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 15:03:23 +0200 (CEST) Subject: [pypy-svn] r53655 - in pypy/branch/jit-hotpath/pypy: rpython/lltypesystem rpython/ootypesystem rpython/test translator/backendopt/test Message-ID: <20080410130323.5A947169F49@codespeak.net> Author: antocuni Date: Thu Apr 10 15:03:22 2008 New Revision: 53655 Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ooopimpl.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rclass.py pypy/branch/jit-hotpath/pypy/rpython/test/test_rclass.py pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_constfold.py Log: teach backendopt how to constfold oogetfield Modified: pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py Thu Apr 10 15:03:22 2008 @@ -459,7 +459,7 @@ 'runtimenew': LLOp(oo=True, canraise=(MemoryError,)), 'oonewcustomdict': LLOp(oo=True, canraise=(MemoryError,)), 'oosetfield': LLOp(oo=True), - 'oogetfield': LLOp(oo=True, sideeffects=False), + 'oogetfield': LLOp(oo=True, sideeffects=False, canrun=True), 'oosend': LLOp(oo=True, canraise=(Exception,)), 'ooupcast': LLOp(oo=True, canfold=True), 'oodowncast': LLOp(oo=True, canfold=True), Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ooopimpl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ooopimpl.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ooopimpl.py Thu Apr 10 15:03:22 2008 @@ -49,6 +49,11 @@ def op_subclassof(class1, class2): return ootype.subclassof(class1, class2) +def op_oogetfield(inst, name): + checkinst(inst) + if not ootype.typeOf(inst)._hints.get('immutable'): + raise TypeError("cannot fold oogetfield on mutable struct") + return getattr(inst, name) def is_inst(inst): return isinstance(ootype.typeOf(inst), (ootype.Instance, ootype.BuiltinType, ootype.StaticMethod)) Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rclass.py Thu Apr 10 15:03:22 2008 @@ -174,6 +174,9 @@ hints = classdef.classdesc.pyobj._rpython_hints else: hints = {} + if '_immutable_' in self.classdef.classdesc.classdict: + hints = hints.copy() + hints['immutable'] = True self.lowleveltype = ootype.Instance(classdef.name, b, {}, {}, _hints = hints) self.prebuiltinstances = {} # { id(x): (x, _ptr) } self.object_type = self.lowleveltype Modified: pypy/branch/jit-hotpath/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/test/test_rclass.py Thu Apr 10 15:03:22 2008 @@ -632,6 +632,41 @@ return a.revealconst(1) + b.revealconst(2) + a.revealconst(3) assert self.interpret(fn, []) == 3 + 8 + 9 + def test_immutable(self): + class I(object): + _immutable_ = True + + def __init__(self, v): + self.v = v + + i = I(3) + def f(): + return i.v + + t, typer, graph = self.gengraph(f, [], backendopt=True) + assert summary(graph) == {} + + def test_immutable_inheritance(self): + class I(object): + def __init__(self, v): + self.v = v + + class J(I): + _immutable_ = True + def __init__(self, v, w): + self.w = w + I.__init__(self, v) + + j = J(3, 4) + def f(): + j.v = j.v * 1 # make the annotator think it is mutated + j.w = j.w * 1 # make the annotator think it is mutated + return j.v + j.w + + t, typer, graph = self.gengraph(f, [], backendopt=True) + summ = summary(graph) + assert summ == {"setfield": 2} or summ == {"oosetfield": 2} + class TestLltype(BaseTestRclass, LLRtypeMixin): @@ -699,40 +734,6 @@ assert destrptra is not None assert destrptrb is not None - def test_immutable(self): - class I(object): - _immutable_ = True - - def __init__(self, v): - self.v = v - - i = I(3) - def f(): - return i.v - - t, typer, graph = self.gengraph(f, [], backendopt=True) - assert summary(graph) == {} - - def test_immutable_inheritance(self): - class I(object): - def __init__(self, v): - self.v = v - - class J(I): - _immutable_ = True - def __init__(self, v, w): - self.w = w - I.__init__(self, v) - - j = J(3, 4) - def f(): - j.v = j.v * 1 # make the annotator think it is mutated - j.w = j.w * 1 # make the annotator think it is mutated - return j.v + j.w - - t, typer, graph = self.gengraph(f, [], backendopt=True) - assert summary(graph) == {"setfield": 2} - def test_instance_repr(self): from pypy.rlib.objectmodel import current_object_addr_as_int class FooBar(object): Modified: pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_constfold.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_constfold.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_constfold.py Thu Apr 10 15:03:22 2008 @@ -3,6 +3,7 @@ from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib import objectmodel from pypy.translator.backendopt.constfold import constant_fold_graph @@ -41,6 +42,21 @@ assert summary(graph) == {'direct_call': 1} check_graph(graph, [], 124, t) +def test_simple_ootype(): + S1 = ootype.Instance('S1', ootype.ROOT, {'x': lltype.Signed}, _hints={'immutable': True}) + s1 = ootype.new(S1) + s1.x = 123 + def g(y): + return y + 1 + def fn(): + return g(s1.x) + + graph, t = get_graph(fn, []) + assert summary(graph) == {'oogetfield': 1, 'direct_call': 1} + constant_fold_graph(graph) + assert summary(graph) == {'direct_call': 1} + check_graph(graph, [], 124, t) + def test_along_link(): S1 = lltype.GcStruct('S1', ('x', lltype.Signed), hints={'immutable': True}) From antocuni at codespeak.net Thu Apr 10 15:10:22 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 15:10:22 +0200 (CEST) Subject: [pypy-svn] r53656 - in pypy/branch/jit-hotpath/pypy/jit: rainbow rainbow/test timeshifter Message-ID: <20080410131022.219CA2A0151@codespeak.net> Author: antocuni Date: Thu Apr 10 15:10:21 2008 New Revision: 53656 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Log: make test_ptrequality and test_green_ptrequality pass Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 10 15:10:21 2008 @@ -1083,6 +1083,11 @@ def opimpl_red_ooisnull(self, ptrbox): return rtimeshift.genptrnonzero(self.jitstate, ptrbox, True) + @arguments("red", "red", returns="red") + def opimpl_red_oois(self, ptrbox1, ptrbox2): + return rtimeshift.genptreq(self.jitstate, ptrbox1, + ptrbox2, False) + class DebugTrace(object): def __init__(self, *args): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 15:10:21 2008 @@ -2334,5 +2334,3 @@ test_compile_time_const_tuple = _skip # needs vdict test_green_char_at_merge = _skip test_self_referential_structures = _skip - test_ptrequality = _skip - test_green_ptrequality = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/typesystem.py Thu Apr 10 15:10:21 2008 @@ -38,6 +38,12 @@ def genop_ptr_nonzero(self, builder, argbox, gv_addr): return builder.genop1("ptr_nonzero", gv_addr) + def genop_ptr_eq(self, builder, gv_addr0, gv_addr1): + return builder.genop2("ptr_eq", gv_addr0, gv_addr1) + + def genop_ptr_ne(self, builder, gv_addr0, gv_addr1): + return builder.genop2("ptr_ne", gv_addr0, gv_addr1) + def get_FuncType(self, ARGS, RESULT): FUNCTYPE = lltype.FuncType(ARGS, RESULT) FUNCPTRTYPE = lltype.Ptr(FUNCTYPE) @@ -60,6 +66,13 @@ def genop_ptr_nonzero(self, builder, argbox, gv_addr): return builder.genop_oononnull(gv_addr) + def genop_ptr_eq(self, builder, gv_addr0, gv_addr1): + return builder.genop2("oois", gv_addr0, gv_addr1) + + def genop_ptr_ne(self, builder, gv_addr0, gv_addr1): + assert False, 'TODO' + #return builder.genop2("ptr_ne", gv_addr0, gv_addr1) + def get_FuncType(self, ARGS, RESULT): FUNCTYPE = ootype.StaticMethod(ARGS, RESULT) return FUNCTYPE, FUNCTYPE Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Thu Apr 10 15:10:21 2008 @@ -255,12 +255,12 @@ return boolbox def genptreq(jitstate, argbox0, argbox1, reverse): - assert isinstance(argbox0, rvalue.PtrRedBox) - assert isinstance(argbox1, rvalue.PtrRedBox) + assert isinstance(argbox0, rvalue.AbstractPtrRedBox) + assert isinstance(argbox1, rvalue.AbstractPtrRedBox) builder = jitstate.curbuilder if argbox0.is_constant() and argbox1.is_constant(): - addr0 = rvalue.ll_getvalue(argbox0, llmemory.Address) - addr1 = rvalue.ll_getvalue(argbox1, llmemory.Address) + addr0 = rvalue.ll_getvalue(argbox0, jitstate.ts.ROOT_TYPE) + addr1 = rvalue.ll_getvalue(argbox1, jitstate.ts.ROOT_TYPE) return rvalue.ll_fromvalue(jitstate, (addr0 == addr1) ^ reverse) if argbox0.content is not None: resultbox = argbox0.content.op_ptreq(jitstate, argbox1, reverse) @@ -273,9 +273,9 @@ gv_addr0 = argbox0.getgenvar(jitstate) gv_addr1 = argbox1.getgenvar(jitstate) if reverse: - gv_res = builder.genop2("ptr_ne", gv_addr0, gv_addr1) + gv_res = jitstate.ts.genop_ptr_ne(builder, gv_addr0, gv_addr1) else: - gv_res = builder.genop2("ptr_eq", gv_addr0, gv_addr1) + gv_res = jitstate.ts.genop_ptr_eq(builder, gv_addr0, gv_addr1) boolbox = rvalue.BoolRedBox(gv_res) boolbox.iftrue.append(booleffect.PtrEqualEffect(argbox0, argbox1, reverse)) return boolbox From antocuni at codespeak.net Thu Apr 10 16:26:21 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 10 Apr 2008 16:26:21 +0200 (CEST) Subject: [pypy-svn] r53658 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080410142621.140D22D8009@codespeak.net> Author: antocuni Date: Thu Apr 10 16:26:19 2008 New Revision: 53658 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: port this test to ootype, it passes out of the box :-) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 16:26:19 2008 @@ -1237,15 +1237,19 @@ res = self.interpret(f, [ord('b'), 0], [], policy=P_NOVIRTUAL) assert res == 1 - def test_self_referential_structures(self): + def _make_self_referential_type(self): S = lltype.GcForwardReference() - S.become(lltype.GcStruct('s', - ('ps', lltype.Ptr(S)))) + S.become(lltype.GcStruct('s', ('ps', lltype.Ptr(S)))) + return S + + def test_self_referential_structures(self): + S = self._make_self_referential_type() + malloc = self.malloc def f(x): - s = lltype.malloc(S) + s = malloc(S) if x: - s.ps = lltype.malloc(S) + s.ps = malloc(S) return s def count_depth(s): x = 0 @@ -2216,6 +2220,11 @@ def malloc_immortal(T): return ootype.new(T) + def _make_self_referential_type(self): + S = ootype.Instance('s', ootype.ROOT, {}) + S._add_fields({'ps': S}) + return S + def translate_insns(self, insns): replace = { 'getfield': 'oogetfield', @@ -2333,4 +2342,3 @@ test_array_of_voids = _skip test_compile_time_const_tuple = _skip # needs vdict test_green_char_at_merge = _skip - test_self_referential_structures = _skip From fijal at codespeak.net Thu Apr 10 17:45:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 17:45:42 +0200 (CEST) Subject: [pypy-svn] r53659 - pypy/branch/io-improvements/pypy/rpython/test Message-ID: <20080410154542.5C8ED2A00DB@codespeak.net> Author: fijal Date: Thu Apr 10 17:45:40 2008 New Revision: 53659 Modified: pypy/branch/io-improvements/pypy/rpython/test/test_annlowlevel.py Log: Few passing tests, just because they're in my wc Modified: pypy/branch/io-improvements/pypy/rpython/test/test_annlowlevel.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_annlowlevel.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_annlowlevel.py Thu Apr 10 17:45:40 2008 @@ -4,7 +4,7 @@ from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr +from pypy.rpython.annlowlevel import hlstr, llstr class TestLLType(BaseRtypingTest, LLRtypeMixin): def test_hlstr(self): @@ -13,4 +13,19 @@ s.chars[1] = "b" s.chars[2] = "c" assert hlstr(s) == "abc" + + def test_llstr(self): + s = llstr("abc") + assert len(s.chars) == 3 + assert s.chars[0] == "a" + assert s.chars[1] == "b" + assert s.chars[2] == "c" + + def test_llstr_compile(self): + def f(arg): + s = llstr(hlstr(arg)) + return len(s.chars) + + res = self.interpret(f, [self.string_to_ll("abc")]) + assert res == 3 From fijal at codespeak.net Thu Apr 10 17:46:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 17:46:12 +0200 (CEST) Subject: [pypy-svn] r53660 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080410154612.5D2E42A00DB@codespeak.net> Author: fijal Date: Thu Apr 10 17:46:11 2008 New Revision: 53660 Modified: pypy/branch/io-improvements/pypy/rpython/annlowlevel.py Log: Ah. A function for tests in previous checkin :) Modified: pypy/branch/io-improvements/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/io-improvements/pypy/rpython/annlowlevel.py Thu Apr 10 17:46:11 2008 @@ -400,6 +400,28 @@ return hop.genop('same_as', [v_ll_str], resulttype = hop.r_result.lowleveltype) +def llstr(s): + from pypy.rpython.lltypesystem.rstr import mallocstr + # XXX not sure what to do with ootypesystem + ll_s = mallocstr(len(s)) + for i, c in enumerate(s): + ll_s.chars[i] = c + return ll_s + +class LLStrEntry(extregistry.ExtRegistryEntry): + _about_ = llstr + + def compute_result_annotation(self, s_str): + from pypy.rpython.lltypesystem.rstr import STR + return annmodel.lltype_to_annotation(lltype.Ptr(STR)) + + def specialize_call(self, hop): + hop.exception_cannot_occur() + assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype + v_ll_str, = hop.inputargs(*hop.args_r) + return hop.genop('same_as', [v_ll_str], + resulttype = hop.r_result.lowleveltype) + # ____________________________________________________________ def cast_object_to_ptr(PTR, object): From docgok at codespeak.net Thu Apr 10 17:46:40 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 10 Apr 2008 17:46:40 +0200 (CEST) Subject: [pypy-svn] r53661 - in pypy/branch/io-improvements/pypy: rpython/module translator/goal Message-ID: <20080410154640.4AEDD2A0185@codespeak.net> Author: docgok Date: Thu Apr 10 17:46:39 2008 New Revision: 53661 Added: pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Big os_write speedup. Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Thu Apr 10 17:46:39 2008 @@ -17,12 +17,13 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.tool import rffi_platform as platform from pypy.rlib import rposix +from pypy.rlib import rgc from pypy.tool.udir import udir from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem.rstr import mallocstr from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem.llmemory import raw_memcopy, sizeof,\ - itemoffsetof, cast_ptr_to_adr, offsetof + itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR posix = __import__(os.name) @@ -512,17 +513,25 @@ def os_write_llimpl(fd, data): count = len(data) - outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') - try: - for i in range(count): - outbuf[i] = data[i] + if rgc.can_move(data): + outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') + try: + for i in range(count): + outbuf[i] = data[i] + written = rffi.cast(lltype.Signed, os_write( + rffi.cast(rffi.INT, fd), + outbuf, rffi.cast(rffi.SIZE_T, count))) + if written < 0: + raise OSError(rposix.get_errno(), "os_write failed") + finally: + lltype.free(outbuf, flavor='raw') + else: + outbuf = rffi.cast(rffi.VOIDP, data) written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), outbuf, rffi.cast(rffi.SIZE_T, count))) if written < 0: raise OSError(rposix.get_errno(), "os_write failed") - finally: - lltype.free(outbuf, flavor='raw') return written def os_write_oofakeimpl(fd, data): Added: pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py Thu Apr 10 17:46:39 2008 @@ -0,0 +1,30 @@ +import os + +def main(iterations=1): + dest = os.open('/dev/null', os.O_RDWR, 0777) + payload = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + + for x in xrange(1024 * 1024 * iterations): + os.write(dest, payload) + + os.close(dest) + +def entry_point(argv): + if len(argv) > 1: + n = int(argv[1]) + else: + n = 1 + main(n) + return 0 + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None + +if __name__ == '__main__': + import sys + if len(sys.argv) >= 2: + main(iterations = int(sys.argv[1])) + else: + main() From fijal at codespeak.net Thu Apr 10 17:47:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 17:47:03 +0200 (CEST) Subject: [pypy-svn] r53662 - in pypy/branch/io-improvements/pypy/rpython: . module/test test Message-ID: <20080410154703.07CB12A00DB@codespeak.net> Author: fijal Date: Thu Apr 10 17:47:02 2008 New Revision: 53662 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py pypy/branch/io-improvements/pypy/rpython/test/tool.py Log: Another bunch of posix tests, run with a flag moving_gc=False. Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Thu Apr 10 17:47:02 2008 @@ -43,7 +43,7 @@ """ low level interpreter working with concrete values. """ def __init__(self, typer, tracing=True, exc_data_ptr=None, - malloc_check=True): + malloc_check=True, moving_gc=True): self.bindings = {} self.typer = typer # 'heap' is module or object that provides malloc, etc for lltype ops @@ -54,6 +54,7 @@ self.malloc_check = malloc_check self.frame_class = LLFrame self.mallocs = {} + self.moving_gc = moving_gc if tracing: self.tracer = Tracer() @@ -754,7 +755,7 @@ self.heap.collect() def op_gc_can_move(self, p): - return True + return self.moving_gc def op_gc__disable_finalizers(self): self.heap.disable_finalizers() Modified: pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Thu Apr 10 17:47:02 2008 @@ -151,6 +151,9 @@ class TestLLtype(BaseTestPosix, LLRtypeMixin): pass +class TestLLtypeNonMovingGc(BaseTestPosix, LLRtypeMixin): + MOVING_GV = False + class TestOOtype(BaseTestPosix, OORtypeMixin): def test_fstat(self): py.test.skip("ootypesystem does not support os.fstat") Modified: pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py Thu Apr 10 17:47:02 2008 @@ -72,7 +72,8 @@ def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", backendopt=False, - config=None, malloc_check=True, **extraconfigopts): + config=None, malloc_check=True, + moving_gc=True, **extraconfigopts): extra_key = [(key, value) for key, value in extraconfigopts.iteritems()] extra_key.sort() extra_key = tuple(extra_key) @@ -97,7 +98,8 @@ viewbefore, policy, type_system=type_system, backendopt=backendopt, config=config, **extraconfigopts) - interp = LLInterpreter(typer, malloc_check=malloc_check) + interp = LLInterpreter(typer, malloc_check=malloc_check, + moving_gc=moving_gc) _tcache[key] = (t, interp, graph) # keep the cache small _lastinterpreted.append(key) @@ -111,11 +113,12 @@ def interpret(func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", backendopt=False, - config=None, malloc_check=True): + config=None, malloc_check=True, moving_gc=True): interp, graph = get_interpreter(func, values, view, viewbefore, policy, someobjects, type_system=type_system, backendopt=backendopt, config=config, - malloc_check=malloc_check) + malloc_check=malloc_check, + moving_gc=moving_gc) result = interp.eval_graph(graph, values) if malloc_check and interp.mallocs: raise MallocMismatch(interp.mallocs) @@ -123,10 +126,11 @@ def interpret_raises(exc, func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", - backendopt=False): + backendopt=False, moving_gc=True): interp, graph = get_interpreter(func, values, view, viewbefore, policy, someobjects, type_system=type_system, - backendopt=backendopt) + backendopt=backendopt, + moving_gc=moving_gc) info = py.test.raises(LLException, "interp.eval_graph(graph, values)") try: got = interp.find_exception(info.value) Modified: pypy/branch/io-improvements/pypy/rpython/test/tool.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/tool.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/tool.py Thu Apr 10 17:47:02 2008 @@ -6,6 +6,7 @@ class BaseRtypingTest(object): FLOAT_PRECISION = 8 + MOVING_GC = True def gengraph(self, func, argtypes=[], viewbefore='auto', policy=None, backendopt=False, config=None): @@ -13,10 +14,12 @@ backendopt=backendopt, config=config) def interpret(self, fn, args, **kwds): - return interpret(fn, args, type_system=self.type_system, **kwds) + return interpret(fn, args, type_system=self.type_system, + moving_gc=self.MOVING_GC, **kwds) def interpret_raises(self, exc, fn, args, **kwds): - return interpret_raises(exc, fn, args, type_system=self.type_system, **kwds) + return interpret_raises(exc, fn, args, type_system=self.type_system, + moving_gc=self.MOVING_GC, **kwds) def float_eq(self, x, y): return x == y @@ -40,7 +43,7 @@ if skipLL and self.type_system == 'lltype': py.test.skip("lltypesystem doesn't support %s, yet" % reason) if skipOO and self.type_system == 'ootype': - py.test.skip("ootypesystem doesn't support %s, yet" % reason) + py.test.skip("ootypesystem doesn't support %s, yet" % reason) class LLRtypeMixin(object): type_system = 'lltype' From fijal at codespeak.net Thu Apr 10 17:49:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 17:49:30 +0200 (CEST) Subject: [pypy-svn] r53663 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080410154930.75D43169E9C@codespeak.net> Author: fijal Date: Thu Apr 10 17:49:30 2008 New Revision: 53663 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py Log: oops Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Thu Apr 10 17:49:30 2008 @@ -755,7 +755,7 @@ self.heap.collect() def op_gc_can_move(self, p): - return self.moving_gc + return self.llinterpreter.moving_gc def op_gc__disable_finalizers(self): self.heap.disable_finalizers() From fijal at codespeak.net Thu Apr 10 17:58:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 17:58:24 +0200 (CEST) Subject: [pypy-svn] r53664 - pypy/branch/io-improvements/pypy/rpython/module/test Message-ID: <20080410155824.C05A32A00DB@codespeak.net> Author: fijal Date: Thu Apr 10 17:58:24 2008 New Revision: 53664 Modified: pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Log: jeez, typo Modified: pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Thu Apr 10 17:58:24 2008 @@ -72,7 +72,10 @@ def test_write(self): def f(fi): - text = 'This is a test' + if fi > 0: + text = 'This is a test' + else: + text = '333' return posix.write(fi,text) fi = os.open(path,os.O_WRONLY,0777) text = 'This is a test' @@ -152,7 +155,7 @@ pass class TestLLtypeNonMovingGc(BaseTestPosix, LLRtypeMixin): - MOVING_GV = False + MOVING_GC = False class TestOOtype(BaseTestPosix, OORtypeMixin): def test_fstat(self): From docgok at codespeak.net Thu Apr 10 18:27:03 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 10 Apr 2008 18:27:03 +0200 (CEST) Subject: [pypy-svn] r53665 - pypy/branch/io-improvements/pypy/rpython/module Message-ID: <20080410162703.146D32A0185@codespeak.net> Author: docgok Date: Thu Apr 10 18:27:00 2008 New Revision: 53665 Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Updated pointer arithmetic. Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Thu Apr 10 18:27:00 2008 @@ -526,7 +526,9 @@ finally: lltype.free(outbuf, flavor='raw') else: - outbuf = rffi.cast(rffi.VOIDP, data) + data_start = cast_ptr_to_adr(llstr(data)) + \ + fieldoffsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + outbuf = rffi.cast(rffi.VOIDP, data_start) written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), outbuf, rffi.cast(rffi.SIZE_T, count))) From docgok at codespeak.net Thu Apr 10 18:46:13 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 10 Apr 2008 18:46:13 +0200 (CEST) Subject: [pypy-svn] r53666 - pypy/branch/io-improvements/pypy/rpython/module Message-ID: <20080410164613.94C8D2A019A@codespeak.net> Author: docgok Date: Thu Apr 10 18:46:13 2008 New Revision: 53666 Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Now actually compiles. Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Thu Apr 10 18:46:13 2008 @@ -18,10 +18,11 @@ from pypy.rpython.tool import rffi_platform as platform from pypy.rlib import rposix from pypy.rlib import rgc +from pypy.rlib.objectmodel import keepalive_until_here from pypy.tool.udir import udir from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr +from pypy.rpython.annlowlevel import hlstr, llstr from pypy.rpython.lltypesystem.llmemory import raw_memcopy, sizeof,\ itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR @@ -527,13 +528,14 @@ lltype.free(outbuf, flavor='raw') else: data_start = cast_ptr_to_adr(llstr(data)) + \ - fieldoffsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) outbuf = rffi.cast(rffi.VOIDP, data_start) written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), outbuf, rffi.cast(rffi.SIZE_T, count))) if written < 0: raise OSError(rposix.get_errno(), "os_write failed") + keepalive_until_here(data) return written def os_write_oofakeimpl(fd, data): From fijal at codespeak.net Thu Apr 10 19:06:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 19:06:10 +0200 (CEST) Subject: [pypy-svn] r53669 - in pypy/branch/io-improvements/pypy/rpython/lltypesystem: . test Message-ID: <20080410170610.7B324168514@codespeak.net> Author: fijal Date: Thu Apr 10 19:06:10 2008 New Revision: 53669 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py Log: Potentially strange checkin. Casting between lltype.FixedSizeArray and lltype.Array(hints={'nolength':True}) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Thu Apr 10 19:06:10 2008 @@ -761,13 +761,22 @@ return dwn OUTSIDE = getattr(OUTSIDE, first) return -1 - + +def _exchangable_arrays(ONE, TWO): + if (isinstance(ONE, FixedSizeArray) and isinstance(TWO, Array) and + TWO._hints['nolength']): + return True + return False + def castable(PTRTYPE, CURTYPE): if CURTYPE.TO._gckind != PTRTYPE.TO._gckind: raise TypeError("cast_pointer() cannot change the gc status: %s to %s" % (CURTYPE, PTRTYPE)) if CURTYPE == PTRTYPE: return 0 + if (_exchangable_arrays(PTRTYPE.TO, CURTYPE.TO) or + _exchangable_arrays(CURTYPE.TO, PTRTYPE.TO)): + return 0 if (not isinstance(CURTYPE.TO, (Struct, PyObjectType)) or not isinstance(PTRTYPE.TO, (Struct, PyObjectType))): raise InvalidCast(CURTYPE, PTRTYPE) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py Thu Apr 10 19:06:10 2008 @@ -204,6 +204,11 @@ assert typeOf(p3) == Ptr(S3) assert p1b == cast_pointer(Ptr(S1bis), p3) py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") + A1 = FixedSizeArray(Char, 1) + A2 = Array(Char, hints={'nolength':True}) + p = malloc(A1, flavor='raw') + p2 = cast_pointer(Ptr(A2), p) + assert p2 == p def test_best_effort_gced_parent_detection(): py.test.skip("test not relevant any more") From fijal at codespeak.net Thu Apr 10 19:27:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 19:27:23 +0200 (CEST) Subject: [pypy-svn] r53670 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080410172723.18649169EA9@codespeak.net> Author: fijal Date: Thu Apr 10 19:27:21 2008 New Revision: 53670 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Failing test for ll2ctypes Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Apr 10 19:27:21 2008 @@ -357,6 +357,17 @@ lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test + def test_adr_cast(self): + from pypy.rpython.annlowlevel import llstr + from pypy.rpython.lltypesystem.rstr import STR + def f(): + a = llstr("xyz") + b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + rffi.cast(rffi.VOIDP, b) + # assert did not crash + f() + def test_funcptr1(self): def dummy(n): return n+1 From fijal at codespeak.net Thu Apr 10 19:28:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 19:28:04 +0200 (CEST) Subject: [pypy-svn] r53671 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080410172804.C1312169EA9@codespeak.net> Author: fijal Date: Thu Apr 10 19:28:04 2008 New Revision: 53671 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: also interpret this Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Apr 10 19:28:04 2008 @@ -11,6 +11,7 @@ from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.udir import udir +from pypy.rpython.test.test_llinterp import interpret class TestLL2Ctypes(object): @@ -367,6 +368,7 @@ rffi.cast(rffi.VOIDP, b) # assert did not crash f() + interpret(f, []) def test_funcptr1(self): def dummy(n): From fijal at codespeak.net Thu Apr 10 20:03:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 20:03:05 +0200 (CEST) Subject: [pypy-svn] r53672 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080410180305.796CF16A70A@codespeak.net> Author: fijal Date: Thu Apr 10 20:03:04 2008 New Revision: 53672 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Log: Kill this. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Thu Apr 10 20:03:04 2008 @@ -774,9 +774,6 @@ % (CURTYPE, PTRTYPE)) if CURTYPE == PTRTYPE: return 0 - if (_exchangable_arrays(PTRTYPE.TO, CURTYPE.TO) or - _exchangable_arrays(CURTYPE.TO, PTRTYPE.TO)): - return 0 if (not isinstance(CURTYPE.TO, (Struct, PyObjectType)) or not isinstance(PTRTYPE.TO, (Struct, PyObjectType))): raise InvalidCast(CURTYPE, PTRTYPE) From fijal at codespeak.net Thu Apr 10 20:58:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 20:58:59 +0200 (CEST) Subject: [pypy-svn] r53673 - in pypy/branch/io-improvements/pypy/rpython/lltypesystem: . test Message-ID: <20080410185859.DDD7F169F3B@codespeak.net> Author: fijal Date: Thu Apr 10 20:58:58 2008 New Revision: 53673 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: support for inlined arrays, wow, that took a while (still no caching) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py Thu Apr 10 20:58:58 2008 @@ -204,7 +204,11 @@ return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) - cstruct = cls._malloc() + if STRUCT._arrayfld: + n = len(getattr(container, STRUCT._arrayfld).items) + else: + n = None + cstruct = cls._malloc(n) add_storage(container, _struct_mixin, cstruct) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) @@ -218,7 +222,9 @@ csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) else: - raise NotImplementedError('inlined field', FIELDTYPE) + csubarray = getattr(cstruct, field_name) + convert_array(field_value, csubarray) + #raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container) def remove_regular_struct_content(container): @@ -228,10 +234,11 @@ if not isinstance(FIELDTYPE, lltype.ContainerType): delattr(container, field_name) -def convert_array(container): +def convert_array(container, carray=None): ARRAY = container._TYPE cls = get_ctypes_type(ARRAY) - carray = cls._malloc(container.getlength()) + if carray is None: + carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): for i in range(container.getlength()): @@ -434,7 +441,12 @@ container._ctypes_storage_was_allocated() storage = container._storage p = ctypes.pointer(storage) - if normalize and hasattr(storage, '_normalized_ctype'): + if normalize and getattr(T.TO, '_arrayfld', None): + # XXX doesn't cache + c_tp = build_ctypes_struct(T.TO, [], + len(getattr(storage, T.TO._arrayfld).items)) + p = ctypes.cast(p, ctypes.POINTER(c_tp)) + elif normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) return p Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Apr 10 20:58:58 2008 @@ -110,6 +110,19 @@ lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test + def test_array_inside_struct(self): + # like rstr.STR, but not Gc + STR = lltype.Struct('STR', ('x', lltype.Signed), ('y', lltype.Array(lltype.Char))) + a = lltype.malloc(STR, 3, flavor='raw') + a.y[0] = 'x' + a.y[1] = 'y' + a.y[2] = 'z' + ac = lltype2ctypes(a) + assert ac.contents.y.length == 3 + assert ac.contents.y.items[2] == ord('z') + lltype.free(a, flavor='raw') + assert not ALLOCATED + def test_array_nolength(self): A = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 10, flavor='raw') @@ -359,6 +372,7 @@ assert not ALLOCATED # detects memory leaks in the test def test_adr_cast(self): + py.test.skip("XXX") from pypy.rpython.annlowlevel import llstr from pypy.rpython.lltypesystem.rstr import STR def f(): From docgok at codespeak.net Thu Apr 10 21:12:52 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 10 Apr 2008 21:12:52 +0200 (CEST) Subject: [pypy-svn] r53674 - in pypy/branch/io-improvements/pypy: rpython/lltypesystem rpython/module translator/goal Message-ID: <20080410191252.4BADC169F54@codespeak.net> Author: docgok Date: Thu Apr 10 21:12:50 2008 New Revision: 53674 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/module/ll_os.py pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py Log: New convenience functions for making buffers non-moving. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Thu Apr 10 21:12:50 2008 @@ -2,17 +2,20 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes +from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr +from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof from pypy.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic -from pypy.rlib import rarithmetic +from pypy.rlib.objectmodel import keepalive_until_here +from pypy.rlib import rarithmetic, rgc from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.unroll import unrolling_iterable from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer -from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.annlowlevel import llhelper, llstr import os class UnhandledRPythonException(Exception): @@ -467,7 +470,37 @@ l.append(cp[i]) i += 1 return "".join(l) + +# str -> char* +def get_nonmovingbuffer(data): + """ + Either returns a non-moving copy or performs neccessary pointer arithmetic + to return a pointer to the characters of a string if the string is already + nonmovable. + Must be followed by a free_nonmovingbuffer call. + """ + from pypy.rpython.lltypesystem import rstr + if rgc.can_move(data): + count = len(data) + buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + for i in range(count): + buf[i] = data[i] + return buf + else: + data_start = cast_ptr_to_adr(llstr(data)) + \ + offsetof(rstr.STR, 'chars') + itemoffsetof(rstr.STR.chars, 0) + return cast(VOIDP, data_start) +# (str, char*) -> None +def free_nonmovingbuffer(data, buf): + """ + Either free a non-moving buffer or keep the original storage alive. + """ + if rgc.can_move(data): + lltype.free(buf, flavor='raw') + else: + keepalive_until_here(data) + # char* -> str, with an upper bound on the length in case there is no \x00 def charp2strn(cp, maxlen): l = [] Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Thu Apr 10 21:12:50 2008 @@ -17,8 +17,6 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.tool import rffi_platform as platform from pypy.rlib import rposix -from pypy.rlib import rgc -from pypy.rlib.objectmodel import keepalive_until_here from pypy.tool.udir import udir from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem.rstr import mallocstr @@ -513,29 +511,17 @@ rffi.SIZE_T) def os_write_llimpl(fd, data): - count = len(data) - if rgc.can_move(data): - outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') - try: - for i in range(count): - outbuf[i] = data[i] - written = rffi.cast(lltype.Signed, os_write( - rffi.cast(rffi.INT, fd), - outbuf, rffi.cast(rffi.SIZE_T, count))) - if written < 0: - raise OSError(rposix.get_errno(), "os_write failed") - finally: - lltype.free(outbuf, flavor='raw') - else: - data_start = cast_ptr_to_adr(llstr(data)) + \ - offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - outbuf = rffi.cast(rffi.VOIDP, data_start) + buf = lltype.nullptr(rffi.CCHARP.TO) + try: + count = len(data) + buf = rffi.get_nonmovingbuffer(data) written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), - outbuf, rffi.cast(rffi.SIZE_T, count))) + buf, rffi.cast(rffi.SIZE_T, count))) if written < 0: raise OSError(rposix.get_errno(), "os_write failed") - keepalive_until_here(data) + finally: + rffi.free_nonmovingbuffer(data, buf) return written def os_write_oofakeimpl(fd, data): Modified: pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py (original) +++ pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py Thu Apr 10 21:12:50 2008 @@ -2,7 +2,7 @@ def main(iterations=1): dest = os.open('/dev/null', os.O_RDWR, 0777) - payload = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + payload = 'x' * 1024 for x in xrange(1024 * 1024 * iterations): os.write(dest, payload) From cfbolz at codespeak.net Thu Apr 10 21:26:43 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 10 Apr 2008 21:26:43 +0200 (CEST) Subject: [pypy-svn] r53675 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080410192643.B777D2A01B4@codespeak.net> Author: cfbolz Date: Thu Apr 10 21:26:40 2008 New Revision: 53675 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Log: dummy commit to test commit hook Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py Thu Apr 10 21:26:40 2008 @@ -66,7 +66,8 @@ # if shapemask != -1 in store_back_virtualizables(), we should # not reach this point before we reach the "State sanitized" line. reshaping = content in self.containers_needing_reshaping - gv_result = content.allocate_gv_container(self.rgenop, reshaping) + gv_result = content.allocate_gv_container( + self.rgenop, self.getinitialboxgv, reshaping) self.containers_gv[content] = gv_result content.populate_gv_container(self.rgenop, gv_result, self.getinitialboxgv) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 10 21:26:40 2008 @@ -1052,6 +1052,7 @@ self.opcode_descs.append(opdesc) return index + class LLTypeJitInterpreter(JitInterpreter): ts = typesystem.llhelper Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py Thu Apr 10 21:26:40 2008 @@ -242,6 +242,32 @@ self.check_insns_in_loops({'int_rshift': 1, 'int_add': 1, 'int_is_true': 1}) + def test_beginning_of_list(self): + class MyJitDriver(JitDriver): + greens = [] + reds = ['lst', 'i', 'result'] + def on_enter_jit(self, invariants, reds): + reds.lst = list(reds.lst) + myjitdriver = MyJitDriver() + def f(x): + lst = [x] + i = x + result = 0 + while i: + i -= 1 + result += lst.pop() + lst.append(result) + lst.append(result) + myjitdriver.jit_merge_point(lst=lst, result=result, i=i) + myjitdriver.can_enter_jit(lst=lst, result=result, i=i) + return result + len(lst) + + res = self.run(f, [10], threshold=2, policy=P_OOPSPEC) + assert res == f(10) + # XXX fails due to merging problems + #self.check_insns(int_is_true=2, int_sub=2) # made a second loop + + def test_bogus_index_while_compiling(self): py.test.skip("implement me") class Y: Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 21:26:40 2008 @@ -80,7 +80,7 @@ for v in graph1.getargs()]) hannotator.simplify() if conftest.option.view: - hannotator.translator.view() + hannotator.translator.viewcg() return hs, hannotator, rtyper Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Thu Apr 10 21:26:40 2008 @@ -158,6 +158,56 @@ assert res == -42 self.check_insns({}) + def test_beginning_of_list(self): + def f(x): + lst = [x] + i = x + result = 0 + while i: + i -= 1 + result += lst.pop() + lst.append(result) + lst.append(result) + return result + len(lst) + + res = self.interpret(f, [10], policy=P_OOPSPEC) + assert res == f(10) + self.check_insns(int_is_true=2, int_sub=2) # made a second loop + # the following calls are generated: + # 1 newlist + # 1 resize + # 2 setitems + # 2 length + #self.check_insns(direct_call=6) # how does the check work in ootype? XXX + + def test_beginning_of_list_operations(self): + def f(x): + lst = [x, x, 1] + i = x + result = 0 + while i: + i -= 1 + one = lst.pop() + assert one == 1 + result += lst.pop() + lst[-1] + lst.append(result) + lst.append(result) + lst[-2] = 14 + lst.append(42) + del lst[-1] + lst.append(bool(lst)) + return result + len(lst) + + res = self.interpret(f, [10], policy=P_OOPSPEC) + assert res == f(10) + self.check_insns(int_is_true=2, int_sub=2) # made a second loop + # the following calls are generated: + # 1 newlist + # 1 resize + # 2 setitems + # 2 length + #self.check_insns(direct_call=6) # how does the check work in ootype? XXX + def test_bogus_index_while_compiling(self): py.test.skip("implement me") class Y: @@ -189,8 +239,8 @@ assert res == -7 -class TestOOType(VListTest): - type_system = "ootype" - class TestLLType(VListTest): type_system = "lltype" + +class TestOOType(VListTest): + type_system = "ootype" From cfbolz at codespeak.net Thu Apr 10 21:30:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 10 Apr 2008 21:30:45 +0200 (CEST) Subject: [pypy-svn] r53676 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080410193045.293B82A01B7@codespeak.net> Author: cfbolz Date: Thu Apr 10 21:30:44 2008 New Revision: 53676 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Log: wuaaa, wasn't so dummy Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py Thu Apr 10 21:30:44 2008 @@ -66,8 +66,7 @@ # if shapemask != -1 in store_back_virtualizables(), we should # not reach this point before we reach the "State sanitized" line. reshaping = content in self.containers_needing_reshaping - gv_result = content.allocate_gv_container( - self.rgenop, self.getinitialboxgv, reshaping) + gv_result = content.allocate_gv_container(self.rgenop, reshaping) self.containers_gv[content] = gv_result content.populate_gv_container(self.rgenop, gv_result, self.getinitialboxgv) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 10 21:30:44 2008 @@ -1052,7 +1052,6 @@ self.opcode_descs.append(opdesc) return index - class LLTypeJitInterpreter(JitInterpreter): ts = typesystem.llhelper Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_vlist.py Thu Apr 10 21:30:44 2008 @@ -242,32 +242,6 @@ self.check_insns_in_loops({'int_rshift': 1, 'int_add': 1, 'int_is_true': 1}) - def test_beginning_of_list(self): - class MyJitDriver(JitDriver): - greens = [] - reds = ['lst', 'i', 'result'] - def on_enter_jit(self, invariants, reds): - reds.lst = list(reds.lst) - myjitdriver = MyJitDriver() - def f(x): - lst = [x] - i = x - result = 0 - while i: - i -= 1 - result += lst.pop() - lst.append(result) - lst.append(result) - myjitdriver.jit_merge_point(lst=lst, result=result, i=i) - myjitdriver.can_enter_jit(lst=lst, result=result, i=i) - return result + len(lst) - - res = self.run(f, [10], threshold=2, policy=P_OOPSPEC) - assert res == f(10) - # XXX fails due to merging problems - #self.check_insns(int_is_true=2, int_sub=2) # made a second loop - - def test_bogus_index_while_compiling(self): py.test.skip("implement me") class Y: Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 10 21:30:44 2008 @@ -80,7 +80,7 @@ for v in graph1.getargs()]) hannotator.simplify() if conftest.option.view: - hannotator.translator.viewcg() + hannotator.translator.view() return hs, hannotator, rtyper Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Thu Apr 10 21:30:44 2008 @@ -158,56 +158,6 @@ assert res == -42 self.check_insns({}) - def test_beginning_of_list(self): - def f(x): - lst = [x] - i = x - result = 0 - while i: - i -= 1 - result += lst.pop() - lst.append(result) - lst.append(result) - return result + len(lst) - - res = self.interpret(f, [10], policy=P_OOPSPEC) - assert res == f(10) - self.check_insns(int_is_true=2, int_sub=2) # made a second loop - # the following calls are generated: - # 1 newlist - # 1 resize - # 2 setitems - # 2 length - #self.check_insns(direct_call=6) # how does the check work in ootype? XXX - - def test_beginning_of_list_operations(self): - def f(x): - lst = [x, x, 1] - i = x - result = 0 - while i: - i -= 1 - one = lst.pop() - assert one == 1 - result += lst.pop() + lst[-1] - lst.append(result) - lst.append(result) - lst[-2] = 14 - lst.append(42) - del lst[-1] - lst.append(bool(lst)) - return result + len(lst) - - res = self.interpret(f, [10], policy=P_OOPSPEC) - assert res == f(10) - self.check_insns(int_is_true=2, int_sub=2) # made a second loop - # the following calls are generated: - # 1 newlist - # 1 resize - # 2 setitems - # 2 length - #self.check_insns(direct_call=6) # how does the check work in ootype? XXX - def test_bogus_index_while_compiling(self): py.test.skip("implement me") class Y: @@ -239,8 +189,8 @@ assert res == -7 -class TestLLType(VListTest): - type_system = "lltype" - class TestOOType(VListTest): type_system = "ootype" + +class TestLLType(VListTest): + type_system = "lltype" From docgok at codespeak.net Thu Apr 10 21:48:10 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 10 Apr 2008 21:48:10 +0200 (CEST) Subject: [pypy-svn] r53677 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080410194810.34EB12A01B9@codespeak.net> Author: docgok Date: Thu Apr 10 21:48:09 2008 New Revision: 53677 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Log: Forgot the tests! Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Thu Apr 10 21:48:09 2008 @@ -633,7 +633,18 @@ def test_ptradd_interpret(): interpret(test_ptradd, []) - + +def test_nonmovingbuffer(): + def f(): + buf = lltype.nullptr(CCHARP.TO) + d = 'some cool data that should not move' + try: + buf = get_nonmovingbuffer(d) + for i in range(len(d)): + assert buf[i] == d[i] + finally: + free_nonmovingbuffer(d, buf) + interpret(f, []) class TestCRffi(BaseTestRffi): def compile(self, func, args, **kwds): From fijal at codespeak.net Thu Apr 10 21:57:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 21:57:27 +0200 (CEST) Subject: [pypy-svn] r53678 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080410195727.B7C472A01B4@codespeak.net> Author: fijal Date: Thu Apr 10 21:57:27 2008 New Revision: 53678 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Failing test for address casting. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Apr 10 21:57:27 2008 @@ -372,18 +372,18 @@ assert not ALLOCATED # detects memory leaks in the test def test_adr_cast(self): - py.test.skip("XXX") from pypy.rpython.annlowlevel import llstr from pypy.rpython.lltypesystem.rstr import STR def f(): a = llstr("xyz") b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + llmemory.itemoffsetof(STR.chars, 0)) - rffi.cast(rffi.VOIDP, b) - # assert did not crash - f() - interpret(f, []) - + buf = rffi.cast(rffi.VOIDP, b) + return buf[2] + assert f() == ord("z") + res = interpret(f, []) + assert res == 'z' + def test_funcptr1(self): def dummy(n): return n+1 From fijal at codespeak.net Thu Apr 10 21:58:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 21:58:03 +0200 (CEST) Subject: [pypy-svn] r53679 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080410195803.4E9502A01B4@codespeak.net> Author: fijal Date: Thu Apr 10 21:58:02 2008 New Revision: 53679 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Log: equality of FixedSizeArray and Array(hints='nolength:True) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Thu Apr 10 21:58:02 2008 @@ -631,6 +631,14 @@ hints={'interior_ptr_type':True}) return R + def __eq__(self, other): + if not isinstance(other, Ptr): + return False + if (_exchangable_arrays(self.TO, other.TO) or + _exchangable_arrays(other.TO, self.TO)): + return True + return LowLevelType.__eq__(self, other) + class InteriorPtr(LowLevelType): def __init__(self, PARENTTYPE, TO, offsets): self.PARENTTYPE = PARENTTYPE From docgok at codespeak.net Thu Apr 10 22:08:55 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 10 Apr 2008 22:08:55 +0200 (CEST) Subject: [pypy-svn] r53680 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080410200855.7AE9C2A01B5@codespeak.net> Author: docgok Date: Thu Apr 10 22:08:55 2008 New Revision: 53680 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Log: More complete testing. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Thu Apr 10 22:08:55 2008 @@ -9,6 +9,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir from pypy.rpython.test.test_llinterp import interpret, MallocMismatch +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper from pypy.translator.backendopt.all import backend_optimizations @@ -633,18 +634,25 @@ def test_ptradd_interpret(): interpret(test_ptradd, []) - -def test_nonmovingbuffer(): - def f(): - buf = lltype.nullptr(CCHARP.TO) - d = 'some cool data that should not move' - try: - buf = get_nonmovingbuffer(d) - for i in range(len(d)): - assert buf[i] == d[i] - finally: - free_nonmovingbuffer(d, buf) - interpret(f, []) + +class BaseInterpretedTestRffi(BaseRtypingTest): + def test_nonmovingbuffer(self): + def f(): + buf = lltype.nullptr(CCHARP.TO) + d = 'some cool data that should not move' + try: + buf = get_nonmovingbuffer(d) + for i in range(len(d)): + assert buf[i] == d[i] + finally: + free_nonmovingbuffer(d, buf) + self.interpret(f, []) + +class TestNonmovingBuffer(BaseInterpretedTestRffi, LLRtypeMixin): + pass + +class TestLLtypeNonMovingGc(BaseInterpretedTestRffi, LLRtypeMixin): + MOVING_GC = False class TestCRffi(BaseTestRffi): def compile(self, func, args, **kwds): From fijal at codespeak.net Thu Apr 10 23:51:15 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Apr 2008 23:51:15 +0200 (CEST) Subject: [pypy-svn] r53681 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080410215115.869982A00E1@codespeak.net> Author: fijal Date: Thu Apr 10 23:51:12 2008 New Revision: 53681 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Log: Revert those changes, they made no sense whatsoever. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Thu Apr 10 23:51:12 2008 @@ -631,14 +631,6 @@ hints={'interior_ptr_type':True}) return R - def __eq__(self, other): - if not isinstance(other, Ptr): - return False - if (_exchangable_arrays(self.TO, other.TO) or - _exchangable_arrays(other.TO, self.TO)): - return True - return LowLevelType.__eq__(self, other) - class InteriorPtr(LowLevelType): def __init__(self, PARENTTYPE, TO, offsets): self.PARENTTYPE = PARENTTYPE @@ -770,12 +762,6 @@ OUTSIDE = getattr(OUTSIDE, first) return -1 -def _exchangable_arrays(ONE, TWO): - if (isinstance(ONE, FixedSizeArray) and isinstance(TWO, Array) and - TWO._hints['nolength']): - return True - return False - def castable(PTRTYPE, CURTYPE): if CURTYPE.TO._gckind != PTRTYPE.TO._gckind: raise TypeError("cast_pointer() cannot change the gc status: %s to %s" From cfbolz at codespeak.net Thu Apr 10 23:56:38 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 10 Apr 2008 23:56:38 +0200 (CEST) Subject: [pypy-svn] r53682 - pypy/extradoc/talk/rupy2008 Message-ID: <20080410215638.5EA61168500@codespeak.net> Author: cfbolz Date: Thu Apr 10 23:56:37 2008 New Revision: 53682 Modified: pypy/extradoc/talk/rupy2008/PyPy-architecture.odp Log: tweaks Modified: pypy/extradoc/talk/rupy2008/PyPy-architecture.odp ============================================================================== Binary files. No diff available. From fijal at codespeak.net Fri Apr 11 00:09:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Apr 2008 00:09:27 +0200 (CEST) Subject: [pypy-svn] r53684 - in pypy/branch/io-improvements/pypy/rpython/lltypesystem: . test Message-ID: <20080410220927.F0F8F2A013F@codespeak.net> Author: fijal Date: Fri Apr 11 00:09:27 2008 New Revision: 53684 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: THIS IS A NOT WORKING CHECKIN. I've got no idea how to proceed, giving up. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py Fri Apr 11 00:09:27 2008 @@ -382,6 +382,22 @@ # ____________________________________________________________ +def _find_parent(llobj): + parent, parentindex = lltype.parentlink(llobj) + if parent is None: + return llobj, 0 + next_p, next_i = _find_parent(parent) + if isinstance(parentindex, int): + c_tp = get_ctypes_type(lltype.typeOf(parent)) + sizeof = ctypes.sizeof(get_ctypes_type(lltype.typeOf(parent).OF)) + ofs = c_tp.items.offset + parentindex * sizeof + return next_p, next_i + ofs + else: + c_tp = get_ctypes_type(lltype.typeOf(parent)) + ofs = getattr(c_tp, parentindex).offset + return next_p, next_i + ofs + + # XXX THIS IS A HACK XXX # ctypes does not keep callback arguments alive. So we do. Forever # we need to think deeper how to approach this problem @@ -425,6 +441,11 @@ if T.TO._gckind != 'raw' and not T.TO._hints.get('callback', None): raise Exception("can only pass 'raw' data structures to C, not %r" % (T.TO._gckind,)) + + index = 0 + if isinstance(container, lltype._subarray): + topmost, index = _find_parent(container) + container = topmost if container._storage is None: raise RuntimeError("attempting to pass a freed structure to C") if container._storage is True: @@ -441,6 +462,11 @@ container._ctypes_storage_was_allocated() storage = container._storage p = ctypes.pointer(storage) + if index: + p = ctypes.cast(p, ctypes.c_void_p) + p = ctypes.c_void_p(p.value + index) + c_tp = get_ctypes_type(T.TO) + storage._normalized_ctype = c_tp if normalize and getattr(T.TO, '_arrayfld', None): # XXX doesn't cache c_tp = build_ctypes_struct(T.TO, [], @@ -461,7 +487,6 @@ if T is lltype.SingleFloat: return ctypes.c_float(float(llobj)) - return llobj def ctypes2lltype(T, cobj): @@ -642,6 +667,8 @@ """Cast a value to a result type, trying to use the same rules as C.""" if not isinstance(RESTYPE, lltype.LowLevelType): raise TypeError("rffi.cast() first arg should be a TYPE") + if isinstance(value, llmemory.fakeaddress): + value = value.ptr TYPE1 = lltype.typeOf(value) cvalue = lltype2ctypes(value) cresulttype = get_ctypes_type(RESTYPE) @@ -684,6 +711,8 @@ RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) TYPE1 = v_arg.concretetype + if TYPE1 is llmemory.Address: + v_arg = gen_cast(hop.llops, lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)), v_arg) return gen_cast(hop.llops, RESTYPE, v_arg) def typecheck_ptradd(T): Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Fri Apr 11 00:09:27 2008 @@ -374,13 +374,14 @@ def test_adr_cast(self): from pypy.rpython.annlowlevel import llstr from pypy.rpython.lltypesystem.rstr import STR + P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)) def f(): a = llstr("xyz") b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + llmemory.itemoffsetof(STR.chars, 0)) buf = rffi.cast(rffi.VOIDP, b) return buf[2] - assert f() == ord("z") + #assert f() == 'z' res = interpret(f, []) assert res == 'z' From pedronis at codespeak.net Fri Apr 11 13:27:34 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 13:27:34 +0200 (CEST) Subject: [pypy-svn] r53685 - pypy/branch/ctypes-stable/pypy/doc Message-ID: <20080411112734.C3DA32A01A6@codespeak.net> Author: pedronis Date: Fri Apr 11 13:27:32 2008 New Revision: 53685 Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Log: merge trunk changes to the doc Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Fri Apr 11 13:27:32 2008 @@ -56,16 +56,16 @@ pluggable garbage collectors, some of them are moving collectors, this means that the strategy of passing direct references inside Python objects to an external library is not feasible (unless the GCs -support pinning, which not the case right now). The consequence of +support pinning, which is not the case right now). The consequence of this is that sometimes copying instead of sharing is required, this may result in some semantics differences. C objects created with _rawffi itself are allocated outside of the GC heap, so they can be passed to external functions without worries. Porting the implementation to interpreter-level should likely improve -its speed, Further the current layering and the current _rawffi +its speed. Furthermore the current layering and the current _rawffi interface require more object allocations and copying than strictly -necessary, this too could be improved. +necessary; this too could be improved. The implementation was developed and has only been tested on Linux. @@ -86,14 +86,16 @@ - callbacks accepting by-value structures - - expected semantics when ctypes types are subclassed + - slight semantic differences that ctypes makes + between its primitive types and user subclasses + of its primitive types Getting the code and test suites ================================= A stable revision of PyPy containing the ctypes implementation can be checked out with subversion from: -http://codespeak.net/svn/pypy/tag/ctypes-stable XXX make the tag +http://codespeak.net/svn/pypy/tag/ctypes-stable The various tests can be run on Linux. @@ -119,7 +121,7 @@ $ cd ../.. # back to pypy/ $ ./translator/goal/pypy-c test_all.py lib/app_test/ctypes_tests -There should be 255 passed and 36 skipped tests. +There should be 36 skipped tests and all other tests should pass. Running example code ===================== From pedronis at codespeak.net Fri Apr 11 13:42:14 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 13:42:14 +0200 (CEST) Subject: [pypy-svn] r53686 - pypy/branch/ctypes-stable/pypy/doc Message-ID: <20080411114214.43A6B2A8006@codespeak.net> Author: pedronis Date: Fri Apr 11 13:42:13 2008 New Revision: 53686 Added: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt - copied unchanged from r53685, pypy/dist/pypy/doc/ctypes-implementation.txt Log: I did something wrong merging, do the simplest thign and copy it wholesale from the trunk instead. From pedronis at codespeak.net Fri Apr 11 14:04:47 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 14:04:47 +0200 (CEST) Subject: [pypy-svn] r53687 - pypy/branch/ctypes-stable/pypy/doc Message-ID: <20080411120447.9822E2A8002@codespeak.net> Author: pedronis Date: Fri Apr 11 14:04:46 2008 New Revision: 53687 Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Log: fixes after bea's review Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Fri Apr 11 14:04:46 2008 @@ -3,7 +3,10 @@ PyPy's ctypes implementation ============================= -terminology: +Summary +======== + +Terminology: * application level code - code written in full Python @@ -22,9 +25,9 @@ implementation. This allowed to provide a working implementation with a large part of ctypes features in 2 months real time. -We reused the ``ctypes`` package as-is from CPython. We implemented -``_ctypes`` which is a C module in CPython mostly in pure Python based on -a lower-level layer extension module ``_rawffi``. +We reused the ``ctypes`` package version 1.0.2 as-is from CPython. We +implemented ``_ctypes`` which is a C module in CPython mostly in pure +Python based on a lower-level layer extension module ``_rawffi``. .. _`libffi`: http://sources.redhat.com/libffi/ @@ -52,14 +55,14 @@ Discussion and limitations ============================= -Reimplementing ctypes features was in general possible. PyPy supports +Reimplementing ctypes features were in general possible. PyPy supports pluggable garbage collectors, some of them are moving collectors, this means that the strategy of passing direct references inside Python objects to an external library is not feasible (unless the GCs support pinning, which is not the case right now). The consequence of this is that sometimes copying instead of sharing is required, this may result in some semantics differences. C objects created with -_rawffi itself are allocated outside of the GC heap, so they can be +_rawffi itself are allocated outside of the GC heap, such that they can be passed to external functions without worries. Porting the implementation to interpreter-level should likely improve @@ -113,7 +116,8 @@ To run the test suite a compiled pypy-c is required with the proper configuration. To build the required pypy-c one should inside the checkout:: $ cd pypy/translator/goal - $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --withmod-_rawffi --allworkingmodules + $ ./translate.py --text --batch --gc=generation targetpypystandalone.py + --withmod-_rawffi --allworkingmodules this should produce a pypy-c executable in the ``goal`` directory. From pedronis at codespeak.net Fri Apr 11 17:32:15 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 17:32:15 +0200 (CEST) Subject: [pypy-svn] r53689 - pypy/branch/ctypes-stable/pypy/doc Message-ID: <20080411153215.2BD972D80C7@codespeak.net> Author: pedronis Date: Fri Apr 11 17:32:12 2008 New Revision: 53689 Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Log: reference to PyPy documentation Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Fri Apr 11 17:32:12 2008 @@ -13,6 +13,8 @@ * interpreter level code - code written in RPython, compiled to something else, say C, part of the interpreter. +* for more information on PyPy see the `PyPy documentation`_. + PyPy's ctypes implementation in its current state proves the feasibility of implementing a module with the same interface and behavior for PyPy as ctypes for CPython. @@ -30,6 +32,7 @@ Python based on a lower-level layer extension module ``_rawffi``. .. _`libffi`: http://sources.redhat.com/libffi/ +.. _`PyPy documentation`: http://codespeak.net/pypy/dist/pypy/doc/ Low-level part: ``_rawffi`` ============================ From pedronis at codespeak.net Fri Apr 11 17:34:38 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 17:34:38 +0200 (CEST) Subject: [pypy-svn] r53690 - pypy/branch/ctypes-stable/pypy/doc Message-ID: <20080411153438.3A607398003@codespeak.net> Author: pedronis Date: Fri Apr 11 17:34:37 2008 New Revision: 53690 Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Log: redundant here Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Fri Apr 11 17:34:37 2008 @@ -13,8 +13,6 @@ * interpreter level code - code written in RPython, compiled to something else, say C, part of the interpreter. -* for more information on PyPy see the `PyPy documentation`_. - PyPy's ctypes implementation in its current state proves the feasibility of implementing a module with the same interface and behavior for PyPy as ctypes for CPython. @@ -32,7 +30,6 @@ Python based on a lower-level layer extension module ``_rawffi``. .. _`libffi`: http://sources.redhat.com/libffi/ -.. _`PyPy documentation`: http://codespeak.net/pypy/dist/pypy/doc/ Low-level part: ``_rawffi`` ============================ From pedronis at codespeak.net Fri Apr 11 17:43:16 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 17:43:16 +0200 (CEST) Subject: [pypy-svn] r53691 - pypy/branch/ctypes-stable/pypy/doc Message-ID: <20080411154316.C9775398002@codespeak.net> Author: pedronis Date: Fri Apr 11 17:43:16 2008 New Revision: 53691 Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Log: got confused here Modified: pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt (original) +++ pypy/branch/ctypes-stable/pypy/doc/ctypes-implementation.txt Fri Apr 11 17:43:16 2008 @@ -55,7 +55,7 @@ Discussion and limitations ============================= -Reimplementing ctypes features were in general possible. PyPy supports +Reimplementing ctypes features was in general possible. PyPy supports pluggable garbage collectors, some of them are moving collectors, this means that the strategy of passing direct references inside Python objects to an external library is not feasible (unless the GCs From pedronis at codespeak.net Fri Apr 11 17:43:59 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 17:43:59 +0200 (CEST) Subject: [pypy-svn] r53692 - pypy/dist/pypy/doc Message-ID: <20080411154359.35BE1398002@codespeak.net> Author: pedronis Date: Fri Apr 11 17:43:58 2008 New Revision: 53692 Modified: pypy/dist/pypy/doc/ctypes-implementation.txt Log: last changes from ctypes-stable branch Modified: pypy/dist/pypy/doc/ctypes-implementation.txt ============================================================================== --- pypy/dist/pypy/doc/ctypes-implementation.txt (original) +++ pypy/dist/pypy/doc/ctypes-implementation.txt Fri Apr 11 17:43:58 2008 @@ -3,7 +3,10 @@ PyPy's ctypes implementation ============================= -terminology: +Summary +======== + +Terminology: * application level code - code written in full Python @@ -22,9 +25,9 @@ implementation. This allowed to provide a working implementation with a large part of ctypes features in 2 months real time. -We reused the ``ctypes`` package as-is from CPython. We implemented -``_ctypes`` which is a C module in CPython mostly in pure Python based on -a lower-level layer extension module ``_rawffi``. +We reused the ``ctypes`` package version 1.0.2 as-is from CPython. We +implemented ``_ctypes`` which is a C module in CPython mostly in pure +Python based on a lower-level layer extension module ``_rawffi``. .. _`libffi`: http://sources.redhat.com/libffi/ @@ -59,7 +62,7 @@ support pinning, which is not the case right now). The consequence of this is that sometimes copying instead of sharing is required, this may result in some semantics differences. C objects created with -_rawffi itself are allocated outside of the GC heap, so they can be +_rawffi itself are allocated outside of the GC heap, such that they can be passed to external functions without worries. Porting the implementation to interpreter-level should likely improve @@ -113,7 +116,8 @@ To run the test suite a compiled pypy-c is required with the proper configuration. To build the required pypy-c one should inside the checkout:: $ cd pypy/translator/goal - $ ./translate.py --text --batch --gc=generation targetpypystandalone.py --withmod-_rawffi --allworkingmodules + $ ./translate.py --text --batch --gc=generation targetpypystandalone.py + --withmod-_rawffi --allworkingmodules this should produce a pypy-c executable in the ``goal`` directory. From pedronis at codespeak.net Fri Apr 11 17:44:57 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 11 Apr 2008 17:44:57 +0200 (CEST) Subject: [pypy-svn] r53693 - pypy/tag/ctypes-stable Message-ID: <20080411154457.D3360398002@codespeak.net> Author: pedronis Date: Fri Apr 11 17:44:57 2008 New Revision: 53693 Added: pypy/tag/ctypes-stable/ - copied from r53692, pypy/branch/ctypes-stable/ Log: making the ctypes stable tag From arigo at codespeak.net Fri Apr 11 18:39:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 18:39:12 +0200 (CEST) Subject: [pypy-svn] r53694 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080411163912.2239F2A01B1@codespeak.net> Author: arigo Date: Fri Apr 11 18:39:11 2008 New Revision: 53694 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py Log: Typo (not really a bug, as it is unlikely to change anything in practice). Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Fri Apr 11 18:39:11 2008 @@ -121,7 +121,7 @@ def malloc_fixedsize_clear(self, typeid, size, can_collect, has_finalizer=False, contains_weakptr=False): if (has_finalizer or not can_collect or - (raw_malloc_usage(size) > self.lb_young_var_basesize and + (raw_malloc_usage(size) > self.lb_young_fixedsize and raw_malloc_usage(size) > self.largest_young_fixedsize)): # ^^^ we do two size comparisons; the first one appears redundant, # but it can be constant-folded if 'size' is a constant; then From arigo at codespeak.net Fri Apr 11 20:24:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 20:24:30 +0200 (CEST) Subject: [pypy-svn] r53700 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20080411182430.B7F3E39B5A4@codespeak.net> Author: arigo Date: Fri Apr 11 20:24:30 2008 New Revision: 53700 Modified: pypy/dist/pypy/rpython/memory/support.py pypy/dist/pypy/rpython/memory/test/test_support.py Log: A foreach() method on AddressStack. As it turned out, I don't need it, but it can't hurt to check it in anyway. Modified: pypy/dist/pypy/rpython/memory/support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/support.py (original) +++ pypy/dist/pypy/rpython/memory/support.py Fri Apr 11 20:24:30 2008 @@ -110,6 +110,20 @@ cur = next free_non_gc_object(self) + def foreach(self, callback, arg): + """Invoke 'callback(address, arg)' for all addresses in the stack. + Typically, 'callback' is a bound method and 'arg' can be None. + """ + chunk = self.chunk + count = self.used_in_last_chunk + while chunk: + while count > 0: + count -= 1 + callback(chunk.items[count], arg) + chunk = chunk.next + count = chunk_size + foreach._annspecialcase_ = 'specialize:arg(1)' + cache[chunk_size] = AddressStack return AddressStack Modified: pypy/dist/pypy/rpython/memory/test/test_support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_support.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_support.py Fri Apr 11 20:24:30 2008 @@ -61,6 +61,23 @@ for addr in addrs: raw_free(addr) + def test_foreach(self): + AddressStack = get_address_stack() + addrs = [raw_malloc(llmemory.sizeof(lltype.Signed)) + for i in range(3000)] + ll = AddressStack() + for i in range(3000): + ll.append(addrs[i]) + + seen = [] + + def callback(addr, fortytwo): + assert fortytwo == 42 + seen.append(addr) + + ll.foreach(callback, 42) + assert seen == addrs or seen[::-1] == addrs # order not guaranteed + class TestAddressDeque: def test_big_access(self): From arigo at codespeak.net Fri Apr 11 20:25:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 20:25:39 +0200 (CEST) Subject: [pypy-svn] r53701 - pypy/branch/hybrid-gc Message-ID: <20080411182539.E0F741684DC@codespeak.net> Author: arigo Date: Fri Apr 11 20:25:37 2008 New Revision: 53701 Added: pypy/branch/hybrid-gc/ - copied from r53700, pypy/dist/ Log: A branch to play with a hybrid generational and mark-n-sweep GC. From arigo at codespeak.net Fri Apr 11 20:26:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 20:26:33 +0200 (CEST) Subject: [pypy-svn] r53702 - in pypy/branch/hybrid-gc/pypy: config rpython/memory/gc rpython/memory/test Message-ID: <20080411182633.65BF92A01A6@codespeak.net> Author: arigo Date: Fri Apr 11 20:26:32 2008 New Revision: 53702 Added: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py (contents, props changed) Modified: pypy/branch/hybrid-gc/pypy/config/translationoption.py pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py pypy/branch/hybrid-gc/pypy/rpython/memory/gc/generation.py pypy/branch/hybrid-gc/pypy/rpython/memory/gc/semispace.py pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_transformed_gc.py Log: Initial check-in. test_gc passes but test_transformed_gc shows obscure failures. Modified: pypy/branch/hybrid-gc/pypy/config/translationoption.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/config/translationoption.py (original) +++ pypy/branch/hybrid-gc/pypy/config/translationoption.py Fri Apr 11 20:26:32 2008 @@ -41,7 +41,7 @@ requires=[("translation.backend", "llvm")]), ChoiceOption("gc", "Garbage Collection Strategy", ["boehm", "ref", "marksweep", "semispace", "statistics", - "generation", "none"], + "generation", "hybrid", "none"], "ref", requires={ "ref": [("translation.rweakref", False), # XXX ("translation.gctransformer", "ref")], @@ -51,6 +51,7 @@ "marksweep": [("translation.gctransformer", "framework")], "statistics": [("translation.gctransformer", "framework")], "generation": [("translation.gctransformer", "framework")], + "hybrid": [("translation.gctransformer", "framework")], "boehm": [("translation.gctransformer", "boehm")], }, cmdline="--gc"), Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py Fri Apr 11 20:26:32 2008 @@ -281,13 +281,18 @@ GC_PARAMS = {'space_size': 8*1024*1024} # XXX adjust from pypy.rpython.memory.gc.semispace import SemiSpaceGC return SemiSpaceGC, GC_PARAMS - elif config.translation.gc == "generation": + elif config.translation.gc in ("generation", "hybrid"): GC_PARAMS = {'space_size': 8*1024*1024, # XXX adjust 'nursery_size': 896*1024, 'min_nursery_size': 48*1024, 'auto_nursery_size': True} - from pypy.rpython.memory.gc.generation import GenerationGC - return GenerationGC, GC_PARAMS + if config.translation.gc == "generation": + from pypy.rpython.memory.gc.generation import GenerationGC + return GenerationGC, GC_PARAMS + else: + GC_PARAMS['large_size'] = 1024 # XXX adjust + from pypy.rpython.memory.gc.hybrid import HybridGC + return HybridGC, GC_PARAMS else: raise ValueError("unknown value for translation.gc: %r" % ( config.translation.gc,)) Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/generation.py Fri Apr 11 20:26:32 2008 @@ -1,5 +1,6 @@ import sys -from pypy.rpython.memory.gc.semispace import SemiSpaceGC, GCFLAG_IMMORTAL +from pypy.rpython.memory.gc.semispace import SemiSpaceGC +from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE @@ -226,6 +227,12 @@ flags=GCFLAG_NO_YOUNG_PTRS|GCFLAG_NO_HEAP_PTRS): SemiSpaceGC.init_gc_object_immortal(self, addr, typeid, flags) + # flags exposed for the HybridGC subclass + GCFLAGS_FOR_NEW_YOUNG_OBJECTS = 0 # NO_YOUNG_PTRS never set on young objs + GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS = (GCFLAG_EXTERNAL | GCFLAG_FORWARDED | + GCFLAG_NO_YOUNG_PTRS) + + def semispace_collect(self, size_changing=False): self.reset_young_gcflags() # we are doing a full collection anyway self.weakrefs_grow_older() Added: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- (empty file) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py Fri Apr 11 20:26:32 2008 @@ -0,0 +1,162 @@ +import sys +from pypy.rpython.memory.gc.semispace import SemiSpaceGC +from pypy.rpython.memory.gc.generation import GenerationGC +from pypy.rpython.lltypesystem import llmemory, llarena +from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage +from pypy.rlib.debug import ll_assert +from pypy.rlib.rarithmetic import ovfcheck + +GCFLAG_MARK = GenerationGC.first_unused_gcflag << 0 + + +class HybridGC(GenerationGC): + """A two-generations semi-space GC like the GenerationGC, + except that objects above a certain size are handled separately: + they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion. + """ + first_unused_gcflag = GenerationGC.first_unused_gcflag << 1 + + def __init__(self, *args, **kwds): + large_object = kwds.pop('large_object', 32) + GenerationGC.__init__(self, *args, **kwds) + + # Objects whose total size is at least 'large_object' bytes are + # allocated separately in a mark-n-sweep fashion. In this + # class, we assume that the 'large_object' limit is not very high, + # so that all objects that wouldn't easily fit in the nursery + # are considered large by this limit. This is the meaning of + # the 'assert' below. + self.nonlarge_max = large_object - 1 + assert self.nonlarge_max <= self.lb_young_var_basesize + self.large_objects_collect_trigger = self.space_size + + def setup(self): + self.large_objects_list = self.AddressDeque() + GenerationGC.setup(self) + + # NB. to simplify the code, only varsized objects can be considered + # 'large'. + + def malloc_varsize_clear(self, typeid, length, size, itemsize, + offset_to_length, can_collect, + has_finalizer=False): + if has_finalizer or not can_collect: + return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size, + itemsize, offset_to_length, + can_collect, has_finalizer) + size_gc_header = self.gcheaderbuilder.size_gc_header + nonvarsize = size_gc_header + size + + # Compute the maximal length that makes the object still + # below 'nonlarge_max'. All the following logic is usually + # constant-folded because self.nonlarge_max, size and itemsize + # are all constants (the arguments are constant due to + # inlining). + if not raw_malloc_usage(itemsize): + too_many_items = raw_malloc_usage(nonvarsize) > self.nonlarge_max + else: + maxlength = self.nonlarge_max - raw_malloc_usage(nonvarsize) + maxlength = maxlength // raw_malloc_usage(itemsize) + too_many_items = length > maxlength + + if not too_many_items: + # With the above checks we know now that totalsize cannot be more + # than 'nonlarge_max'; in particular, the + and * cannot overflow. + # Let's try to fit the object in the nursery. + totalsize = nonvarsize + itemsize * length + result = self.nursery_free + if raw_malloc_usage(totalsize) <= self.nursery_top - result: + llarena.arena_reserve(result, totalsize) + # GCFLAG_NO_YOUNG_PTRS is never set on young objs + self.init_gc_object(result, typeid, flags=0) + (result + size_gc_header + offset_to_length).signed[0] = length + self.nursery_free = result + llarena.round_up_for_allocation( + totalsize) + return llmemory.cast_adr_to_ptr(result+size_gc_header, + llmemory.GCREF) + return self.malloc_varsize_slowpath(typeid, length) + + def malloc_varsize_slowpath(self, typeid, length): + # For objects that are too large, or when the nursery is exhausted. + # In order to keep malloc_varsize_clear() as compact as possible, + # we recompute what we need in this slow path instead of passing + # it all as function arguments. + size_gc_header = self.gcheaderbuilder.size_gc_header + nonvarsize = size_gc_header + self.fixed_size(typeid) + itemsize = self.varsize_item_sizes(typeid) + offset_to_length = self.varsize_offset_to_length(typeid) + try: + varsize = ovfcheck(itemsize * length) + totalsize = ovfcheck(nonvarsize + varsize) + except OverflowError: + raise MemoryError() + if raw_malloc_usage(totalsize) > self.nonlarge_max: + result = self.malloc_varsize_marknsweep(totalsize) + flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS + else: + result = self.malloc_varsize_collecting_nursery(totalsize) + flags = self.GCFLAGS_FOR_NEW_YOUNG_OBJECTS + self.init_gc_object(result, typeid, flags) + (result + size_gc_header + offset_to_length).signed[0] = length + return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) + + malloc_varsize_slowpath._dont_inline_ = True + + def malloc_varsize_collecting_nursery(self, totalsize): + result = self.collect_nursery() + ll_assert(raw_malloc_usage(totalsize) <= self.nursery_top - result, + "not enough room in malloc_varsize_collecting_nursery()") + llarena.arena_reserve(result, totalsize) + self.nursery_free = result + llarena.round_up_for_allocation( + totalsize) + return result + + def malloc_varsize_marknsweep(self, totalsize): + # In order to free the large objects from time to time, we + # arbitrarily force a full collect() if none occurs when we have + # allocated 'self.space_size' bytes of large objects. + self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) + if self.large_objects_collect_trigger < 0: + self.semispace_collect() + # XXX maybe we should use llarena.arena_malloc above a certain size? + result = llmemory.raw_malloc(totalsize) + if not result: + raise MemoryError() + # The parent classes guarantee zero-filled allocations, so we + # need to follow suit. + llmemory.raw_memclear(result, totalsize) + size_gc_header = self.gcheaderbuilder.size_gc_header + self.large_objects_list.append(result + size_gc_header) + return result + + # the following methods are hook into SemiSpaceGC.semispace_collect() + + def starting_full_collect(self): + # This hook is not really necessary but it's a nice place + # to put the following comment: + # No object should have a GCFLAG_MARK at this point + # (except some prebuilt objects but they are ignored). + pass + + def visit_external_object(self, obj): + # leave a GCFLAG_MARK on all external objects visited (some + # prebuilt objects will also get the flag, but it doesn't matter) + self.header(obj).tid |= GCFLAG_MARK + + def finished_full_collect(self): + # free all mark-n-sweep-managed objects that have not been marked + large_objects = self.large_objects_list + remaining_large_objects = self.AddressDeque() + while large_objects.non_empty(): + obj = large_objects.popleft() + if self.header(obj).tid & GCFLAG_MARK: + self.header(obj).tid -= GCFLAG_MARK + remaining_large_objects.append(obj) + else: + addr = obj - self.gcheaderbuilder.size_gc_header + llmemory.raw_free(addr) + large_objects.delete() + self.large_objects_list = remaining_large_objects + # As we just collected, it's fine to raw_malloc'ate up to space_size + # bytes again before we should force another collect. + self.large_objects_collect_trigger = self.space_size Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/semispace.py Fri Apr 11 20:26:32 2008 @@ -16,7 +16,9 @@ TYPEID_MASK = 0xffff first_gcflag = 1 << 16 GCFLAG_FORWARDED = first_gcflag -GCFLAG_IMMORTAL = first_gcflag << 1 +# GCFLAG_EXTERNAL is set on objects not living in the semispace: +# either immortal objects or (for HybridGC) externally raw_malloc'ed +GCFLAG_EXTERNAL = first_gcflag << 1 GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2 DEBUG_PRINT = False @@ -218,6 +220,7 @@ self.tospace = tospace self.top_of_space = tospace + self.space_size scan = self.free = tospace + self.starting_full_collect() self.collect_roots() if self.run_finalizers.non_empty(): self.update_run_finalizers() @@ -226,6 +229,7 @@ scan = self.deal_with_objects_with_finalizers(scan) if self.objects_with_weakrefs.non_empty(): self.invalidate_weakrefs() + self.finished_full_collect() self.notify_objects_just_moved() if not size_changing: llarena.arena_reset(fromspace, self.space_size, True) @@ -268,6 +272,12 @@ llop.debug_print(lltype.Void, "`----------------------------------------------") + def starting_full_collect(self): + pass # hook for the HybridGC + + def finished_full_collect(self): + pass # hook for the HybridGC + def record_red_zone(self): # red zone: if the space is more than 80% full, the next collection # should double its size. If it is more than 66% full twice in a row, @@ -330,12 +340,17 @@ def get_forwarding_address(self, obj): tid = self.header(obj).tid - if tid & GCFLAG_IMMORTAL: - return obj # prebuilt objects are "forwarded" to themselves + if tid & GCFLAG_EXTERNAL: + self.visit_external_object(obj) + return obj # external or prebuilt objects are "forwarded" + # to themselves else: stub = llmemory.cast_adr_to_ptr(obj, self.FORWARDSTUBPTR) return stub.forw + def visit_external_object(self, obj): + pass # hook for the HybridGC + def set_forwarding_address(self, obj, newobj, objsize): # To mark an object as forwarded, we set the GCFLAG_FORWARDED and # overwrite the object with a FORWARDSTUB. Doing so is a bit @@ -344,7 +359,7 @@ size_gc_header = self.size_gc_header() stubsize = llmemory.sizeof(self.FORWARDSTUB) tid = self.header(obj).tid - ll_assert(tid & GCFLAG_IMMORTAL == 0, "unexpected GCFLAG_IMMORTAL") + ll_assert(tid & GCFLAG_EXTERNAL == 0, "unexpected GCFLAG_EXTERNAL") ll_assert(tid & GCFLAG_FORWARDED == 0, "unexpected GCFLAG_FORWARDED") # replace the object at 'obj' with a FORWARDSTUB. hdraddr = obj - size_gc_header @@ -371,7 +386,7 @@ def get_type_id(self, addr): tid = self.header(addr).tid - ll_assert(tid & (GCFLAG_FORWARDED|GCFLAG_IMMORTAL) != GCFLAG_FORWARDED, + ll_assert(tid & (GCFLAG_FORWARDED|GCFLAG_EXTERNAL) != GCFLAG_FORWARDED, "get_type_id on forwarded obj") # Non-prebuilt forwarded objects are overwritten with a FORWARDSTUB. # Although calling get_type_id() on a forwarded object works by itself, @@ -385,7 +400,7 @@ def init_gc_object_immortal(self, addr, typeid, flags=0): hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR)) - hdr.tid = typeid | flags | GCFLAG_IMMORTAL | GCFLAG_FORWARDED + hdr.tid = typeid | flags | GCFLAG_EXTERNAL | GCFLAG_FORWARDED # immortal objects always have GCFLAG_FORWARDED set; # see get_forwarding_address(). Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py Fri Apr 11 20:26:32 2008 @@ -414,3 +414,6 @@ return 0 res = self.interpret(malloc_a_lot, [], backendopt=True, coalloc=True) assert res == 0 + +class TestHybridGC(TestGenerationalGC): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_transformed_gc.py Fri Apr 11 20:26:32 2008 @@ -921,3 +921,14 @@ run = self.runner(f, nbargs=0) res = run([]) assert res == 40 * 5 + +class TestHybridGC(TestGenerationGC): + gcname = "hybrid" + + class gcpolicy(gc.FrameworkGcPolicy): + class transformerclass(framework.FrameworkGCTransformer): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_PARAMS = {'space_size': 2048, + 'nursery_size': 128, + 'large_object': 32} + root_stack_depth = 200 From fijal at codespeak.net Fri Apr 11 21:12:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Apr 2008 21:12:18 +0200 (CEST) Subject: [pypy-svn] r53703 - pypy/branch/jit-hotpath/pypy/jit/tl Message-ID: <20080411191218.31C9D2A01A6@codespeak.net> Author: fijal Date: Fri Apr 11 21:12:15 2008 New Revision: 53703 Added: pypy/branch/jit-hotpath/pypy/jit/tl/grep.py (contents, props changed) Log: work-in-progress. The fastest grep on earth Added: pypy/branch/jit-hotpath/pypy/jit/tl/grep.py ============================================================================== --- (empty file) +++ pypy/branch/jit-hotpath/pypy/jit/tl/grep.py Fri Apr 11 21:12:15 2008 @@ -0,0 +1,16 @@ + +""" Fully controlled, dead-simple nfa engine +""" + +class BaseMatch(object): + pass + +class Single(BaseMatch): + def __init__(self, char): + self.char = char + +def parse(elements): + xxx + + + From arigo at codespeak.net Fri Apr 11 21:46:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 21:46:26 +0200 (CEST) Subject: [pypy-svn] r53704 - in pypy/branch/hybrid-gc/pypy/rpython/memory: gc test Message-ID: <20080411194626.079FA2A01C0@codespeak.net> Author: arigo Date: Fri Apr 11 21:46:25 2008 New Revision: 53704 Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py Log: Test and fix. Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py Fri Apr 11 21:46:25 2008 @@ -6,7 +6,7 @@ from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck -GCFLAG_MARK = GenerationGC.first_unused_gcflag << 0 +GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0 class HybridGC(GenerationGC): @@ -29,6 +29,7 @@ self.nonlarge_max = large_object - 1 assert self.nonlarge_max <= self.lb_young_var_basesize self.large_objects_collect_trigger = self.space_size + self.pending_external_object_list = self.AddressDeque() def setup(self): self.large_objects_list = self.AddressDeque() @@ -92,7 +93,7 @@ raise MemoryError() if raw_malloc_usage(totalsize) > self.nonlarge_max: result = self.malloc_varsize_marknsweep(totalsize) - flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS + flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED else: result = self.malloc_varsize_collecting_nursery(totalsize) flags = self.GCFLAGS_FOR_NEW_YOUNG_OBJECTS @@ -129,32 +130,51 @@ self.large_objects_list.append(result + size_gc_header) return result + # ___________________________________________________________________ # the following methods are hook into SemiSpaceGC.semispace_collect() def starting_full_collect(self): - # This hook is not really necessary but it's a nice place - # to put the following comment: - # No object should have a GCFLAG_MARK at this point - # (except some prebuilt objects but they are ignored). - pass + # At the start of a collection, all raw_malloc'ed objects should + # have the GCFLAG_UNVISITED bit set. No other object ever has + # this bit set. + ll_assert(not self.pending_external_object_list.non_empty(), + "pending_external_object_list should be empty at start") def visit_external_object(self, obj): - # leave a GCFLAG_MARK on all external objects visited (some - # prebuilt objects will also get the flag, but it doesn't matter) - self.header(obj).tid |= GCFLAG_MARK + hdr = self.header(obj) + if hdr.tid & GCFLAG_UNVISITED: + # This is a not-visited-yet raw_malloced object. + hdr.tid -= GCFLAG_UNVISITED + self.pending_external_object_list.append(obj) + + def scan_copied(self, scan): + # Alternate between scanning the regular objects we just moved + # and scanning the raw_malloc'ed object we just visited. + progress = True + while progress: + newscan = GenerationGC.scan_copied(self, scan) + progress = newscan != scan + scan = newscan + while self.pending_external_object_list.non_empty(): + obj = self.pending_external_object_list.popleft() + self.trace_and_copy(obj) + progress = True + return scan def finished_full_collect(self): + ll_assert(not self.pending_external_object_list.non_empty(), + "pending_external_object_list should be empty at end") # free all mark-n-sweep-managed objects that have not been marked large_objects = self.large_objects_list remaining_large_objects = self.AddressDeque() while large_objects.non_empty(): obj = large_objects.popleft() - if self.header(obj).tid & GCFLAG_MARK: - self.header(obj).tid -= GCFLAG_MARK - remaining_large_objects.append(obj) - else: + if self.header(obj).tid & GCFLAG_UNVISITED: addr = obj - self.gcheaderbuilder.size_gc_header llmemory.raw_free(addr) + else: + self.header(obj).tid |= GCFLAG_UNVISITED + remaining_large_objects.append(obj) large_objects.delete() self.large_objects_list = remaining_large_objects # As we just collected, it's fine to raw_malloc'ate up to space_size Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/test/test_gc.py Fri Apr 11 21:46:25 2008 @@ -417,3 +417,14 @@ class TestHybridGC(TestGenerationalGC): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + + def test_ref_from_rawmalloced_to_regular(self): + import gc + def concat(j): + lst = [] + for i in range(j): + lst.append(str(i)) + gc.collect() + return len("".join(lst)) + res = self.interpret(concat, [100]) + assert res == concat(100) From arigo at codespeak.net Fri Apr 11 22:05:48 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 22:05:48 +0200 (CEST) Subject: [pypy-svn] r53705 - pypy/branch/hybrid-gc/pypy/translator/c/test Message-ID: <20080411200548.07DE92A01B1@codespeak.net> Author: arigo Date: Fri Apr 11 22:05:48 2008 New Revision: 53705 Modified: pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py Log: Add tests in genc too. Modified: pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py Fri Apr 11 22:05:48 2008 @@ -899,3 +899,7 @@ class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" should_be_moving = True + +class TestHybridGC(TestGenerationalGC): + gcpolicy = "hybrid" + should_be_moving = True From arigo at codespeak.net Fri Apr 11 22:06:42 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Apr 2008 22:06:42 +0200 (CEST) Subject: [pypy-svn] r53706 - pypy/branch/hybrid-gc/pypy/rpython/memory/gc Message-ID: <20080411200642.CF4502A01B1@codespeak.net> Author: arigo Date: Fri Apr 11 22:06:42 2008 New Revision: 53706 Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py Log: Typo. Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py Fri Apr 11 22:06:42 2008 @@ -290,7 +290,7 @@ from pypy.rpython.memory.gc.generation import GenerationGC return GenerationGC, GC_PARAMS else: - GC_PARAMS['large_size'] = 1024 # XXX adjust + GC_PARAMS['large_object'] = 1024 # XXX adjust from pypy.rpython.memory.gc.hybrid import HybridGC return HybridGC, GC_PARAMS else: From docgok at codespeak.net Sat Apr 12 00:27:35 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Sat, 12 Apr 2008 00:27:35 +0200 (CEST) Subject: [pypy-svn] r53709 - in pypy/branch/io-improvements/pypy: rlib rlib/test rpython/lltypesystem rpython/lltypesystem/test Message-ID: <20080411222735.B025F2A01BF@codespeak.net> Author: docgok Date: Sat Apr 12 00:27:33 2008 New Revision: 53709 Modified: pypy/branch/io-improvements/pypy/rlib/rsocket.py pypy/branch/io-improvements/pypy/rlib/rzlib.py pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Log: New non-moving buffer API usage in new exciting places. Modified: pypy/branch/io-improvements/pypy/rlib/rsocket.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rsocket.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rsocket.py Sat Apr 12 00:27:33 2008 @@ -869,18 +869,18 @@ """Send a data string to the socket. For the optional flags argument, see the Unix manual. Return the number of bytes sent; this may be less than len(data) if the network is busy.""" - dataptr = rffi.str2charp(data) + dataptr = rffi.get_nonmovingbuffer(data) try: return self.send_raw(dataptr, len(data), flags) finally: - rffi.free_charp(dataptr) + rffi.free_nonmovingbuffer(data, dataptr) def sendall(self, data, flags=0): """Send a data string to the socket. For the optional flags argument, see the Unix manual. This calls send() repeatedly until all data is sent. If an error occurs, it's impossible to tell how much data has been sent.""" - dataptr = rffi.str2charp(data) + dataptr = rffi.get_nonmovingbuffer(data) try: remaining = len(data) p = dataptr @@ -889,7 +889,7 @@ p = rffi.ptradd(p, res) remaining -= res finally: - rffi.free_charp(dataptr) + rffi.free_nonmovingbuffer(data, dataptr) def sendto(self, data, flags, address): """Like send(data, flags) but allows specifying the destination @@ -1265,7 +1265,7 @@ raise RSocketError("unknown address family") if len(packed) != srcsize: raise ValueError("packed IP wrong length for inet_ntop") - srcbuf = rffi.str2charp(packed) + srcbuf = rffi.get_nonmovingbuffer(packed) try: dstbuf = mallocbuf(dstsize) try: @@ -1276,7 +1276,7 @@ finally: lltype.free(dstbuf, flavor='raw') finally: - lltype.free(srcbuf, flavor='raw') + lltype.free_nonmovingbuffer(packed, srcbuf) def setdefaulttimeout(timeout): if timeout < 0.0: Modified: pypy/branch/io-improvements/pypy/rlib/rzlib.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rzlib.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rzlib.py Sat Apr 12 00:27:33 2008 @@ -154,9 +154,11 @@ Compute the CRC32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ - bytes = rffi.str2charp(string) - checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) - rffi.free_charp(bytes) + try: + bytes = rffi.get_nonmovingbuffer(string) + checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) + finally: + rffi.free_nonmovingbuffer(string, bytes) return checksum @@ -167,9 +169,11 @@ Compute the Adler-32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ - bytes = rffi.str2charp(string) - checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) - rffi.free_charp(bytes) + try: + bytes = rffi.get_nonmovingbuffer(string) + checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) + finally: + rffi.free_nonmovingbuffer(string, bytes) return checksum # ____________________________________________________________ Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py Sat Apr 12 00:27:33 2008 @@ -1,6 +1,7 @@ import py, errno, sys from pypy.rlib import rsocket from pypy.rlib.rsocket import * +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin import socket as cpy_socket # cannot test error codes in Win32 because ll2ctypes doesn't save @@ -257,23 +258,23 @@ py.test.raises(GAIError, getaddrinfo, 'www.very-invalidaddress.com', None) def test_getaddrinfo_snake(): - lst = getaddrinfo('snake.cs.uni-duesseldorf.de', None) + lst = getaddrinfo('codespeak.net', None) assert isinstance(lst, list) found = False for family, socktype, protocol, canonname, addr in lst: - if addr.get_host() == '134.99.112.214': + if addr.get_host() == '213.239.226.252': found = True assert found, lst def test_getaddrinfo_no_reverse_lookup(): # It seems that getaddrinfo never runs a reverse lookup on Linux. # Python2.3 on Windows returns the hostname. - lst = getaddrinfo('134.99.112.214', None, flags=AI_NUMERICHOST) + lst = getaddrinfo('213.239.226.252', None, flags=AI_NUMERICHOST) assert isinstance(lst, list) found = False for family, socktype, protocol, canonname, addr in lst: - assert canonname != 'snake.cs.uni-duesseldorf.de' - if addr.get_host() == '134.99.112.214': + assert canonname != 'codespeak.net' + if addr.get_host() == '213.239.226.252': found = True assert found, lst @@ -369,7 +370,30 @@ clientsock.close() s.close() + +class BaseSendRecvTest(BaseRtypingTest): + def test_socketpair(self): + if sys.platform == "win32": + py.test.skip('No socketpair on Windows') + + def f(): + s1, s2 = socketpair() + s1.sendall('?') + buf = s2.recv(100) + assert buf == '?' + count = s2.send('x'*99) + assert 1 <= count <= 99 + buf = s1.recv(100) + assert buf == 'x'*count + s1.close() + s2.close() + self.interpret(f,[]) + +class TestSendRecvMovingGc(BaseSendRecvTest, LLRtypeMixin): + MOVING_GC = True +class TestSendRecvNonMovingGc(BaseSendRecvTest, LLRtypeMixin): + MOVING_GC = False class TestTCP: PORT = 50007 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Sat Apr 12 00:27:33 2008 @@ -489,7 +489,7 @@ else: data_start = cast_ptr_to_adr(llstr(data)) + \ offsetof(rstr.STR, 'chars') + itemoffsetof(rstr.STR.chars, 0) - return cast(VOIDP, data_start) + return cast(CCHARP, data_start) # (str, char*) -> None def free_nonmovingbuffer(data, buf): Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Sat Apr 12 00:27:33 2008 @@ -648,10 +648,10 @@ free_nonmovingbuffer(d, buf) self.interpret(f, []) -class TestNonmovingBuffer(BaseInterpretedTestRffi, LLRtypeMixin): - pass +class TestNonmovingBufferMovingGc(BaseInterpretedTestRffi, LLRtypeMixin): + MOVING_GC = True -class TestLLtypeNonMovingGc(BaseInterpretedTestRffi, LLRtypeMixin): +class TestNonmovingBufferNonMovingGc(BaseInterpretedTestRffi, LLRtypeMixin): MOVING_GC = False class TestCRffi(BaseTestRffi): From cfbolz at codespeak.net Sat Apr 12 08:30:29 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 12 Apr 2008 08:30:29 +0200 (CEST) Subject: [pypy-svn] r53710 - pypy/extradoc/talk/rupy2008 Message-ID: <20080412063029.72CC039B5D4@codespeak.net> Author: cfbolz Date: Sat Apr 12 08:30:27 2008 New Revision: 53710 Modified: pypy/extradoc/talk/rupy2008/PyPy-architecture.odp pypy/extradoc/talk/rupy2008/talk.tex Log: train changes Modified: pypy/extradoc/talk/rupy2008/PyPy-architecture.odp ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/rupy2008/talk.tex ============================================================================== --- pypy/extradoc/talk/rupy2008/talk.tex (original) +++ pypy/extradoc/talk/rupy2008/talk.tex Sat Apr 12 08:30:27 2008 @@ -15,7 +15,7 @@ \usepackage{times} \usepackage[T1]{fontenc} -\title{PyPy ? status and next goals} +\title{PyPy ? Status and Next Goals} \author{Carl Friedrich Bolz} @@ -63,14 +63,22 @@ \begin{frame} \frametitle{What is PyPy?} + ... pretty pictures and demos +\end{frame} + + +\begin{frame} + \frametitle{What is PyPy?} \begin{itemize} \item A flexible toolkit for writing interpreters \begin{itemize} \item + geared at dynamic languages + \item giving you lots of help \item - translation to lots of environments + translation to various of environments (C, .NET, Java) \item a mostly good GC \item @@ -80,9 +88,11 @@ \end{itemize} \pause \item - the biggest implemented interpreter is a full Python interpreter + a Python interpreter \begin{itemize} \item + using the toolkit + \item implementing Python 2.4 semantics fully \item extra features @@ -93,18 +103,13 @@ \item experimental things like lazy evaluation \end{itemize} + \item most important goal: flexibility at all levels \item Open Source project (MIT licenced) \end{itemize} \end{frame} -\begin{frame} - \frametitle{What is PyPy?} - ... pretty pictures and demos -\end{frame} - - \begin{frame} @@ -141,9 +146,8 @@ \frametitle{CTypes} \begin{itemize} \item CTypes is a libffi wrapper for CPython - \item implemented in C - \item can be used to wrap C libraries rather effortlessly \item no need to write C code to interface with libraries + \item can be used to wrap C libraries rather effortlessly \end{itemize} \pause @@ -180,7 +184,6 @@ % no, it is mentioned in the pictures part \item when translating to C, a GC is integrated into the program \item GCs are completely written in RPython - \item similar to the MMTK toolkit of Jikes RVM \item two fast GCs: semispace, generational \item lots of care to get the semantics right: \begin{itemize} @@ -190,7 +193,7 @@ \end{itemize} \item performance pretty good \item memory-bound benchmarks faster than CPython - \item ... demo + \item ... tiny demo \end{itemize} \end{frame} @@ -200,6 +203,7 @@ Problems: \begin{itemize} \item writing good JITs for dynamic languages is hard work + \item good performance needs lots of care \item keeping up with new language features is hard \item compilers are a bad encoding for language semantics \pause @@ -221,7 +225,7 @@ \begin{itemize} \item If you cannot write a JIT, don't do that then \pause - \item Idea: Automatically Generate the JIT from the interpreter + \item Idea: Automatically generate the JIT from the interpreter \pause \end{itemize} \begin{block}{ @@ -241,8 +245,8 @@ Writing a JIT generator is hard, but: \begin{itemize} \item You only need to do it once - \item the effort of writing a JIT generator is independent of the size of the language \item can keep up with language evolution + \item the JIT is correct by construction \item retargetting the JIT is possible (e.g. to .NET, as Antonio Cuni is doing right now) \item make the JIT behave radically differently is much easier with a generator \item it's fun too @@ -262,7 +266,6 @@ \item goes into the direction of a tracing JIT \item right now we are starting to hit the hard bits \item we hope to get really good results for more general code in a few months - \item ... demo \end{itemize} \end{frame} From arigo at codespeak.net Sat Apr 12 11:12:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Apr 2008 11:12:59 +0200 (CEST) Subject: [pypy-svn] r53712 - in pypy/branch/hybrid-gc/pypy: rpython/memory/gc translator/c/test Message-ID: <20080412091259.18F7939B5F4@codespeak.net> Author: arigo Date: Sat Apr 12 11:12:58 2008 New Revision: 53712 Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py Log: A comment. Mark gc_set_max_heap_size() as not implemented. Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py Sat Apr 12 11:12:58 2008 @@ -30,11 +30,19 @@ assert self.nonlarge_max <= self.lb_young_var_basesize self.large_objects_collect_trigger = self.space_size self.pending_external_object_list = self.AddressDeque() + # XXX we could use two limits: it could be larger for objects + # that contain gc references than for objects that don't. The + # idea is that separately allocated objects are allocated + # immediately "old" and it's not good to have too many pointers + # from old to young objects. def setup(self): self.large_objects_list = self.AddressDeque() GenerationGC.setup(self) + def set_max_heap_size(self, size): + raise NotImplementedError + # NB. to simplify the code, only varsized objects can be considered # 'large'. Modified: pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-gc/pypy/translator/c/test/test_newgc.py Sat Apr 12 11:12:58 2008 @@ -903,3 +903,6 @@ class TestHybridGC(TestGenerationalGC): gcpolicy = "hybrid" should_be_moving = True + + def test_gc_set_max_heap_size(self): + py.test.skip("not implemented") From cfbolz at codespeak.net Sat Apr 12 11:47:15 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 12 Apr 2008 11:47:15 +0200 (CEST) Subject: [pypy-svn] r53713 - pypy/dist/pypy/translator/cli Message-ID: <20080412094715.3CE3B49801A@codespeak.net> Author: cfbolz Date: Sat Apr 12 11:47:14 2008 New Revision: 53713 Modified: pypy/dist/pypy/translator/cli/opcodes.py Log: fix cli translation by dummy-implementing the finalizers enabling/disabling ops Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Sat Apr 12 11:47:14 2008 @@ -67,6 +67,8 @@ 'cast_ptr_to_weakadr': [PushAllArgs, 'newobj instance void class %s::.ctor(object)' % WEAKREF], 'gc__collect': 'call void class [mscorlib]System.GC::Collect()', 'gc_set_max_heap_size': Ignore, + 'gc__enable_finalizers': Ignore, + 'gc__disable_finalizers': Ignore, 'resume_point': Ignore, 'debug_assert': Ignore, 'keepalive': Ignore, From arigo at codespeak.net Sat Apr 12 12:01:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Apr 2008 12:01:56 +0200 (CEST) Subject: [pypy-svn] r53714 - in pypy/dist/pypy: config config/test rlib translator/goal Message-ID: <20080412100156.D3840168511@codespeak.net> Author: arigo Date: Sat Apr 12 12:01:56 2008 New Revision: 53714 Modified: pypy/dist/pypy/config/config.py pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/config/test/test_config.py pypy/dist/pypy/config/test/test_pypyoption.py pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/translator/goal/translate.py Log: * Add a hook allowing code to check if bool options can be enabled. * Use the hook to check if libffi is installed, for '_rawffi'. * Use a custom ConfigError instead of ValueError to report bad option combinations. * Add a way to report warnings. Modified: pypy/dist/pypy/config/config.py ============================================================================== --- pypy/dist/pypy/config/config.py (original) +++ pypy/dist/pypy/config/config.py Sat Apr 12 12:01:56 2008 @@ -10,6 +10,9 @@ class NoMatchingOptionFound(AttributeError): pass +class ConfigError(Exception): + pass + class Config(object): _cfgimpl_frozen = False @@ -18,6 +21,7 @@ self._cfgimpl_value_owners = {} self._cfgimpl_parent = parent self._cfgimpl_values = {} + self._cfgimpl_warnings = [] self._cfgimpl_build(overrides) def _cfgimpl_build(self, overrides): @@ -95,7 +99,7 @@ if oldvalue != value and oldowner not in ("default", "suggested"): if who in ("default", "suggested"): return - raise ValueError('cannot override value to %s for option %s' % + raise ConfigError('cannot override value to %s for option %s' % (value, name)) child.setoption(self, value, who) self._cfgimpl_value_owners[name] = who @@ -128,6 +132,12 @@ self = self._cfgimpl_parent return self + def add_warning(self, warning): + self._cfgimpl_get_toplevel()._cfgimpl_warnings.append(warning) + + def get_warnings(self): + return self._cfgimpl_get_toplevel()._cfgimpl_warnings + def _freeze_(self): self.__dict__['_cfgimpl_frozen'] = True return True @@ -197,7 +207,7 @@ if who == "default" and value is None: pass elif not self.validate(value): - raise ValueError('invalid value %s for option %s' % (value, name)) + raise ConfigError('invalid value %s for option %s' % (value, name)) config._cfgimpl_values[name] = value def getkey(self, value): @@ -240,7 +250,7 @@ homeconfig, name = toplevel._cfgimpl_get_home_by_path(path) try: homeconfig.setoption(name, reqvalue, "suggested") - except ValueError: + except ConfigError: # setting didn't work, but that is fine, since it is # suggested only pass @@ -262,19 +272,23 @@ class BoolOption(Option): def __init__(self, name, doc, default=None, requires=None, - suggests=None, + suggests=None, validator=None, cmdline=DEFAULT_OPTION_NAME, negation=True): super(BoolOption, self).__init__(name, doc, cmdline=cmdline) self._requires = requires self._suggests = suggests self.default = default self.negation = negation + self._validator = validator def validate(self, value): return isinstance(value, bool) def setoption(self, config, value, who): name = self._name + if value and self._validator is not None: + toplevel = config._cfgimpl_get_toplevel() + self._validator(toplevel) if value and self._requires is not None: for path, reqvalue in self._requires: toplevel = config._cfgimpl_get_toplevel() @@ -286,7 +300,7 @@ homeconfig, name = toplevel._cfgimpl_get_home_by_path(path) try: homeconfig.setoption(name, reqvalue, "suggested") - except ValueError: + except ConfigError: # setting didn't work, but that is fine, since it is # suggested pass @@ -330,7 +344,7 @@ try: super(IntOption, self).setoption(config, int(value), who) except TypeError, e: - raise ValueError(*e.args) + raise ConfigError(*e.args) class FloatOption(Option): @@ -351,7 +365,7 @@ try: super(FloatOption, self).setoption(config, float(value), who) except TypeError, e: - raise ValueError(*e.args) + raise ConfigError(*e.args) class StrOption(Option): @@ -368,7 +382,7 @@ try: super(StrOption, self).setoption(config, value, who) except TypeError, e: - raise ValueError(*e.args) + raise ConfigError(*e.args) class ArbitraryOption(Option): @@ -505,7 +519,7 @@ try: value = self.convert_from_cmdline(value) self.config.setoption(self.option._name, value, who='cmdline') - except ValueError, e: + except ConfigError, e: raise optparse.OptionValueError(e.args[0]) def help_default(self): Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sat Apr 12 12:01:56 2008 @@ -3,6 +3,7 @@ import sys from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config +from pypy.config.config import ConfigError modulepath = py.magic.autopath().dirpath().dirpath().join("module") all_modules = [p.basename for p in modulepath.listdir() @@ -44,6 +45,29 @@ if os.name == "posix": module_dependencies['rctime'] = [("objspace.usemodules.select", True),] +module_import_dependencies = { + # no _rawffi if importing pypy.rlib.libffi raises ImportError + "_rawffi": ["pypy.rlib.libffi"], + } + +def get_module_validator(modname): + if modname in module_import_dependencies: + modlist = module_import_dependencies[modname] + def validator(config): + try: + for name in modlist: + __import__(name) + except ImportError, e: + err = "%s: %s" % (e.__class__.__name__, e) + config.add_warning( + "The module %r is disabled\n" % (modname,) + + "because importing %s raised\n" % (name,) + + err) + raise ConfigError("--withmod-%s: %s" % (modname, err)) + return validator + else: + return None + pypy_optiondescription = OptionDescription("objspace", "Object Space Options", [ ChoiceOption("name", "Object Space name", @@ -89,7 +113,8 @@ cmdline="--withmod-%s" % (modname, ), requires=module_dependencies.get(modname, []), suggests=module_suggests.get(modname, []), - negation=modname not in essential_modules) + negation=modname not in essential_modules, + validator=get_module_validator(modname)) for modname in all_modules]), BoolOption("allworkingmodules", "use as many working modules as possible", Modified: pypy/dist/pypy/config/test/test_config.py ============================================================================== --- pypy/dist/pypy/config/test/test_config.py (original) +++ pypy/dist/pypy/config/test/test_config.py Sat Apr 12 12:01:56 2008 @@ -50,17 +50,17 @@ config.str = "def" assert config.str == "def" - py.test.raises(ValueError, 'config.objspace = "foo"') - py.test.raises(ValueError, 'config.gc.name = "foo"') + py.test.raises(ConfigError, 'config.objspace = "foo"') + py.test.raises(ConfigError, 'config.gc.name = "foo"') py.test.raises(AttributeError, 'config.gc.foo = "bar"') - py.test.raises(ValueError, 'config.bool = 123') - py.test.raises(ValueError, 'config.int = "hello"') - py.test.raises(ValueError, 'config.gc.float = None') + py.test.raises(ConfigError, 'config.bool = 123') + py.test.raises(ConfigError, 'config.int = "hello"') + py.test.raises(ConfigError, 'config.gc.float = None') config = Config(descr, bool=False) assert config.gc.name == 'ref' config.wantframework = True - py.test.raises(ValueError, 'config.gc.name = "ref"') + py.test.raises(ConfigError, 'config.gc.name = "ref"') config.gc.name = "framework" def test_arbitrary_option(): @@ -439,7 +439,7 @@ assert not c2.s1.a c2.s1.a = True assert c2.s1.a - py.test.raises(ValueError, "c2.int = 44") + py.test.raises(ConfigError, "c2.int = 44") c2 = c1.copy(as_default=True) assert c2.int == 43 assert not c2.s1.a @@ -542,3 +542,32 @@ assert c.int == 42 c.int = 45 assert c.int == 45 + +def test_validator(): + def my_validator_1(config): + assert config is c + + def my_validator_2(config): + assert config is c + raise ConfigError + + descr = OptionDescription("opt", "", [ + BoolOption('booloption1', 'option test1', default=False, + validator=my_validator_1), + BoolOption('booloption2', 'option test2', default=False, + validator=my_validator_2), + BoolOption('booloption3', 'option test3', default=False, + requires=[("booloption2", True)]), + BoolOption('booloption4', 'option test4', default=False, + suggests=[("booloption2", True)]), + ]) + c = Config(descr) + c.booloption1 = True + py.test.raises(ConfigError, "c.booloption2 = True") + assert c.booloption2 is False + py.test.raises(ConfigError, "c.booloption3 = True") + assert c.booloption2 is False + c.booloption4 = True + assert c.booloption2 is False + c.booloption2 = False + assert c.booloption2 is False 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 Sat Apr 12 12:01:56 2008 @@ -1,6 +1,6 @@ import py from pypy.config.pypyoption import get_pypy_config -from pypy.config.config import Config +from pypy.config.config import Config, ConfigError thisdir = py.magic.autopath().dirpath() @@ -14,7 +14,7 @@ assert not conf.objspace.std.withprebuiltint conf = get_pypy_config() conf.objspace.std.withprebuiltint = True - py.test.raises(ValueError, "conf.objspace.std.withsmallint = True") + py.test.raises(ConfigError, "conf.objspace.std.withsmallint = True") def test_stacklessgc_required(): conf = get_pypy_config() @@ -25,7 +25,7 @@ assert conf.translation.gc == "generation" conf = get_pypy_config() conf.translation.gc = "boehm" - py.test.raises(ValueError, "conf.translation.gcrootfinder = 'stackless'") + py.test.raises(ConfigError, "conf.translation.gcrootfinder = 'stackless'") def test_frameworkgc(): Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Sat Apr 12 12:01:56 2008 @@ -51,6 +51,9 @@ ffi_closure = rffi_platform.Struct('ffi_closure', []) +if not rffi_platform.check_eci(CConfig._compilation_info_): + raise ImportError("cannot find an installed 'libffi' library") + def add_simple_type(type_name): for name in ['size', 'alignment', 'type']: setattr(CConfig, type_name + '_' + name, Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Sat Apr 12 12:01:56 2008 @@ -193,6 +193,8 @@ def log_config(config, header="config used"): log('%s:' % header) log(str(config)) + for warning in config.get_warnings(): + log.WARNING(warning) def main(): targetspec_dic, translateconfig, config, args = parse_options_and_load_target() From arigo at codespeak.net Sat Apr 12 12:31:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Apr 2008 12:31:09 +0200 (CEST) Subject: [pypy-svn] r53715 - pypy/dist/pypy/translator/c Message-ID: <20080412103109.8891049800E@codespeak.net> Author: arigo Date: Sat Apr 12 12:31:06 2008 New Revision: 53715 Modified: pypy/dist/pypy/translator/c/genc.py Log: Complete "make clean". Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sat Apr 12 12:31:06 2008 @@ -846,7 +846,7 @@ \t$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@ || (rm -f $@ && exit 1) clean: -\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) +\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) *.gc?? debug: \t$(MAKE) CFLAGS="-g -DRPY_ASSERT" From fijal at codespeak.net Sat Apr 12 18:21:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:21:47 +0200 (CEST) Subject: [pypy-svn] r53722 - in pypy/branch/io-improvements/pypy/rpython/module: . test Message-ID: <20080412162147.225FD16A20F@codespeak.net> Author: fijal Date: Sat Apr 12 18:21:46 2008 New Revision: 53722 Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Log: Run this test directly instead of on top of llinterp. this is because implementing rffi.cast on top of llinterp correctly is an awful mess Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Sat Apr 12 18:21:46 2008 @@ -24,6 +24,7 @@ from pypy.rpython.lltypesystem.llmemory import raw_memcopy, sizeof,\ itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.annlowlevel import llstr posix = __import__(os.name) Modified: pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Sat Apr 12 18:21:46 2008 @@ -155,6 +155,9 @@ pass class TestLLtypeNonMovingGc(BaseTestPosix, LLRtypeMixin): + def interpret(self, f, args): + return f(*args) + MOVING_GC = False class TestOOtype(BaseTestPosix, OORtypeMixin): From fijal at codespeak.net Sat Apr 12 18:34:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:34:59 +0200 (CEST) Subject: [pypy-svn] r53723 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080412163459.1F2CC16A490@codespeak.net> Author: fijal Date: Sat Apr 12 18:34:57 2008 New Revision: 53723 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: don't try to interpret this stuff Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sat Apr 12 18:34:57 2008 @@ -381,9 +381,10 @@ + llmemory.itemoffsetof(STR.chars, 0)) buf = rffi.cast(rffi.VOIDP, b) return buf[2] - #assert f() == 'z' - res = interpret(f, []) - assert res == 'z' + assert f() == 'z' + # XXX let's say we don't run it on top of llinterp + #res = interpret(f, []) + #assert res == 'z' def test_funcptr1(self): def dummy(n): From fijal at codespeak.net Sat Apr 12 18:35:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:35:12 +0200 (CEST) Subject: [pypy-svn] r53724 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080412163512.5EAF32D80C9@codespeak.net> Author: fijal Date: Sat Apr 12 18:35:11 2008 New Revision: 53724 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Log: Port tests to be slightly different Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Sat Apr 12 18:35:11 2008 @@ -430,6 +430,38 @@ unregister_keepalive(pos, TP) assert res == 8 + def test_nonmovingbuffer(self): + d = 'some cool data that should not move' + def f(): + buf = lltype.nullptr(CCHARP.TO) + try: + buf = get_nonmovingbuffer(d) + counter = 0 + for i in range(len(d)): + if buf[i] == d[i]: + counter += 1 + return counter + finally: + free_nonmovingbuffer(d, buf) + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == len(d) + + def test_nonmovingbuffer_semispace(self): + d = 'some cool data that should not move' + def f(): + buf = lltype.nullptr(CCHARP.TO) + try: + buf = get_nonmovingbuffer(d) + counter = 0 + for i in range(len(d)): + if buf[i] == d[i]: + counter += 1 + return counter + finally: + free_nonmovingbuffer(d, buf) + fn = self.compile(f, [], gcpolicy='semispace') + assert fn(expected_extra_mallocs=9) == len(d) + class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) @@ -635,25 +667,6 @@ def test_ptradd_interpret(): interpret(test_ptradd, []) -class BaseInterpretedTestRffi(BaseRtypingTest): - def test_nonmovingbuffer(self): - def f(): - buf = lltype.nullptr(CCHARP.TO) - d = 'some cool data that should not move' - try: - buf = get_nonmovingbuffer(d) - for i in range(len(d)): - assert buf[i] == d[i] - finally: - free_nonmovingbuffer(d, buf) - self.interpret(f, []) - -class TestNonmovingBufferMovingGc(BaseInterpretedTestRffi, LLRtypeMixin): - MOVING_GC = True - -class TestNonmovingBufferNonMovingGc(BaseInterpretedTestRffi, LLRtypeMixin): - MOVING_GC = False - class TestCRffi(BaseTestRffi): def compile(self, func, args, **kwds): return compile_c(func, args, **kwds) @@ -669,5 +682,11 @@ del kwds['backendopt'] return compile_llvm(func, args, **kwds) + def test_nonmovingbuffer(self): + py.test.skip("Somewhat buggy...") + + def test_nonmovingbuffer_semispace(self): + py.test.skip("LLVM backend error - unsupported operator") + def test_hashdefine(self): py.test.skip("Macros cannot be called as llexternals by design, rffi does not have any special support for them") From fijal at codespeak.net Sat Apr 12 18:40:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:40:57 +0200 (CEST) Subject: [pypy-svn] r53725 - pypy/branch/io-improvements/pypy/rpython/module/test Message-ID: <20080412164057.4C72E16A4F4@codespeak.net> Author: fijal Date: Sat Apr 12 18:40:56 2008 New Revision: 53725 Modified: pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Log: This test stopped making sense. Modified: pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/test/test_posix.py Sat Apr 12 18:40:56 2008 @@ -154,12 +154,6 @@ class TestLLtype(BaseTestPosix, LLRtypeMixin): pass -class TestLLtypeNonMovingGc(BaseTestPosix, LLRtypeMixin): - def interpret(self, f, args): - return f(*args) - - MOVING_GC = False - class TestOOtype(BaseTestPosix, OORtypeMixin): def test_fstat(self): py.test.skip("ootypesystem does not support os.fstat") From fijal at codespeak.net Sat Apr 12 18:43:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:43:02 +0200 (CEST) Subject: [pypy-svn] r53726 - pypy/branch/io-improvements/pypy/translator/c/test Message-ID: <20080412164302.463A016A500@codespeak.net> Author: fijal Date: Sat Apr 12 18:43:01 2008 New Revision: 53726 Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py Log: Make this test run on both moving and not moving gc Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py Sat Apr 12 18:43:01 2008 @@ -77,6 +77,25 @@ assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) +def test_open_read_write_seek_close_moving(): + filename = str(udir.join('test_open_read_write_close.txt')) + def does_stuff(): + fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) + count = os.write(fd, "hello world\n") + assert count == len("hello world\n") + os.close(fd) + fd = os.open(filename, os.O_RDONLY, 0777) + result = os.lseek(fd, 1, 0) + assert result == 1 + data = os.read(fd, 500) + assert data == "ello world\n" + os.close(fd) + + f1 = compile(does_stuff, [], gcpolicy='semispace') + f1(expected_extra_mallocs=9) + assert open(filename, 'r').read() == "hello world\n" + os.unlink(filename) + def test_big_read(): filename = str(udir.join('test_open_read_write_close.txt')) def does_stuff(): From fijal at codespeak.net Sat Apr 12 18:45:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:45:20 +0200 (CEST) Subject: [pypy-svn] r53727 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080412164520.B4F8A16A4FD@codespeak.net> Author: fijal Date: Sat Apr 12 18:45:20 2008 New Revision: 53727 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py Log: this makes no sense (is inserted automatically anyway) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py Sat Apr 12 18:45:20 2008 @@ -711,8 +711,6 @@ RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) TYPE1 = v_arg.concretetype - if TYPE1 is llmemory.Address: - v_arg = gen_cast(hop.llops, lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)), v_arg) return gen_cast(hop.llops, RESTYPE, v_arg) def typecheck_ptradd(T): From fijal at codespeak.net Sat Apr 12 18:50:16 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 18:50:16 +0200 (CEST) Subject: [pypy-svn] r53728 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080412165016.BF87C16A4ED@codespeak.net> Author: fijal Date: Sat Apr 12 18:50:16 2008 New Revision: 53728 Modified: pypy/branch/io-improvements/pypy/rlib/rsocket.py pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py Log: Always run tests! Kill nonworking tests and fix typo catched by others. Modified: pypy/branch/io-improvements/pypy/rlib/rsocket.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rsocket.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rsocket.py Sat Apr 12 18:50:16 2008 @@ -1276,7 +1276,7 @@ finally: lltype.free(dstbuf, flavor='raw') finally: - lltype.free_nonmovingbuffer(packed, srcbuf) + rffi.free_nonmovingbuffer(packed, srcbuf) def setdefaulttimeout(timeout): if timeout < 0.0: Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rsocket.py Sat Apr 12 18:50:16 2008 @@ -370,30 +370,6 @@ clientsock.close() s.close() - -class BaseSendRecvTest(BaseRtypingTest): - def test_socketpair(self): - if sys.platform == "win32": - py.test.skip('No socketpair on Windows') - - def f(): - s1, s2 = socketpair() - s1.sendall('?') - buf = s2.recv(100) - assert buf == '?' - count = s2.send('x'*99) - assert 1 <= count <= 99 - buf = s1.recv(100) - assert buf == 'x'*count - s1.close() - s2.close() - self.interpret(f,[]) - -class TestSendRecvMovingGc(BaseSendRecvTest, LLRtypeMixin): - MOVING_GC = True - -class TestSendRecvNonMovingGc(BaseSendRecvTest, LLRtypeMixin): - MOVING_GC = False class TestTCP: PORT = 50007 From fijal at codespeak.net Sat Apr 12 19:04:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Apr 2008 19:04:34 +0200 (CEST) Subject: [pypy-svn] r53729 - pypy/branch/io-improvements/pypy/translator/c/test Message-ID: <20080412170434.ABE7B2D80CF@codespeak.net> Author: fijal Date: Sat Apr 12 19:04:34 2008 New Revision: 53729 Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py Log: move this test to test_newgc, now it's run against all gcs Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_extfunc.py Sat Apr 12 19:04:34 2008 @@ -77,25 +77,6 @@ assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) -def test_open_read_write_seek_close_moving(): - filename = str(udir.join('test_open_read_write_close.txt')) - def does_stuff(): - fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) - count = os.write(fd, "hello world\n") - assert count == len("hello world\n") - os.close(fd) - fd = os.open(filename, os.O_RDONLY, 0777) - result = os.lseek(fd, 1, 0) - assert result == 1 - data = os.read(fd, 500) - assert data == "ello world\n" - os.close(fd) - - f1 = compile(does_stuff, [], gcpolicy='semispace') - f1(expected_extra_mallocs=9) - assert open(filename, 'r').read() == "hello world\n" - os.unlink(filename) - def test_big_read(): filename = str(udir.join('test_open_read_write_close.txt')) def does_stuff(): Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py Sat Apr 12 19:04:34 2008 @@ -2,6 +2,7 @@ import sys import py from py.test import raises +import os from pypy.objspace.flow.model import summary from pypy.translator.translator import TranslationContext @@ -11,6 +12,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.memory.test import snippet from pypy import conftest +from pypy.tool.udir import udir def compile_func(fn, inputtypes, t=None, gcpolicy="ref"): from pypy.config.pypyoption import get_pypy_config @@ -813,6 +815,25 @@ c_fn = self.getcompiled(f) assert c_fn() == 0 + def test_open_read_write_seek_close(self): + filename = str(udir.join('test_open_read_write_close.txt')) + def does_stuff(): + fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) + count = os.write(fd, "hello world\n") + assert count == len("hello world\n") + os.close(fd) + fd = os.open(filename, os.O_RDONLY, 0777) + result = os.lseek(fd, 1, 0) + assert result == 1 + data = os.read(fd, 500) + assert data == "ello world\n" + os.close(fd) + + f1 = self.getcompiled(does_stuff, []) + f1() + assert open(filename, 'r').read() == "hello world\n" + os.unlink(filename) + class TestUsingStacklessFramework(TestUsingFramework): @@ -840,6 +861,9 @@ def test_weakref(self): py.test.skip("fails for some reason I couldn't figure out yet :-(") + def test_open_read_write_seek_close(self): + py.test.skip("str complaining") + class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTests): gcpolicy = "semispace" should_be_moving = True @@ -895,7 +919,6 @@ res = c_fn() assert res == 2 - class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" should_be_moving = True From cami at codespeak.net Sat Apr 12 22:13:30 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 12 Apr 2008 22:13:30 +0200 (CEST) Subject: [pypy-svn] r53730 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080412201330.6FDEB2D80D4@codespeak.net> Author: cami Date: Sat Apr 12 22:13:28 2008 New Revision: 53730 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: restructured cartridge, introduced helper functions Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat Apr 12 22:13:28 2008 @@ -82,22 +82,34 @@ self.mbc.write(address, data) def load(self, cartridgeName): + self.loadROM() + self.checkROM() + self.createRAM() + self.loadBattery() + self.mbc = self.createBankController(self.getCartridgeType(), rom, ram, clock) + + def loadROM(self): romSize = self.store.getCartridgeSize(cartridgeName) self.rom = [0]*romSize self.store.readCartridge(cartridgeName, self.rom) + + def checkROM(self): if not self.verifyHeader(): raise Exeption("Cartridge header is corrupted") if romSize < self.getROMSize(): raise Exeption("Cartridge is truncated") + + def createRAM(self): ramSize = self.getRAMSize() if (getCartridgeType() >= constants.TYPE_MBC2 and getCartridgeType() <= constants.TYPE_MBC2_BATTERY): ramSize = 512 self.ram = [0xFF]*ramSize + + def loadBattery(self): if self.store.hasBattery(cartridgeName): self.store.readBattery(cartridgeName, ram) - self.mbc = createBankController(self.getCartridgeType(), rom, ram, clock) - + def save(self, cartridgeName): if self.hasBattery(): self.store.writeBattery(cartridgeName, self.ram) @@ -116,7 +128,9 @@ for address in range(0x0134, 0x014C): checksum = (checksum - (rom[address] & 0xFF)) & 0xFF return (checksum == self.getHeaderChecksum()) - + + def createBankController(self, type, rom, ram, clockDriver): + return MEMORY_BANK_MAPPING[type](rom, ram, clockDriver) def CartridgeStoreManager(object): @@ -126,8 +140,8 @@ def setCartridgeName(self, cartridgeName): self.cartridgeName = cartridgeName self.batteryName = self.createBatteryName() - self.cartridgeFile = File(self.cartridgeName) - self.batteryFile = File(self.batteryName) + self.cartridgeFile = open(self.cartridgeName) + self.batteryFile = open(self.batteryName) def createBatteryName(self): if self.cartridgeName.endsWith(constants.CARTRIDGE_FILE_EXTENSION): @@ -208,6 +222,10 @@ # CARTRIDGE TYPES class MBC(object): + + def __init__(self, rom, ram, clockDriver): + self.setROM(rom) + self.setRAM(ram) def reset(self): self.romBank = constants.ROM_BANK_SIZE @@ -261,13 +279,13 @@ 4000-7FFF ROM Bank 1-127 (16KB) A000-BFFF RAM Bank 0-3 (8KB) """ - def __init__(self, rom, ram): + def __init__(self, rom, ram, clockDriver): + self.reset() self.minRamBankSize = 0 self.maxRamBankSize = 4 self.minRomBankSize = 2 self.maxRomBankSize = 128 - self.setRom(rom) - self.serRam(ram) + super.__init__(rom, ram, clockDriver) def reset(self): super.reset() @@ -275,27 +293,33 @@ def write(self, address, data): if (address <= 0x1FFF): # 0000-1FFF - if (self.ramSize > 0): - self.ramEnable = ((data & 0x0A) == 0x0A) + self.writeRAMEnable(address, data) elif (address <= 0x3FFF): # 2000-3FFF - if ((data & 0x1F) == 0): - data = 1 - if (self.memoryModel == 0): - self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize - else: - self.romBank = ((data & 0x1F) << 14) & self.romSize + self.writeROMBank1(address, data) elif (address <= 0x5FFF): # 4000-5FFF - if (self.memoryModel == 0): - self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize - else: - self.ramBank = ((data & 0x03) << 13) & self.ramSize + self.writeROMBank2(address, data) elif (address <= 0x7FFF): # 6000-7FFF self.memoryModel = data & 0x01 elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF self.ram[self.ramBank + (address & 0x1FFF)] = data + def writeRAMEnable(self, address, data): + if (self.ramSize > 0): + self.ramEnable = ((data & 0x0A) == 0x0A) + + def writeROMBank1(self, address, data): + if ((data & 0x1F) == 0): + data = 1 + if (self.memoryModel == 0): + self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize + else: + self.romBank = ((data & 0x1F) << 14) & self.romSize - + def writeROMBank2(self, address, data): + if (self.memoryModel == 0): + self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize + else: + self.ramBank = ((data & 0x03) << 13) & self.ramSize class MBC2(MBC): """ @@ -310,14 +334,14 @@ RAM_BANK_SIZE = 512 - def __init__(self, rom, ram): + def __init__(self, rom, ram, clockDriver): + self.reset() self.minRamBankSize = constants.RAM_BANK_SIZE self.maxRamBankSize = constants.RAM_BANK_SIZE self.minRomBankSize = 2 self.maxRomBankSize = 16 + super.__init__(rom, ram, clockDriver) - self.setROM(rom) - self.setRAM(ram) def read(self, address): if address > 0xA1FF: @@ -327,39 +351,28 @@ def write(self, address, data): if (address <= 0x1FFF): # 0000-1FFF - if ((address & 0x0100) == 0): - self.ramEnable = ((data & 0x0A) == 0x0A) + self.writeRAMEnable(address, data) elif (address <= 0x3FFF): # 2000-3FFF - if ((address & 0x0100) != 0): - if ((data & 0x0F) == 0): - data = 1 - self.romBank = ((data & 0x0F) << 14) & self.romSize + self.writeROMBank() elif (address >= 0xA000 and address <= 0xA1FF): # A000-A1FF - if (self.ramEnable): - self.ram[address & 0x01FF] = (byte) (data & 0x0F) + self.writeRAMEnable(address, data) + + def writeRAMEnable(self, address, data): + if (address & 0x0100) == 0: + self.ramEnable = ((data & 0x0A) == 0x0A) + + def writeROMBank(self, address): + if (address & 0x0100) == 0: + return + if (data & 0x0F) == 0: + data = 1 + self.romBank = ((data & 0x0F) << 14) & self.romSize + + def writeRAM(self, address, data): + if self.ramEnable: + self.ram[address & 0x01FF] = (byte) (data & 0x0F) - def write(self, address, data): - if (address <= 0x1FFF): # 0000-1FFF - if (self.ramSize > 0): - self.ramEnable = ((data & 0x0A) == 0x0A) - elif (address <= 0x3FFF): # 2000-3FFF - if ((data & 0x1F) == 0): - data = 1 - if (self.memoryModel == 0): - self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize - else: - self.romBank = ((data & 0x1F) << 14) & self.romSize - elif (address <= 0x5FFF): # 4000-5FFF - if (self.memoryModel == 0): - self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize - else: - self.ramBank = ((data & 0x03) << 13) & self.ramSize - elif (address <= 0x7FFF): # 6000-7FFF - self.memoryModel = data & 0x01 - elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF - self.ram[self.ramBank + (address & 0x1FFF)] = data - class MBC3(MBC): @@ -373,29 +386,18 @@ A000-BFFF RAM Bank 0-3 (8KB) """ - clockSeconds = 0 - clockMinutes = 0 - clockHours = 0 - clockDays = 0 - clockControl = None - clockLSeconds = 0 - clockLMinutes = 0 - clockLHours = 0 - clockLDaysclockLControl = None - def __init__(self, rom, ram, clock): + self.reset() self.minRamBankSize = 0 self.maxRamBankSize = 4 self.minRomBankSize = 2 self.maxRomBankSize = 128 self.clock = clock - self.clockRegister = 0 - self.clockLatch = 0 - self.clockTime = 0 + self.clockLDaysclockLControl = None - self.setROM(rom) - self.setRAM(ram) + super.__init__(rom, ram, clockDriver) + self.reset() def reset(): @@ -411,55 +413,72 @@ if (self.ramBank >= 0): return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF else: - if (self.clockRegister == 0x08): - return self.clockLSeconds - if (self.clockRegister == 0x09): - return self.clockLMinutes - if (self.clockRegister == 0x0A): - return self.clockLHours - if (self.clockRegister == 0x0B): - return self.clockLDays - if (self.clockRegister == 0x0C): - return self.clockLControl + return self.readClockData(address) else: return super.read(address) - + + def readClockDaata(self, address): + if (self.clockRegister == 0x08): + return self.clockLSeconds + if (self.clockRegister == 0x09): + return self.clockLMinutes + if (self.clockRegister == 0x0A): + return self.clockLHours + if (self.clockRegister == 0x0B): + return self.clockLDays + if (self.clockRegister == 0x0C): + return self.clockLControl def write(self, address, data): if (address <= 0x1FFF): # 0000-1FFF - if (self.ramSize > 0): - self.ramEnable = ((data & 0x0A) == 0x0A) + self.writeRAMEnable(address, data) elif (address <= 0x3FFF): # 2000-3FFF - if (data == 0): - data = 1 - self.romBank = ((data & 0x7F) << 14) & self.romSize + self.writeROMBank(address, data) elif (address <= 0x5FFF): # 4000-5FFF - if (data >= 0x00 and data <= 0x03): - self.ramBank = (data << 13) & self.ramSize - else: - self.ramBank = -1 - self.clockRegister = data + self.writeRAMBank(address, data) elif (address <= 0x7FFF): # 6000-7FFF - if (self.clockLatch == 0 and data == 1): - self.latchClock() - if (data == 0 or data == 1): - self.clockLatch = data + self.writeClockLatch(address, data) elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF - if (self.ramBank >= 0): - self.ram[self.ramBank + (address & 0x1FFF)] = data - else: - self.updateClock() - if (self.clockRegister == 0x08): - self.clockSeconds = data - if (self.clockRegister == 0x09): - self.clockMinutes = data - if (self.clockRegister == 0x0A): - self.clockHours = data - if (self.clockRegister == 0x0B): - self.clockDays = data - if (self.clockRegister == 0x0C): - self.clockControl = (self.clockControl & 0x80) | data - + self.writeClockData(address, data) + + def writeRAMEnable(self, address, data): + if (self.ramSize > 0): + self.ramEnable = ((data & 0x0A) == 0x0A) + + def writeROMBank(self, address, data): + if (data == 0): + data = 1 + self.romBank = ((data & 0x7F) << 14) & self.romSize + + def writeRAMBank(self, address, data): + if (data >= 0x00 and data <= 0x03): + self.ramBank = (data << 13) & self.ramSize + else: + self.ramBank = -1 + self.clockRegister = data + + def writeClockLatch(self, address, data): + if (self.clockLatch == 0 and data == 1): + self.latchClock() + if (data == 0 or data == 1): + self.clockLatch = data + + def writeClockData(self, address, data): + if (self.ramBank >= 0): + self.ram[self.ramBank + (address & 0x1FFF)] = data + else: + self.updateClock() + if (self.clockRegister == 0x08): + self.clockSeconds = data + if (self.clockRegister == 0x09): + self.clockMinutes = data + if (self.clockRegister == 0x0A): + self.clockHours = data + if (self.clockRegister == 0x0B): + self.clockDays = data + if (self.clockRegister == 0x0C): + self.clockControl = (self.clockControl & 0x80) | data + def latchClock(self): self.updateClock() @@ -510,39 +529,43 @@ 4000-7FFF ROM Bank 1-511 (16KB) A000-BFFF RAM Bank 0-15 (8KB) """ - def __init__(self, rom, ram, rumble): + def __init__(self, rom, ram, clockDriver, rumble): + self.reset() self.minRamBankSize = 0 self.maxRamBankSize = 16 self.minRomBankSize = 2 self.maxRomBankSize = 512 self.rumble = rumble - self.setROM(rom) - self.setRAM(ram) + super.__init__(rom, ram, clockDriver) def write(self, address, data): if (address <= 0x1FFF): # 0000-1FFF - if (self.ramSize > 0): - self.ramEnable = ((data & 0x0A) == 0x0A) + self.writeRAMEnable(address, data) elif (address <= 0x2FFF): # 2000-2FFF self.romBank = ((self.romBank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize elif (address <= 0x3FFF): # 3000-3FFF self.romBank = ((self.romBank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize elif (address <= 0x4FFF): # 4000-4FFF - if (self.rumble): - self.ramBank = ((data & 0x07) << 13) & self.ramSize - else: - self.ramBank = ((data & 0x0F) << 13) & self.ramSize + self.writeRAMBank(address, data) elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF self.ram[self.ramBank + (address & 0x1FFF)] = data - - + def writeRAMEnable(self, address, data): + if (self.ramSize > 0): + self.ramEnable = ((data & 0x0A) == 0x0A) + + def writeRAMBank(self, address, data): + if (self.rumble): + self.ramBank = ((data & 0x07) << 13) & self.ramSize + else: + self.ramBank = ((data & 0x0F) << 13) & self.ramSize class HuC1(MBC): - def __init__(self, ram, rom): - super.__init__(self, ram, rom) + def __init__(self, ram, rom, clockDriver): + self.reset() + super.__init__(rom, ram, clockDriver) class HuC3(MBC): @@ -556,6 +579,7 @@ A000-BFFF RAM Bank 0-15 (8KB) """ def __init__(self, rom, ram, clock): + self.reset() self.minRamBankSize = 0 self.maxRamBankSize = 4 self.minRomBankSize = 2 @@ -569,6 +593,7 @@ self.setRAM(ram) self.ramFlag = 0 self.ramValue = 0 + super.__init__(rom, ram, clockDriver) def reset(): @@ -596,44 +621,60 @@ if (address <= 0x1FFF): # 0000-1FFF self.ramFlag = data elif (address <= 0x3FFF):# 2000-3FFF - if ((data & 0x7F) == 0): - data = 1 - self.romBank = ((data & 0x7F) << 14) & self.romSize + self.writeROMBank(address, data) elif (address <= 0x5FFF): # 4000-5FFF self.ramBank = ((data & 0x0F) << 13) & self.ramSize elif (address >= 0xA000 and address <= 0xBFFF): # A000-BFFF - if (self.ramFlag == 0x0B): - self.writeWithRamFlag0x0B(address, data) - elif (self.ramFlag >= 0x0C and self.ramFlag <= 0x0E): - pass - elif (self.ramFlag == 0x0A and self.ramSize > 0): - self.ram[self.ramBank + (address & 0x1FFF)] = data + self.writeRAMFlag(address, data) - + def writeROMBank(self, address, data): + if ((data & 0x7F) == 0): + data = 1 + self.romBank = ((data & 0x7F) << 14) & self.romSize + + def writeRAMFlag(self, address, data): + if (self.ramFlag == 0x0B): + self.writeWithRamFlag0x0B(address, data) + elif (self.ramFlag >= 0x0C and self.ramFlag <= 0x0E): + pass + elif (self.ramFlag == 0x0A and self.ramSize > 0): + self.ram[self.ramBank + (address & 0x1FFF)] = data + def writeWithRamFlag0x0B(self, address, data): if ((data & 0xF0) == 0x10): - if (self.clockShift <= 24): - self.ramValue = (self.clockRegister >> self.clockShift) & 0x0F - self.clockShift += 4 + self.writeRAMValueClockShift(address, data) elif ((data & 0xF0) == 0x30): - if (self.clockShift <= 24): - self.clockRegister &= ~(0x0F << self.clockShift) - self.clockRegister |= ((data & 0x0F) << self.clockShift) - self.clockShift += 4 + self.writeClockRegisterClockShift(address, data) elif ((data & 0xF0) == 0x40): - self.updateClock() - if ((data & 0x0F) == 0x00): - self.clockShift = 0 - elif ((data & 0x0F) == 0x03): - self.clockShift = 0 - elif ((data & 0x0F) == 0x07): - self.clockShift = 0 + self.writeClockShift(address, data) elif ((data & 0xF0) == 0x50): pass elif ((data & 0xF0) == 0x60): self.ramValue = 0x01 + def writeRAMValueClockShift(self, address, data): + if self.clockShift > 24: + return + self.ramValue = (self.clockRegister >> self.clockShift) & 0x0F + self.clockShift += 4 + + def writeClockRegisterClockShift(self, address, data): + if self.clockShift > 24: + return + self.clockRegister &= ~(0x0F << self.clockShift) + self.clockRegister |= ((data & 0x0F) << self.clockShift) + self.clockShift += 4 + def writeClocckShift(self, address, data): + switch = data & 0x0F + self.updateClock() + if switch == 0: + self.clockShift = 0 + elif switch == 3: + self.clockShift = 0 + elif switch == 7: + self.clockShift = 0 + def updateClock(self): now = self.clock.getTime() elapsed = now - self.clockTime @@ -655,9 +696,9 @@ self.clockRegister += (1 << 24) - (365 << 12) self.clockTime = now - elapsed +# MEMORY BANK MAPPING ---------------------------------------------------------- - -CATRIDGE_TYPE_RANGES = [ +MEMORY_BANK_TYPE_RANGES = [ (constants.TYPE_MBC1, constants.TYPE_MBC1_RAM_BATTERY, MBC1), (constants.TYPE_MBC2, constants.TYPE_MBC2_BATTERY, MBC2), (constants.TYPE_MBC3_RTC_BATTERY, constants.TYPE_MBC3_RAM_BATTERY, MBC3), @@ -667,3 +708,16 @@ ] +def initialize_mapping_table(): + result = [None] * 256 + for entry in MEMORY_BANK_TYPE_RANGES: + if len(entry) == 2: + positions = [entry[0]] + else: + positions = range(entry[0], entry[1]+1) + for pos in positions: + result[pos] = entry[-1] + assert None not in result + return result + +MEMORY_BANK_MAPPING = initialize_mapping_table() \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sat Apr 12 22:13:28 2008 @@ -286,6 +286,7 @@ self.interrupt.raiseInterrupt(constants.LCD) else: self.stat &= 0xFB + if (self.lineY < 144): self.stat = (self.stat & 0xFC) | 0x02 self.cycles += constants.MODE_2_TICKS From tverwaes at codespeak.net Sat Apr 12 22:55:10 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 12 Apr 2008 22:55:10 +0200 (CEST) Subject: [pypy-svn] r53731 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080412205510.9F28C169F45@codespeak.net> Author: tverwaes Date: Sat Apr 12 22:55:08 2008 New Revision: 53731 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Log: commented out bogous assert Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat Apr 12 22:55:08 2008 @@ -699,12 +699,12 @@ # MEMORY BANK MAPPING ---------------------------------------------------------- MEMORY_BANK_TYPE_RANGES = [ - (constants.TYPE_MBC1, constants.TYPE_MBC1_RAM_BATTERY, MBC1), - (constants.TYPE_MBC2, constants.TYPE_MBC2_BATTERY, MBC2), - (constants.TYPE_MBC3_RTC_BATTERY, constants.TYPE_MBC3_RAM_BATTERY, MBC3), - (constants.TYPE_MBC5, constants.TYPE_MBC5_RUMBLE_RAM_BATTERY, MBC5), - (constants.TYPE_HUC3_RTC_RAM, constants.TYPE_HUC3_RTC_RAM, HuC3), - (constants.TYPE_HUC1_RAM_BATTERY, constants.TYPE_HUC1_RAM_BATTERY, HuC1) + (constants.TYPE_MBC1, constants.TYPE_MBC1_RAM_BATTERY, MBC1), + (constants.TYPE_MBC2, constants.TYPE_MBC2_BATTERY, MBC2), + (constants.TYPE_MBC3_RTC_BATTERY, constants.TYPE_MBC3_RAM_BATTERY, MBC3), + (constants.TYPE_MBC5, constants.TYPE_MBC5_RUMBLE_RAM_BATTERY, MBC5), + (constants.TYPE_HUC3_RTC_RAM, constants.TYPE_HUC3_RTC_RAM, HuC3), + (constants.TYPE_HUC1_RAM_BATTERY, constants.TYPE_HUC1_RAM_BATTERY, HuC1) ] @@ -717,7 +717,9 @@ positions = range(entry[0], entry[1]+1) for pos in positions: result[pos] = entry[-1] - assert None not in result + # XXX the following assert is disabled because it seems bogous + # in constants, they don't have 256 types... + # assert None not in result return result -MEMORY_BANK_MAPPING = initialize_mapping_table() \ No newline at end of file +MEMORY_BANK_MAPPING = initialize_mapping_table() From fijal at codespeak.net Sun Apr 13 04:10:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Apr 2008 04:10:02 +0200 (CEST) Subject: [pypy-svn] r53733 - pypy/branch/io-improvements/pypy/rpython/memory/gctransform Message-ID: <20080413021002.792EA169EAE@codespeak.net> Author: fijal Date: Sun Apr 13 04:10:01 2008 New Revision: 53733 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Log: actually move this up a bit in subclass hierarchy (framework.py will use it than as well) Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py Sun Apr 13 04:10:01 2008 @@ -141,9 +141,6 @@ resulttype = lltype.Signed) hop.genop('int_invert', [v_int], resultvar=hop.spaceop.result) - def gct_gc_can_move(self, hop): - return hop.cast_result(rmodel.inputconst(lltype.Bool, False)) - ########## weakrefs ########## # Boehm: weakref objects are small structures containing only a Boehm # disappearing link. We don't have to hide the link's value with Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Sun Apr 13 04:10:01 2008 @@ -492,11 +492,11 @@ flags = hop.spaceop.args[1].value flavor = flags['flavor'] meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) - assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) + assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) v_raw = meth(hop, flags, TYPE, c_size) hop.cast_result(v_raw) - + def gct_coalloc(self, hop): TYPE = hop.spaceop.result.concretetype.TO assert not TYPE._is_varsize() @@ -527,12 +527,11 @@ return v_raw def gct_malloc_varsize(self, hop): - flags = hop.spaceop.args[1].value flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) - assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) + assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) def gct_coalloc_varsize(self, hop): @@ -608,3 +607,6 @@ hop.genop('raw_free', [v]) else: assert False, "%s has no support for free with flavor %r" % (self, flavor) + + def gct_gc_can_move(self, hop): + return hop.cast_result(rmodel.inputconst(lltype.Bool, False)) From arigo at codespeak.net Sun Apr 13 10:02:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 10:02:07 +0200 (CEST) Subject: [pypy-svn] r53736 - pypy/branch/hybrid-gc/pypy/rpython/memory/gc Message-ID: <20080413080207.4CEDA16A0AE@codespeak.net> Author: arigo Date: Sun Apr 13 10:02:06 2008 New Revision: 53736 Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py Log: Introduce two 'large object' limits, depending on the presence of gc ptrs in the variable part of the object. Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/base.py Sun Apr 13 10:02:06 2008 @@ -291,6 +291,7 @@ return GenerationGC, GC_PARAMS else: GC_PARAMS['large_object'] = 1024 # XXX adjust + GC_PARAMS['large_object_gcptrs'] = 8192 # XXX adjust from pypy.rpython.memory.gc.hybrid import HybridGC return HybridGC, GC_PARAMS else: Modified: pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py Sun Apr 13 10:02:06 2008 @@ -17,24 +17,28 @@ first_unused_gcflag = GenerationGC.first_unused_gcflag << 1 def __init__(self, *args, **kwds): - large_object = kwds.pop('large_object', 32) + large_object = kwds.pop('large_object', 24) + large_object_gcptrs = kwds.pop('large_object_gcptrs', 32) GenerationGC.__init__(self, *args, **kwds) # Objects whose total size is at least 'large_object' bytes are - # allocated separately in a mark-n-sweep fashion. In this - # class, we assume that the 'large_object' limit is not very high, - # so that all objects that wouldn't easily fit in the nursery - # are considered large by this limit. This is the meaning of - # the 'assert' below. + # allocated separately in a mark-n-sweep fashion. If the object + # has GC pointers in its varsized part, we use instead the + # higher limit 'large_object_gcptrs'. The idea is that + # separately allocated objects are allocated immediately "old" + # and it's not good to have too many pointers from old to young + # objects. + + # In this class, we assume that the 'large_object' limit is not + # very high, so that all objects that wouldn't easily fit in the + # nursery are considered large by this limit. This is the + # meaning of the 'assert' below. self.nonlarge_max = large_object - 1 - assert self.nonlarge_max <= self.lb_young_var_basesize + self.nonlarge_gcptrs_max = large_object_gcptrs - 1 + assert self.nonlarge_gcptrs_max <= self.lb_young_var_basesize + assert self.nonlarge_max <= self.nonlarge_gcptrs_max self.large_objects_collect_trigger = self.space_size self.pending_external_object_list = self.AddressDeque() - # XXX we could use two limits: it could be larger for objects - # that contain gc references than for objects that don't. The - # idea is that separately allocated objects are allocated - # immediately "old" and it's not good to have too many pointers - # from old to young objects. def setup(self): self.large_objects_list = self.AddressDeque() @@ -60,11 +64,16 @@ # below 'nonlarge_max'. All the following logic is usually # constant-folded because self.nonlarge_max, size and itemsize # are all constants (the arguments are constant due to - # inlining). + # inlining) and self.has_gcptr_in_varsize() is constant-folded. + if self.has_gcptr_in_varsize(typeid): + nonlarge_max = self.nonlarge_gcptrs_max + else: + nonlarge_max = self.nonlarge_max + if not raw_malloc_usage(itemsize): - too_many_items = raw_malloc_usage(nonvarsize) > self.nonlarge_max + too_many_items = raw_malloc_usage(nonvarsize) > nonlarge_max else: - maxlength = self.nonlarge_max - raw_malloc_usage(nonvarsize) + maxlength = nonlarge_max - raw_malloc_usage(nonvarsize) maxlength = maxlength // raw_malloc_usage(itemsize) too_many_items = length > maxlength @@ -99,7 +108,11 @@ totalsize = ovfcheck(nonvarsize + varsize) except OverflowError: raise MemoryError() - if raw_malloc_usage(totalsize) > self.nonlarge_max: + if self.has_gcptr_in_varsize(typeid): + nonlarge_max = self.nonlarge_gcptrs_max + else: + nonlarge_max = self.nonlarge_max + if raw_malloc_usage(totalsize) > nonlarge_max: result = self.malloc_varsize_marknsweep(totalsize) flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED else: From arigo at codespeak.net Sun Apr 13 10:11:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 10:11:47 +0200 (CEST) Subject: [pypy-svn] r53737 - in pypy/dist/pypy: config rpython/memory/gc rpython/memory/test translator/c/test Message-ID: <20080413081147.1591A16A0B3@codespeak.net> Author: arigo Date: Sun Apr 13 10:11:46 2008 New Revision: 53737 Added: pypy/dist/pypy/rpython/memory/gc/hybrid.py - copied unchanged from r53736, pypy/branch/hybrid-gc/pypy/rpython/memory/gc/hybrid.py Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/gc/semispace.py pypy/dist/pypy/rpython/memory/test/test_gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: [merge the hybrid-gc branch] A new subclass of GenerationGC: HybridGC, in which objects are allocated in two possible ways: * if they are small enough, they go to the nursery; * above a threshold, they are independently raw_malloc'ed. The raw_malloc'ed objects are handled in mark-n-sweep style at each full collection. Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Sun Apr 13 10:11:46 2008 @@ -41,7 +41,7 @@ requires=[("translation.backend", "llvm")]), ChoiceOption("gc", "Garbage Collection Strategy", ["boehm", "ref", "marksweep", "semispace", "statistics", - "generation", "none"], + "generation", "hybrid", "none"], "ref", requires={ "ref": [("translation.rweakref", False), # XXX ("translation.gctransformer", "ref")], @@ -51,6 +51,7 @@ "marksweep": [("translation.gctransformer", "framework")], "statistics": [("translation.gctransformer", "framework")], "generation": [("translation.gctransformer", "framework")], + "hybrid": [("translation.gctransformer", "framework")], "boehm": [("translation.gctransformer", "boehm")], }, cmdline="--gc"), Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Sun Apr 13 10:11:46 2008 @@ -281,13 +281,19 @@ GC_PARAMS = {'space_size': 8*1024*1024} # XXX adjust from pypy.rpython.memory.gc.semispace import SemiSpaceGC return SemiSpaceGC, GC_PARAMS - elif config.translation.gc == "generation": + elif config.translation.gc in ("generation", "hybrid"): GC_PARAMS = {'space_size': 8*1024*1024, # XXX adjust 'nursery_size': 896*1024, 'min_nursery_size': 48*1024, 'auto_nursery_size': True} - from pypy.rpython.memory.gc.generation import GenerationGC - return GenerationGC, GC_PARAMS + if config.translation.gc == "generation": + from pypy.rpython.memory.gc.generation import GenerationGC + return GenerationGC, GC_PARAMS + else: + GC_PARAMS['large_object'] = 1024 # XXX adjust + GC_PARAMS['large_object_gcptrs'] = 8192 # XXX adjust + from pypy.rpython.memory.gc.hybrid import HybridGC + return HybridGC, GC_PARAMS else: raise ValueError("unknown value for translation.gc: %r" % ( config.translation.gc,)) Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Sun Apr 13 10:11:46 2008 @@ -1,5 +1,6 @@ import sys -from pypy.rpython.memory.gc.semispace import SemiSpaceGC, GCFLAG_IMMORTAL +from pypy.rpython.memory.gc.semispace import SemiSpaceGC +from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE @@ -226,6 +227,12 @@ flags=GCFLAG_NO_YOUNG_PTRS|GCFLAG_NO_HEAP_PTRS): SemiSpaceGC.init_gc_object_immortal(self, addr, typeid, flags) + # flags exposed for the HybridGC subclass + GCFLAGS_FOR_NEW_YOUNG_OBJECTS = 0 # NO_YOUNG_PTRS never set on young objs + GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS = (GCFLAG_EXTERNAL | GCFLAG_FORWARDED | + GCFLAG_NO_YOUNG_PTRS) + + def semispace_collect(self, size_changing=False): self.reset_young_gcflags() # we are doing a full collection anyway self.weakrefs_grow_older() Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/dist/pypy/rpython/memory/gc/semispace.py Sun Apr 13 10:11:46 2008 @@ -16,7 +16,9 @@ TYPEID_MASK = 0xffff first_gcflag = 1 << 16 GCFLAG_FORWARDED = first_gcflag -GCFLAG_IMMORTAL = first_gcflag << 1 +# GCFLAG_EXTERNAL is set on objects not living in the semispace: +# either immortal objects or (for HybridGC) externally raw_malloc'ed +GCFLAG_EXTERNAL = first_gcflag << 1 GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2 DEBUG_PRINT = False @@ -218,6 +220,7 @@ self.tospace = tospace self.top_of_space = tospace + self.space_size scan = self.free = tospace + self.starting_full_collect() self.collect_roots() if self.run_finalizers.non_empty(): self.update_run_finalizers() @@ -226,6 +229,7 @@ scan = self.deal_with_objects_with_finalizers(scan) if self.objects_with_weakrefs.non_empty(): self.invalidate_weakrefs() + self.finished_full_collect() self.notify_objects_just_moved() if not size_changing: llarena.arena_reset(fromspace, self.space_size, True) @@ -268,6 +272,12 @@ llop.debug_print(lltype.Void, "`----------------------------------------------") + def starting_full_collect(self): + pass # hook for the HybridGC + + def finished_full_collect(self): + pass # hook for the HybridGC + def record_red_zone(self): # red zone: if the space is more than 80% full, the next collection # should double its size. If it is more than 66% full twice in a row, @@ -330,12 +340,17 @@ def get_forwarding_address(self, obj): tid = self.header(obj).tid - if tid & GCFLAG_IMMORTAL: - return obj # prebuilt objects are "forwarded" to themselves + if tid & GCFLAG_EXTERNAL: + self.visit_external_object(obj) + return obj # external or prebuilt objects are "forwarded" + # to themselves else: stub = llmemory.cast_adr_to_ptr(obj, self.FORWARDSTUBPTR) return stub.forw + def visit_external_object(self, obj): + pass # hook for the HybridGC + def set_forwarding_address(self, obj, newobj, objsize): # To mark an object as forwarded, we set the GCFLAG_FORWARDED and # overwrite the object with a FORWARDSTUB. Doing so is a bit @@ -344,7 +359,7 @@ size_gc_header = self.size_gc_header() stubsize = llmemory.sizeof(self.FORWARDSTUB) tid = self.header(obj).tid - ll_assert(tid & GCFLAG_IMMORTAL == 0, "unexpected GCFLAG_IMMORTAL") + ll_assert(tid & GCFLAG_EXTERNAL == 0, "unexpected GCFLAG_EXTERNAL") ll_assert(tid & GCFLAG_FORWARDED == 0, "unexpected GCFLAG_FORWARDED") # replace the object at 'obj' with a FORWARDSTUB. hdraddr = obj - size_gc_header @@ -371,7 +386,7 @@ def get_type_id(self, addr): tid = self.header(addr).tid - ll_assert(tid & (GCFLAG_FORWARDED|GCFLAG_IMMORTAL) != GCFLAG_FORWARDED, + ll_assert(tid & (GCFLAG_FORWARDED|GCFLAG_EXTERNAL) != GCFLAG_FORWARDED, "get_type_id on forwarded obj") # Non-prebuilt forwarded objects are overwritten with a FORWARDSTUB. # Although calling get_type_id() on a forwarded object works by itself, @@ -385,7 +400,7 @@ def init_gc_object_immortal(self, addr, typeid, flags=0): hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR)) - hdr.tid = typeid | flags | GCFLAG_IMMORTAL | GCFLAG_FORWARDED + hdr.tid = typeid | flags | GCFLAG_EXTERNAL | GCFLAG_FORWARDED # immortal objects always have GCFLAG_FORWARDED set; # see get_forwarding_address(). Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gc.py Sun Apr 13 10:11:46 2008 @@ -414,3 +414,17 @@ return 0 res = self.interpret(malloc_a_lot, [], backendopt=True, coalloc=True) assert res == 0 + +class TestHybridGC(TestGenerationalGC): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + + def test_ref_from_rawmalloced_to_regular(self): + import gc + def concat(j): + lst = [] + for i in range(j): + lst.append(str(i)) + gc.collect() + return len("".join(lst)) + res = self.interpret(concat, [100]) + assert res == concat(100) 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 Sun Apr 13 10:11:46 2008 @@ -921,3 +921,14 @@ run = self.runner(f, nbargs=0) res = run([]) assert res == 40 * 5 + +class TestHybridGC(TestGenerationGC): + gcname = "hybrid" + + class gcpolicy(gc.FrameworkGcPolicy): + class transformerclass(framework.FrameworkGCTransformer): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_PARAMS = {'space_size': 2048, + 'nursery_size': 128, + 'large_object': 32} + root_stack_depth = 200 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 Sun Apr 13 10:11:46 2008 @@ -899,3 +899,10 @@ class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" should_be_moving = True + +class TestHybridGC(TestGenerationalGC): + gcpolicy = "hybrid" + should_be_moving = True + + def test_gc_set_max_heap_size(self): + py.test.skip("not implemented") From arigo at codespeak.net Sun Apr 13 10:12:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 10:12:10 +0200 (CEST) Subject: [pypy-svn] r53738 - pypy/branch/hybrid-gc Message-ID: <20080413081210.371CA16A0B6@codespeak.net> Author: arigo Date: Sun Apr 13 10:12:09 2008 New Revision: 53738 Removed: pypy/branch/hybrid-gc/ Log: Branch merged. From arigo at codespeak.net Sun Apr 13 12:24:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 12:24:30 +0200 (CEST) Subject: [pypy-svn] r53739 - in pypy/dist/pypy/rpython: lltypesystem ootypesystem Message-ID: <20080413102430.608FF498111@codespeak.net> Author: arigo Date: Sun Apr 13 12:24:28 2008 New Revision: 53739 Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/ootypesystem/rclass.py Log: An optimization that I thought was already done - apparently not. Constant-fold the result of "instance.attr" if the annotator aready says that the result is constant. Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Sun Apr 13 12:24:28 2008 @@ -520,6 +520,8 @@ return instance_repr.getfield(vinst, '__class__', hop.llops) def rtype_getattr(self, hop): + if hop.s_result.is_constant(): + return hop.inputconst(hop.r_result, hop.s_result.const) attr = hop.args_s[1].const vinst, vattr = hop.inputargs(self, Void) if attr == '__class__' and hop.r_result.lowleveltype is Void: Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Sun Apr 13 12:24:28 2008 @@ -380,6 +380,8 @@ return ll_inst_hash def rtype_getattr(self, hop): + if hop.s_result.is_constant(): + return hop.inputconst(hop.r_result, hop.s_result.const) v_inst, _ = hop.inputargs(self, ootype.Void) s_inst = hop.args_s[0] attr = hop.args_s[1].const From arigo at codespeak.net Sun Apr 13 16:23:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 16:23:37 +0200 (CEST) Subject: [pypy-svn] r53740 - pypy/dist/pypy/translator/c Message-ID: <20080413142337.12C71169EFF@codespeak.net> Author: arigo Date: Sun Apr 13 16:23:37 2008 New Revision: 53740 Modified: pypy/dist/pypy/translator/c/genc.py Log: Last time, hopefully, that I get confused about faassen builds which you should not recompile with "make" but with "make profopt". Now a plain "make" does profopt if the Makefile was generated in a profopt translation. Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sun Apr 13 16:23:37 2008 @@ -306,11 +306,7 @@ compiler = self.getccompiler() if self.config.translation.gcrootfinder == "asmgcc": # as we are gcc-only anyway, let's just use the Makefile. - if compiler.profbased: - target = 'profopt' - else: - target = '' # default target - cmdline = "make -C '%s' %s" % (self.targetdir, target) + cmdline = "make -C '%s'" % (self.targetdir,) err = os.system(cmdline) if err != 0: raise OSError("failed (see output): " + cmdline) @@ -375,8 +371,10 @@ cc = 'gcc' if self.config.translation.profopt: profopt = self.config.translation.profopt + default_target = 'profopt' else: profopt = '' + default_target = '$(TARGET)' f = targetdir.join('Makefile').open('w') print >> f, '# automatically generated Makefile' @@ -385,6 +383,8 @@ print >> f print >> f, 'TARGET =', py.path.local(compiler.outputfilename).basename print >> f + print >> f, 'DEFAULT_TARGET =', default_target + print >> f write_list(cfiles, 'SOURCES =') print >> f if self.config.translation.gcrootfinder == "asmgcc": @@ -830,6 +830,8 @@ MAKEFILE = ''' +all: $(DEFAULT_TARGET) + $(TARGET): $(OBJECTS) \t$(CC) $(LDFLAGS) $(TFLAGS) -o $@ $(OBJECTS) $(LIBDIRS) $(LIBS) @@ -849,32 +851,32 @@ \trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) *.gc?? debug: -\t$(MAKE) CFLAGS="-g -DRPY_ASSERT" +\t$(MAKE) CFLAGS="-g -DRPY_ASSERT" $(TARGET) debug_exc: -\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DDO_LOG_EXC" +\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DDO_LOG_EXC" $(TARGET) debug_mem: -\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DTRIVIAL_MALLOC_DEBUG" +\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DTRIVIAL_MALLOC_DEBUG" $(TARGET) no_obmalloc: -\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DNO_OBMALLOC" +\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DNO_OBMALLOC" $(TARGET) linuxmemchk: -\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DLINUXMEMCHK" +\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DLINUXMEMCHK" $(TARGET) llsafer: -\t$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" +\t$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(TARGET) lldebug: -\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DRPY_LL_ASSERT" +\t$(MAKE) CFLAGS="-g -DRPY_ASSERT -DRPY_LL_ASSERT" $(TARGET) profile: -\t$(MAKE) CFLAGS="-g -pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)" +\t$(MAKE) CFLAGS="-g -pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)" $(TARGET) profopt: -\t$(MAKE) CFLAGS="-fprofile-generate $(CFLAGS)" LDFLAGS="-fprofile-generate $(LDFLAGS)" +\t$(MAKE) CFLAGS="-fprofile-generate $(CFLAGS)" LDFLAGS="-fprofile-generate $(LDFLAGS)" $(TARGET) \tcd $(PYPYDIR)/translator/goal && $(abspath $(TARGET)) $(PROFOPT) \t$(MAKE) clean -\t$(MAKE) CFLAGS="-fprofile-use $(CFLAGS)" LDFLAGS="-fprofile-use $(LDFLAGS)" +\t$(MAKE) CFLAGS="-fprofile-use $(CFLAGS)" LDFLAGS="-fprofile-use $(LDFLAGS)" $(TARGET) ''' From arigo at codespeak.net Sun Apr 13 17:34:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 17:34:55 +0200 (CEST) Subject: [pypy-svn] r53741 - in pypy/dist/pypy: rpython/memory/gctransform translator/c translator/c/src Message-ID: <20080413153455.20AFB16A04F@codespeak.net> Author: arigo Date: Sun Apr 13 17:34:53 2008 New Revision: 53741 Modified: pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/src/mem.h Log: Remove old stuff. Modified: pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py Sun Apr 13 17:34:53 2008 @@ -28,15 +28,10 @@ return # mark the values as gc roots for var in livevars: - if 0: - # uses direct support in genc - more compact code, - # but it's probably not changing anything - hop.genop("asm_gcroot", [var]) - else: - v_adr = gen_cast(hop.llops, llmemory.Address, var) - v_newaddr = hop.genop("direct_call", [c_asm_gcroot, v_adr], - resulttype=llmemory.Address) - hop.genop("gc_reload_possibly_moved", [v_newaddr, var]) + v_adr = gen_cast(hop.llops, llmemory.Address, var) + v_newaddr = hop.genop("direct_call", [c_asm_gcroot, v_adr], + resulttype=llmemory.Address) + hop.genop("gc_reload_possibly_moved", [v_newaddr, var]) def build_root_walker(self): return AsmStackRootWalker(self) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sun Apr 13 17:34:53 2008 @@ -765,8 +765,4 @@ def OP_IS_EARLY_CONSTANT(self, op): return self.expr(op.result) + ' = 0;' # Allways false - def OP_ASM_GCROOT(self, op): - value = self.expr(op.args[0]) - return 'PYPY_GCROOT(%s);' % (value,) - assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/dist/pypy/translator/c/src/mem.h ============================================================================== --- pypy/dist/pypy/translator/c/src/mem.h (original) +++ pypy/dist/pypy/translator/c/src/mem.h Sun Apr 13 17:34:53 2008 @@ -21,7 +21,6 @@ extern char __gcmapend; extern char __gccallshapes; -#define PYPY_GCROOT(p) asm ("/* GCROOT %0 */" : "=g" (p) : "0" (p) : "memory") #define pypy_asm_gcroot(p) ({void*_r; \ asm ("/* GCROOT %0 */" : "=g" (_r) : "0" (p) : "memory"); \ _r; }) From arigo at codespeak.net Sun Apr 13 18:41:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Apr 2008 18:41:22 +0200 (CEST) Subject: [pypy-svn] r53743 - pypy/dist/pypy/translator/c/src Message-ID: <20080413164122.AE1F849812A@codespeak.net> Author: arigo Date: Sun Apr 13 18:41:22 2008 New Revision: 53743 Modified: pypy/dist/pypy/translator/c/src/mem.h Log: Hopefully fix the asm() instruction for GCROOT. Add some documentation about it. Modified: pypy/dist/pypy/translator/c/src/mem.h ============================================================================== --- pypy/dist/pypy/translator/c/src/mem.h (original) +++ pypy/dist/pypy/translator/c/src/mem.h Sun Apr 13 18:41:22 2008 @@ -20,9 +20,27 @@ extern char __gcmapstart; extern char __gcmapend; extern char __gccallshapes; +extern char __gcnoreorderhack; +/* The following pseudo-instruction is used by --gcrootfinder=asmgcc + just after a call to tell gcc to put a GCROOT mark on each gc-pointer + local variable. All such local variables need to go through a "v = + pypy_asm_gcroot(v)". The old value should not be used any more by + the C code; this prevents the following case from occurring: gcc + could make two copies of the local variable (e.g. one in the stack + and one in a register), pass one to GCROOT, and later use the other + one. In practice the pypy_asm_gcroot() is often a no-op in the final + machine code and doesn't prevent most optimizations. Getting the + asm() right was tricky, though. The asm() is not volatile so that + gcc is free to delete it if the output variable is not used at all. + We need to prevent gcc from moving the asm() *before* the call that + could cause a collection; this is the purpose of the (unused) + __gcnoreorderhack input argument. Any memory input argument would + have this effect: as far as gcc knows the call instruction can modify + arbitrary memory, thus creating the order dependency that we want. */ #define pypy_asm_gcroot(p) ({void*_r; \ - asm ("/* GCROOT %0 */" : "=g" (_r) : "0" (p) : "memory"); \ + asm ("/* GCROOT %0 */" : "=g" (_r) : \ + "0" (p), "m" (__gcnoreorderhack)); \ _r; }) #define OP_LLVM_GCMAPSTART(r) r = &__gcmapstart From arigo at codespeak.net Mon Apr 14 11:02:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 11:02:32 +0200 (CEST) Subject: [pypy-svn] r53752 - pypy/dist/pypy/rlib/test Message-ID: <20080414090232.F01F839B58F@codespeak.net> Author: arigo Date: Mon Apr 14 11:02:30 2008 New Revision: 53752 Modified: pypy/dist/pypy/rlib/test/test_rsocket.py Log: Fix test. Modified: pypy/dist/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rsocket.py (original) +++ pypy/dist/pypy/rlib/test/test_rsocket.py Mon Apr 14 11:02:30 2008 @@ -256,12 +256,12 @@ assert found, lst py.test.raises(GAIError, getaddrinfo, 'www.very-invalidaddress.com', None) -def test_getaddrinfo_snake(): - lst = getaddrinfo('snake.cs.uni-duesseldorf.de', None) +def test_getaddrinfo_codespeak(): + lst = getaddrinfo('codespeak.net', None) assert isinstance(lst, list) found = False for family, socktype, protocol, canonname, addr in lst: - if addr.get_host() == '134.99.112.214': + if addr.get_host() == '213.239.226.252': found = True assert found, lst From arigo at codespeak.net Mon Apr 14 15:16:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 15:16:45 +0200 (CEST) Subject: [pypy-svn] r53754 - in pypy/dist/pypy/rlib: . test Message-ID: <20080414131645.38319168558@codespeak.net> Author: arigo Date: Mon Apr 14 15:16:44 2008 New Revision: 53754 Added: pypy/dist/pypy/rlib/rStringIO.py (contents, props changed) pypy/dist/pypy/rlib/test/test_rStringIO.py (contents, props changed) Log: An RPython version of StringIO. The "fast path" through this code is for the case of a bunch of write() followed by getvalue(). Added: pypy/dist/pypy/rlib/rStringIO.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rStringIO.py Mon Apr 14 15:16:44 2008 @@ -0,0 +1,164 @@ + +PIECES = 80 +BIGPIECES = 32 + +AT_END = -1 + + +class RStringIO(object): + """RPython-level StringIO object. + The fastest path through this code is for the case of a bunch of write() + followed by getvalue(). For at most PIECES write()s and one getvalue(), + there is one copy of the data done, as if ''.join() was used. + """ + _mixin_ = True # for interp_stringio.py + + def __init__(self): + # The real content is the join of the following data: + # * the list of characters self.bigbuffer; + # * each of the strings in self.strings. + # + # Invariants: + # * self.numbigstrings <= self.numstrings; + # * all strings in self.strings[self.numstrings:PIECES] are empty. + # + self.strings = [''] * PIECES + self.numstrings = 0 + self.numbigstrings = 0 + self.bigbuffer = [] + self.pos = AT_END + + def getvalue(self): + """If self.strings contains more than 1 string, join all the + strings together. Return the final single string.""" + if len(self.bigbuffer) > 0: + self.copy_into_bigbuffer() + return ''.join(self.bigbuffer) + if self.numstrings > 1: + result = self.strings[0] = ''.join(self.strings) + self.numstrings = 1 + self.numbigstrings = 1 + else: + result = self.strings[0] + return result + + def getsize(self): + result = len(self.bigbuffer) + for i in range(0, self.numstrings): + result += len(self.strings[i]) + return result + + def copy_into_bigbuffer(self): + """Copy all the data into the list of characters self.bigbuffer.""" + for i in range(0, self.numstrings): + self.bigbuffer += self.strings[i] + self.strings[i] = '' + self.numstrings = 0 + self.numbigstrings = 0 + + def reduce(self): + """Reduce the number of (non-empty) strings in self.strings.""" + # When self.pos == AT_END, the calls to write(str) accumulate + # the strings in self.strings until all PIECES slots are filled. + # Then the reduce() method joins all the strings and put the + # result back into self.strings[0]. The next time all the slots + # are filled, we only join self.strings[1:] and put the result + # in self.strings[1]; and so on. The purpose of this is that + # the string resulting from a join is expected to be big, so the + # next join operation should only join the newly added strings. + # When we have done this BIGPIECES times, the next join collects + # all strings again into self.strings[0] and we start from + # scratch. + limit = self.numbigstrings + self.strings[limit] = ''.join(self.strings[limit:]) + for i in range(limit + 1, self.numstrings): + self.strings[i] = '' + self.numstrings = limit + 1 + if limit < BIGPIECES: + self.numbigstrings = limit + 1 + else: + self.numbigstrings = 0 + assert self.numstrings <= BIGPIECES + 1 + return self.numstrings + + def write(self, buffer): + # Idea: for the common case of a sequence of write() followed + # by only getvalue(), self.bigbuffer remains empty. It is only + # used to handle the more complicated cases. + p = self.pos + if p != AT_END: # slow or semi-fast paths + endp = p + len(buffer) + if len(self.bigbuffer) >= endp: + # semi-fast path: the write is entirely inside self.bigbuffer + for i in range(len(buffer)): + self.bigbuffer[p+i] = buffer[i] + self.pos = endp + return + else: + # slow path: collect all data into self.bigbuffer and + # handle the various cases + self.copy_into_bigbuffer() + fitting = len(self.bigbuffer) - p + if fitting > 0: + # the write starts before the end of the data + fitting = min(len(buffer), fitting) + for i in range(fitting): + self.bigbuffer[p+i] = buffer[i] + if len(buffer) > fitting: + # the write extends beyond the end of the data + self.bigbuffer += buffer[fitting:] + endp = AT_END + self.pos = endp + return + else: + # the write starts at or beyond the end of the data + self.bigbuffer += '\x00' * (-fitting) + self.pos = AT_END # fall-through to the fast path + # Fast path. + # See comments in reduce(). + count = self.numstrings + if count == PIECES: + count = self.reduce() + self.strings[count] = buffer + self.numstrings = count + 1 + + def seek(self, position, mode=0): + if mode == 1: + if self.pos == AT_END: + self.pos = self.getsize() + position += self.pos + elif mode == 2: + if position == 0: + self.pos = AT_END + return + position += self.getsize() + if position < 0: + position = 0 + self.pos = position + + def tell(self): + if self.pos == AT_END: + return self.getsize() + else: + return self.pos + + def read(self, n=-1): + p = self.pos + if p == 0 and n < 0: + self.pos = AT_END + return self.getvalue() # reading everything + if p == AT_END: + return '' + self.copy_into_bigbuffer() + mysize = len(self.bigbuffer) + count = mysize - p + if n >= 0: + count = min(n, count) + if count <= 0: + return '' + if p == 0 and count == mysize: + self.pos = AT_END + return ''.join(self.bigbuffer) + else: + self.pos = p + count + return ''.join(self.bigbuffer[p:p+count]) Added: pypy/dist/pypy/rlib/test/test_rStringIO.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/test/test_rStringIO.py Mon Apr 14 15:16:44 2008 @@ -0,0 +1,115 @@ +from pypy.rlib.rStringIO import RStringIO + + +def test_simple(): + f = RStringIO() + f.write('hello') + f.write(' world') + assert f.getvalue() == 'hello world' + +def test_write_many(): + f = RStringIO() + for j in range(10): + for i in range(253): + f.write(chr(i)) + expected = ''.join([chr(i) for j in range(10) for i in range(253)]) + assert f.getvalue() == expected + +def test_seek(): + f = RStringIO() + f.write('0123') + f.write('456') + f.write('789') + f.seek(4) + f.write('AB') + assert f.getvalue() == '0123AB6789' + f.seek(-2, 2) + f.write('CDE') + assert f.getvalue() == '0123AB67CDE' + f.seek(2, 0) + f.seek(5, 1) + f.write('F') + assert f.getvalue() == '0123AB6FCDE' + +def test_write_beyond_end(): + f = RStringIO() + f.seek(20, 1) + assert f.tell() == 20 + f.write('X') + assert f.getvalue() == '\x00' * 20 + 'X' + +def test_tell(): + f = RStringIO() + f.write('0123') + f.write('456') + assert f.tell() == 7 + f.seek(2) + for i in range(3, 20): + f.write('X') + assert f.tell() == i + assert f.getvalue() == '01XXXXXXXXXXXXXXXXX' + +def test_read(): + f = RStringIO() + assert f.read() == '' + f.write('0123') + f.write('456') + assert f.read() == '' + assert f.read(5) == '' + assert f.tell() == 7 + f.seek(1) + assert f.read() == '123456' + assert f.tell() == 7 + f.seek(1) + assert f.read(12) == '123456' + assert f.tell() == 7 + f.seek(1) + assert f.read(2) == '12' + assert f.read(1) == '3' + assert f.tell() == 4 + f.seek(0) + assert f.read() == '0123456' + assert f.tell() == 7 + f.seek(0) + assert f.read(7) == '0123456' + assert f.tell() == 7 + f.seek(15) + assert f.read(2) == '' + assert f.tell() == 15 + +def test_stress(): + import cStringIO, random + f = RStringIO() + expected = cStringIO.StringIO() + for i in range(2000): + r = random.random() + if r < 0.15: + p = random.randrange(-5000, 10000) + if r < 0.05: + mode = 0 + elif r < 0.1: + mode = 1 + else: + mode = 2 + print 'seek', p, mode + f.seek(p, mode) + expected.seek(p, mode) + elif r < 0.6: + buf = str(random.random()) + print 'write %d bytes' % len(buf) + f.write(buf) + expected.write(buf) + elif r < 0.92: + n = random.randrange(0, 100) + print 'read %d bytes' % n + data1 = f.read(n) + data2 = expected.read(n) + assert data1 == data2 + elif r < 0.97: + print 'check tell()' + assert f.tell() == expected.tell() + else: + print 'check getvalue()' + assert f.getvalue() == expected.getvalue() + assert f.getvalue() == expected.getvalue() + assert f.tell() == expected.tell() From arigo at codespeak.net Mon Apr 14 15:32:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 15:32:19 +0200 (CEST) Subject: [pypy-svn] r53755 - in pypy/dist/pypy: doc/config module/cStringIO module/cStringIO/test rlib Message-ID: <20080414133219.600D216855F@codespeak.net> Author: arigo Date: Mon Apr 14 15:32:17 2008 New Revision: 53755 Added: pypy/dist/pypy/doc/config/objspace.usemodules.cStringIO.txt (contents, props changed) pypy/dist/pypy/module/cStringIO/ (props changed) pypy/dist/pypy/module/cStringIO/__init__.py (contents, props changed) pypy/dist/pypy/module/cStringIO/interp_stringio.py (contents, props changed) pypy/dist/pypy/module/cStringIO/test/ (props changed) pypy/dist/pypy/module/cStringIO/test/__init__.py (contents, props changed) pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py (contents, props changed) Modified: pypy/dist/pypy/rlib/rStringIO.py Log: Starting an interp-level cStringIO module. Motivation: the mako benchmark spends about 3 times longer in cStringIO (which is really StringIO) than it does on CPython. Added: pypy/dist/pypy/doc/config/objspace.usemodules.cStringIO.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/objspace.usemodules.cStringIO.txt Mon Apr 14 15:32:17 2008 @@ -0,0 +1,4 @@ +Use the built-in cStringIO module. + +If not enabled, importing cStringIO gives you the app-level +implementation from the standard library StringIO module. Added: pypy/dist/pypy/module/cStringIO/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/cStringIO/__init__.py Mon Apr 14 15:32:17 2008 @@ -0,0 +1,13 @@ + +# Package initialisation +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + appleveldefs = { + } + + interpleveldefs = { + 'StringIO': 'interp_stringio.StringIO', + #'InputType': 'interp_stringio.W_InputType', + 'OutputType': 'interp_stringio.W_OutputType', + } Added: pypy/dist/pypy/module/cStringIO/interp_stringio.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/cStringIO/interp_stringio.py Mon Apr 14 15:32:17 2008 @@ -0,0 +1,87 @@ +from pypy.interpreter.error import OperationError +from pypy.interpreter.baseobjspace import Wrappable +from pypy.interpreter.typedef import TypeDef, GetSetProperty +from pypy.interpreter.gateway import interp2app +from pypy.rlib.rStringIO import RStringIO + + +PIECES = 80 +BIGPIECES = 32 + + +class W_OutputType(Wrappable, RStringIO): + def __init__(self, space): + RStringIO.__init__(self) + self.space = space + self.softspace = 0 # part of the file object API + + def descr_close(self): + self.close() + descr_close.unwrap_spec = ['self'] + + def check_closed(self): + if self.is_closed(): + space = self.space + raise OperationError(space.w_ValueError, + space.wrap("I/O operation on closed file")) + + def descr_getvalue(self): + self.check_closed() + return self.space.wrap(self.getvalue()) + descr_getvalue.unwrap_spec = ['self'] + + def descr_read(self, n=-1): + self.check_closed() + return self.space.wrap(self.read(n)) + descr_read.unwrap_spec = ['self', int] + + def descr_reset(self): + self.check_closed() + self.seek(0) + descr_reset.unwrap_spec = ['self'] + + def descr_seek(self, position, mode=0): + self.check_closed() + self.seek(position, mode) + descr_seek.unwrap_spec = ['self', int, int] + + def descr_tell(self): + self.check_closed() + return self.space.wrap(self.tell()) + descr_tell.unwrap_spec = ['self'] + + def descr_write(self, buffer): + self.check_closed() + self.write(buffer) + descr_write.unwrap_spec = ['self', 'bufferstr'] + +# ____________________________________________________________ + +def descr_closed(space, self): + return space.wrap(self.strings is None) + +def descr_softspace(space, self): + return space.wrap(self.softspace) + +def descr_setsoftspace(space, self, w_newvalue): + self.softspace = space.int_w(w_newvalue) + +W_OutputType.typedef = TypeDef( + "cStringIO.StringO", + close = interp2app(W_OutputType.descr_close), + closed = GetSetProperty(descr_closed, cls=W_OutputType), + getvalue = interp2app(W_OutputType.descr_getvalue), + read = interp2app(W_OutputType.descr_read), + reset = interp2app(W_OutputType.descr_reset), + seek = interp2app(W_OutputType.descr_seek), + softspace = GetSetProperty(descr_softspace, + descr_setsoftspace, + cls=W_OutputType), + tell = interp2app(W_OutputType.descr_tell), + write = interp2app(W_OutputType.descr_write), + ) + +# ____________________________________________________________ + +def StringIO(space): + return space.wrap(W_OutputType(space)) Added: pypy/dist/pypy/module/cStringIO/test/__init__.py ============================================================================== Added: pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py Mon Apr 14 15:32:17 2008 @@ -0,0 +1,113 @@ + +from pypy.conftest import gettestobjspace + +import os, sys, py + + +class AppTestcStringIO: + def setup_class(cls): + space = gettestobjspace(usemodules=('cStringIO',)) + cls.space = space + cls.w_write_many_expected_result = space.wrap(''.join( + [chr(i) for j in range(10) for i in range(253)])) + cls.w_StringIO = space.appexec([], """(): + import cStringIO + return cStringIO.StringIO + """) + + def test_simple(self): + f = self.StringIO() + f.write('hello') + f.write(' world') + assert f.getvalue() == 'hello world' + + def test_write_many(self): + f = self.StringIO() + for j in range(10): + for i in range(253): + f.write(chr(i)) + expected = ''.join([chr(i) for j in range(10) for i in range(253)]) + assert f.getvalue() == expected + + def test_seek(self): + f = self.StringIO() + f.write('0123') + f.write('456') + f.write('789') + f.seek(4) + f.write('AB') + assert f.getvalue() == '0123AB6789' + f.seek(-2, 2) + f.write('CDE') + assert f.getvalue() == '0123AB67CDE' + f.seek(2, 0) + f.seek(5, 1) + f.write('F') + assert f.getvalue() == '0123AB6FCDE' + + def test_write_beyond_end(self): + f = self.StringIO() + f.seek(20, 1) + assert f.tell() == 20 + f.write('X') + assert f.getvalue() == '\x00' * 20 + 'X' + + def test_tell(self): + f = self.StringIO() + f.write('0123') + f.write('456') + assert f.tell() == 7 + f.seek(2) + for i in range(3, 20): + f.write('X') + assert f.tell() == i + assert f.getvalue() == '01XXXXXXXXXXXXXXXXX' + + def test_read(self): + f = self.StringIO() + assert f.read() == '' + f.write('0123') + f.write('456') + assert f.read() == '' + assert f.read(5) == '' + assert f.tell() == 7 + f.seek(1) + assert f.read() == '123456' + assert f.tell() == 7 + f.seek(1) + assert f.read(12) == '123456' + assert f.tell() == 7 + f.seek(1) + assert f.read(2) == '12' + assert f.read(1) == '3' + assert f.tell() == 4 + f.seek(0) + assert f.read() == '0123456' + assert f.tell() == 7 + f.seek(0) + assert f.read(7) == '0123456' + assert f.tell() == 7 + f.seek(15) + assert f.read(2) == '' + assert f.tell() == 15 + + def test_reset(self): + from cStringIO import StringIO + f = StringIO() + f.write('foobar') + f.reset() + res = f.read() + assert res == 'foobar' + + def test_close(self): + from cStringIO import StringIO + f = StringIO() + assert not f.closed + f.close() + raises(ValueError, f.write, 'hello') + raises(ValueError, f.getvalue) + raises(ValueError, f.read, 0) + raises(ValueError, f.seek, 0) + assert f.closed + f.close() + assert f.closed Modified: pypy/dist/pypy/rlib/rStringIO.py ============================================================================== --- pypy/dist/pypy/rlib/rStringIO.py (original) +++ pypy/dist/pypy/rlib/rStringIO.py Mon Apr 14 15:32:17 2008 @@ -28,6 +28,15 @@ self.bigbuffer = [] self.pos = AT_END + def close(self): + self.strings = None + self.numstrings = 0 + self.numbigstrings = 0 + self.bigbuffer = None + + def is_closed(self): + return self.strings is None + def getvalue(self): """If self.strings contains more than 1 string, join all the strings together. Return the final single string.""" From fijal at codespeak.net Mon Apr 14 16:03:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Apr 2008 16:03:24 +0200 (CEST) Subject: [pypy-svn] r53756 - in pypy/branch/io-improvements/pypy/rpython/memory: gctransform test Message-ID: <20080414140324.02D3D168549@codespeak.net> Author: fijal Date: Mon Apr 14 16:03:24 2008 New Revision: 53756 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: * remove coalloc * add rgc.malloc_nonmoving operation Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py Mon Apr 14 16:03:24 2008 @@ -295,20 +295,6 @@ inline=True) else: self.write_barrier_ptr = None - if hasattr(GCClass, "coalloc_fixedsize_clear"): - self.coalloc_clear_ptr = getfn( - GCClass.coalloc_fixedsize_clear.im_func, - [s_gc, annmodel.SomeAddress(), - annmodel.SomeInteger(nonneg=True), - annmodel.SomeInteger(nonneg=True)], - s_gcref, inline=True) - self.coalloc_varsize_clear_ptr = getfn( - GCClass.coalloc_varsize_clear.im_func, - [s_gc, annmodel.SomeAddress()] + - [annmodel.SomeInteger(nonneg=True) for i in range(5)], - s_gcref, inline=True) - else: - self.coalloc_clear_ptr = self.coalloc_varsize_clear_ptr = None self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], annmodel.SomeInteger()) @@ -489,43 +475,6 @@ gct_fv_gc_malloc_varsize = gct_fv_gc_malloc - def gct_fv_gc_coalloc(self, hop, coallocator, flags, TYPE, *args): - if self.coalloc_clear_ptr is None: - return self.gct_fv_gc_malloc( - hop, flags, TYPE, *args) - op = hop.spaceop - flavor = flags['flavor'] - assert not flags.get("nocollect", False) - - PTRTYPE = op.result.concretetype - assert PTRTYPE.TO == TYPE - type_id = self.get_type_id(TYPE) - - c_type_id = rmodel.inputconst(lltype.Signed, type_id) - info = self.layoutbuilder.type_info_list[type_id] - c_size = rmodel.inputconst(lltype.Signed, info.fixedsize) - has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) - assert not has_finalizer - - v_coallocator = gen_cast(hop.llops, llmemory.Address, coallocator) - - if not op.opname.endswith('_varsize'): - malloc_ptr = self.coalloc_clear_ptr - args = [self.c_const_gc, v_coallocator, c_type_id, c_size] - else: - v_length = op.args[-1] - c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) - c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - malloc_ptr = self.coalloc_varsize_clear_ptr - args = [self.c_const_gc, v_coallocator, c_type_id, v_length, c_size, - c_varitemsize, c_ofstolength] - livevars = self.push_roots(hop) - v_result = hop.genop("direct_call", [malloc_ptr] + args, - resulttype=llmemory.GCREF) - self.pop_roots(hop, livevars) - return v_result - gct_fv_gc_coalloc_varsize = gct_fv_gc_coalloc - def gct_gc__collect(self, hop): op = hop.spaceop livevars = self.push_roots(hop) @@ -642,6 +591,22 @@ self.c_const_gc, v_size]) + def gct_malloc_nonmovable_varsize(self, hop): + TYPE = hop.spaceop.result.concretetype + if self.gcdata.gc.moving_gc: + # first approximation + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) + return self.gct_malloc_varsize(hop) + + def gct_malloc_nonmovable(self, hop): + TYPE = hop.spaceop.result.concretetype + if self.gcdata.gc.moving_gc: + # first approximation + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) + return self.gct_malloc(hop) + def transform_generic_set(self, hop): from pypy.objspace.flow.model import Constant opname = hop.spaceop.opname Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Mon Apr 14 16:03:24 2008 @@ -491,27 +491,14 @@ assert not TYPE._is_varsize() flags = hop.spaceop.args[1].value flavor = flags['flavor'] + if flavor == 'nonmovable': + flavor = 'gc' meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) v_raw = meth(hop, flags, TYPE, c_size) hop.cast_result(v_raw) - def gct_coalloc(self, hop): - TYPE = hop.spaceop.result.concretetype.TO - assert not TYPE._is_varsize() - flags = hop.spaceop.args[2].value - flavor = flags['flavor'] - c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) - meth = getattr(self, 'gct_fv_%s_comalloc' % flavor, None) - if meth is None: - meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) - assert meth, "%s has no support for comalloc with flavor %r" % (self, flavor) - v_raw = meth(hop, flags, TYPE, c_size) - else: - v_raw = meth(hop, hop.spaceop.args[1], flags, TYPE, c_size) - hop.cast_result(v_raw) - def gct_fv_raw_malloc(self, hop, flags, TYPE, c_size): v_raw = hop.genop("direct_call", [self.raw_malloc_fixedsize_ptr, c_size], resulttype=llmemory.Address) @@ -524,9 +511,11 @@ resulttype=llmemory.Address) if flags.get('zero'): hop.genop("raw_memclear", [v_raw, c_size]) - return v_raw + return v_raw def gct_malloc_varsize(self, hop): + op = hop.spaceop + TYPE = op.result.concretetype.TO flags = hop.spaceop.args[1].value flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" @@ -534,19 +523,8 @@ assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) - def gct_coalloc_varsize(self, hop): - - flags = hop.spaceop.args[2].value - flavor = flags['flavor'] - meth = getattr(self, 'gct_fv_%s_coalloc_varsize' % flavor, None) - if meth is None: - meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) - assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) - return self.varsize_malloc_helper(hop, flags, meth, []) - else: - return self.varsize_malloc_helper(hop, flags, meth, - [hop.spaceop.args[1]]) - + gct_malloc_nonmovable = gct_malloc + gct_malloc_nonmovable_varsize = gct_malloc_varsize def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Mon Apr 14 16:03:24 2008 @@ -457,9 +457,61 @@ res = run([]) assert res == self.GC_CAN_MOVE + def _test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + # this test would have different outcome for different + # gcs, please assert differently + run = self.runner(func) + return run([]) + + def _test_malloc_nonmovable_fixsize(self): + TP = lltype.GcStruct('T', ('x', lltype.Float)) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP) + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + # this test would have different outcome for different + # gcs, please assert differently + run = self.runner(func) + return run([]) + + def test_malloc_nonmovable(self): + res = self._test_malloc_nonmovable() + if self.GC_CAN_MOVE: + expected = 1 + else: + expected = 0 + assert res == expected + + def test_malloc_nonmovable_fixsize(self): + res = self._test_malloc_nonmovable_fixsize() + if self.GC_CAN_MOVE: + expected = 1 + else: + expected = 0 + assert res == expected + class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True - + def test_many_ids(self): py.test.skip("fails for bad reasons in lltype.py :-(") class A(object): From fijal at codespeak.net Mon Apr 14 16:03:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Apr 2008 16:03:42 +0200 (CEST) Subject: [pypy-svn] r53757 - pypy/branch/io-improvements/pypy/rpython/module Message-ID: <20080414140342.7AD3016854E@codespeak.net> Author: fijal Date: Mon Apr 14 16:03:41 2008 New Revision: 53757 Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: speed up os.read (ugly impl by now) Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Mon Apr 14 16:03:41 2008 @@ -25,6 +25,8 @@ itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import llstr +from pypy.rlib import rgc +from pypy.rlib.objectmodel import keepalive_until_here posix = __import__(os.name) @@ -485,19 +487,37 @@ def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) - inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') - try: - got = rffi.cast(lltype.Signed, os_read(fd, inbuf, count)) - if got < 0: - raise OSError(rposix.get_errno(), "os_read failed") - s = mallocstr(got) - source = cast_ptr_to_adr(inbuf) + \ - itemoffsetof(lltype.typeOf(inbuf).TO, 0) - dest = cast_ptr_to_adr(s) + offset - raw_memcopy(source, dest, sizeof(lltype.Char) * got) - finally: - lltype.free(inbuf, flavor='raw') - return hlstr(s) + inbuf = rgc.malloc_nonmovable(STR, count) + if inbuf: + try: + realbuf = cast_ptr_to_adr(inbuf) + offset + c_buf = rffi.cast(rffi.VOIDP, realbuf) + got = rffi.cast(lltype.Signed, os_read(fd, c_buf, count)) + if got < 0: + raise OSError(rposix.get_errno(), "os_read failed") + if got != count: + # we need to realloc + s = mallocstr(got) + dest = cast_ptr_to_adr(s) + offset + raw_memcopy(realbuf, dest, sizeof(lltype.Char) * got) + return hlstr(s) + return hlstr(inbuf) + finally: + keepalive_until_here(inbuf) + else: + inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') + try: + got = rffi.cast(lltype.Signed, os_read(fd, inbuf, count)) + if got < 0: + raise OSError(rposix.get_errno(), "os_read failed") + s = mallocstr(got) + source = cast_ptr_to_adr(inbuf) + \ + itemoffsetof(lltype.typeOf(inbuf).TO, 0) + dest = cast_ptr_to_adr(s) + offset + raw_memcopy(source, dest, sizeof(lltype.Char) * got) + finally: + lltype.free(inbuf, flavor='raw') + return hlstr(s) def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) From arigo at codespeak.net Mon Apr 14 16:07:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 16:07:14 +0200 (CEST) Subject: [pypy-svn] r53758 - in pypy/dist/pypy: module/cStringIO module/cStringIO/test rlib rlib/test Message-ID: <20080414140714.0961116854B@codespeak.net> Author: arigo Date: Mon Apr 14 16:07:14 2008 New Revision: 53758 Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py pypy/dist/pypy/rlib/rStringIO.py pypy/dist/pypy/rlib/test/test_rStringIO.py Log: Roughly finished the methods of StringO. Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/interp_stringio.py Mon Apr 14 16:07:14 2008 @@ -1,7 +1,8 @@ +import sys from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.typedef import TypeDef, GetSetProperty -from pypy.interpreter.gateway import interp2app +from pypy.interpreter.gateway import interp2app, W_Root from pypy.rlib.rStringIO import RStringIO @@ -15,6 +16,11 @@ self.space = space self.softspace = 0 # part of the file object API + def descr___iter__(self): + self.check_closed() + return self + descr___iter__.unwrap_spec = ['self'] + def descr_close(self): self.close() descr_close.unwrap_spec = ['self'] @@ -25,16 +31,69 @@ raise OperationError(space.w_ValueError, space.wrap("I/O operation on closed file")) + def descr_flush(self): + self.check_closed() + descr_flush.unwrap_spec = ['self'] + def descr_getvalue(self): self.check_closed() return self.space.wrap(self.getvalue()) descr_getvalue.unwrap_spec = ['self'] + def descr_isatty(self): + self.check_closed() + return self.space.w_False + descr_isatty.unwrap_spec = ['self'] + + def descr_next(self): + space = self.space + self.check_closed() + line = self.readline() + if len(line) == 0: + raise OperationError(space.w_StopIteration, space.w_None) + return space.wrap(line) + def descr_read(self, n=-1): self.check_closed() return self.space.wrap(self.read(n)) descr_read.unwrap_spec = ['self', int] + def readline(self, size=-1): + p = self.tell() + bigbuffer = self.copy_into_bigbuffer() + end = len(bigbuffer) + if size >= 0: + end = min(end, p + size) + assert p >= 0 + i = p + while i < end: + finished = bigbuffer[i] == '\n' + i += 1 + if finished: + break + self.seek(i) + return ''.join(bigbuffer[p:i]) + + def descr_readline(self, size=-1): + self.check_closed() + return self.space.wrap(self.readline(size)) + descr_readline.unwrap_spec = ['self', int] + + def descr_readlines(self, size=0): + self.check_closed() + lines_w = [] + while True: + line = self.readline() + if len(line) == 0: + break + lines_w.append(self.space.wrap(line)) + if size > 0: + size -= len(line) + if size <= 0: + break + return self.space.newlist(lines_w) + descr_readlines.unwrap_spec = ['self', int] + def descr_reset(self): self.check_closed() self.seek(0) @@ -50,11 +109,36 @@ return self.space.wrap(self.tell()) descr_tell.unwrap_spec = ['self'] + def descr_truncate(self, w_size=None): # note: a wrapped size! + self.check_closed() + space = self.space + if w_size is None or space.is_w(w_size, space.w_None): + size = self.tell() + else: + size = space.int_w(w_size) + if size < 0: + raise OperationError(space.w_IOError, space.wrap("negative size")) + self.truncate(size) + descr_truncate.unwrap_spec = ['self', W_Root] + def descr_write(self, buffer): self.check_closed() self.write(buffer) descr_write.unwrap_spec = ['self', 'bufferstr'] + def descr_writelines(self, w_lines): + space = self.space + w_iterator = space.iter(w_lines) + while True: + try: + w_line = space.next(w_iterator) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break # done + self.write(space.str_w(w_line)) + descr_writelines.unwrap_spec = ['self', W_Root] + # ____________________________________________________________ def descr_closed(space, self): @@ -68,17 +152,26 @@ W_OutputType.typedef = TypeDef( "cStringIO.StringO", + __doc__ = "Simple type for output to strings.", + __iter__ = interp2app(W_OutputType.descr___iter__), close = interp2app(W_OutputType.descr_close), closed = GetSetProperty(descr_closed, cls=W_OutputType), + flush = interp2app(W_OutputType.descr_flush), getvalue = interp2app(W_OutputType.descr_getvalue), + isatty = interp2app(W_OutputType.descr_isatty), + next = interp2app(W_OutputType.descr_next), read = interp2app(W_OutputType.descr_read), + readline = interp2app(W_OutputType.descr_readline), + readlines = interp2app(W_OutputType.descr_readlines), reset = interp2app(W_OutputType.descr_reset), seek = interp2app(W_OutputType.descr_seek), softspace = GetSetProperty(descr_softspace, descr_setsoftspace, cls=W_OutputType), tell = interp2app(W_OutputType.descr_tell), + truncate = interp2app(W_OutputType.descr_truncate), write = interp2app(W_OutputType.descr_write), + writelines = interp2app(W_OutputType.descr_writelines), ) # ____________________________________________________________ Modified: pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py Mon Apr 14 16:07:14 2008 @@ -92,16 +92,14 @@ assert f.tell() == 15 def test_reset(self): - from cStringIO import StringIO - f = StringIO() + f = self.StringIO() f.write('foobar') f.reset() res = f.read() assert res == 'foobar' def test_close(self): - from cStringIO import StringIO - f = StringIO() + f = self.StringIO() assert not f.closed f.close() raises(ValueError, f.write, 'hello') @@ -111,3 +109,52 @@ assert f.closed f.close() assert f.closed + + def test_readline(self): + f = self.StringIO() + f.write('foo\nbar\nbaz') + f.seek(0) + assert f.readline() == 'foo\n' + assert f.readline(2) == 'ba' + assert f.readline() == 'r\n' + assert f.readline() == 'baz' + assert f.readline() == '' + f.seek(0) + assert iter(f) is f + assert list(f) == ['foo\n', 'bar\n', 'baz'] + f.write('\n') + f.seek(0) + assert iter(f) is f + assert list(f) == ['foo\n', 'bar\n', 'baz\n'] + f.seek(0) + assert f.readlines() == ['foo\n', 'bar\n', 'baz\n'] + f.seek(0) + assert f.readlines(2) == ['foo\n'] + + def test_misc(self): + f = self.StringIO() + f.flush() + assert f.isatty() is False + + def test_truncate(self): + f = self.StringIO() + f.truncate(20) + assert f.getvalue() == '\x00' * 20 + assert f.tell() == 0 + f.seek(0, 2) + f.write('hello') + f.write(' world') + f.truncate(30) + assert f.getvalue() == '\x00' * 20 + 'hello worl' + f.truncate(25) + assert f.getvalue() == '\x00' * 20 + 'hello' + f.write('baz') + f.write('egg') + f.truncate(3) + assert f.getvalue() == '\x00' * 3 + raises(IOError, f.truncate, -1) + + def test_writelines(self): + f = self.StringIO() + f.writelines(['foo', 'bar', 'baz']) + assert f.getvalue() == 'foobarbaz' Modified: pypy/dist/pypy/rlib/rStringIO.py ============================================================================== --- pypy/dist/pypy/rlib/rStringIO.py (original) +++ pypy/dist/pypy/rlib/rStringIO.py Mon Apr 14 16:07:14 2008 @@ -64,6 +64,7 @@ self.strings[i] = '' self.numstrings = 0 self.numbigstrings = 0 + return self.bigbuffer def reduce(self): """Reduce the number of (non-empty) strings in self.strings.""" @@ -106,22 +107,22 @@ else: # slow path: collect all data into self.bigbuffer and # handle the various cases - self.copy_into_bigbuffer() - fitting = len(self.bigbuffer) - p + bigbuffer = self.copy_into_bigbuffer() + fitting = len(bigbuffer) - p if fitting > 0: # the write starts before the end of the data fitting = min(len(buffer), fitting) for i in range(fitting): - self.bigbuffer[p+i] = buffer[i] + bigbuffer[p+i] = buffer[i] if len(buffer) > fitting: # the write extends beyond the end of the data - self.bigbuffer += buffer[fitting:] + bigbuffer += buffer[fitting:] endp = AT_END self.pos = endp return else: # the write starts at or beyond the end of the data - self.bigbuffer += '\x00' * (-fitting) + bigbuffer += '\x00' * (-fitting) self.pos = AT_END # fall-through to the fast path # Fast path. # See comments in reduce(). @@ -158,8 +159,8 @@ return self.getvalue() # reading everything if p == AT_END: return '' - self.copy_into_bigbuffer() - mysize = len(self.bigbuffer) + bigbuffer = self.copy_into_bigbuffer() + mysize = len(bigbuffer) count = mysize - p if n >= 0: count = min(n, count) @@ -167,7 +168,23 @@ return '' if p == 0 and count == mysize: self.pos = AT_END - return ''.join(self.bigbuffer) + return ''.join(bigbuffer) else: self.pos = p + count - return ''.join(self.bigbuffer[p:p+count]) + return ''.join(bigbuffer[p:p+count]) + + def truncate(self, size): + assert size >= 0 + self.pos = self.tell() # in case it was AT_END + if size > len(self.bigbuffer): + self.copy_into_bigbuffer() + else: + # we can drop all extra strings + for i in range(0, self.numstrings): + self.strings[i] = '' + self.numstrings = 0 + self.numbigstrings = 0 + if size <= len(self.bigbuffer): + del self.bigbuffer[size:] + else: + self.bigbuffer += '\x00' * (size - len(self.bigbuffer)) Modified: pypy/dist/pypy/rlib/test/test_rStringIO.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rStringIO.py (original) +++ pypy/dist/pypy/rlib/test/test_rStringIO.py Mon Apr 14 16:07:14 2008 @@ -77,6 +77,23 @@ assert f.read(2) == '' assert f.tell() == 15 +def test_truncate(): + f = RStringIO() + f.truncate(20) + assert f.getvalue() == '\x00' * 20 + assert f.tell() == 0 + f.seek(0, 2) + f.write('hello') + f.write(' world') + f.truncate(30) + assert f.getvalue() == '\x00' * 20 + 'hello worl' + f.truncate(25) + assert f.getvalue() == '\x00' * 20 + 'hello' + f.write('baz') + f.write('egg') + f.truncate(3) + assert f.getvalue() == '\x00' * 3 + def test_stress(): import cStringIO, random f = RStringIO() From arigo at codespeak.net Mon Apr 14 16:34:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 16:34:19 +0200 (CEST) Subject: [pypy-svn] r53759 - in pypy/dist/pypy/module/cStringIO: . test Message-ID: <20080414143419.A18F42A00E2@codespeak.net> Author: arigo Date: Mon Apr 14 16:34:17 2008 New Revision: 53759 Modified: pypy/dist/pypy/module/cStringIO/__init__.py pypy/dist/pypy/module/cStringIO/interp_stringio.py pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py Log: The StringI type. Modified: pypy/dist/pypy/module/cStringIO/__init__.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/__init__.py (original) +++ pypy/dist/pypy/module/cStringIO/__init__.py Mon Apr 14 16:34:17 2008 @@ -8,6 +8,6 @@ interpleveldefs = { 'StringIO': 'interp_stringio.StringIO', - #'InputType': 'interp_stringio.W_InputType', + 'InputType': 'interp_stringio.W_InputType', 'OutputType': 'interp_stringio.W_OutputType', } Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/interp_stringio.py Mon Apr 14 16:34:17 2008 @@ -2,19 +2,12 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.typedef import TypeDef, GetSetProperty -from pypy.interpreter.gateway import interp2app, W_Root +from pypy.interpreter.gateway import interp2app, W_Root, ObjSpace from pypy.rlib.rStringIO import RStringIO -PIECES = 80 -BIGPIECES = 32 - - -class W_OutputType(Wrappable, RStringIO): - def __init__(self, space): - RStringIO.__init__(self) - self.space = space - self.softspace = 0 # part of the file object API +class W_InputOutputType(Wrappable): + softspace = 0 # part of the file object API def descr___iter__(self): self.check_closed() @@ -58,22 +51,6 @@ return self.space.wrap(self.read(n)) descr_read.unwrap_spec = ['self', int] - def readline(self, size=-1): - p = self.tell() - bigbuffer = self.copy_into_bigbuffer() - end = len(bigbuffer) - if size >= 0: - end = min(end, p + size) - assert p >= 0 - i = p - while i < end: - finished = bigbuffer[i] == '\n' - i += 1 - if finished: - break - self.seek(i) - return ''.join(bigbuffer[p:i]) - def descr_readline(self, size=-1): self.check_closed() return self.space.wrap(self.readline(size)) @@ -109,6 +86,82 @@ return self.space.wrap(self.tell()) descr_tell.unwrap_spec = ['self'] +# ____________________________________________________________ + +class W_InputType(W_InputOutputType): + def __init__(self, space, string): + self.space = space + self.string = string + self.pos = 0 + + def close(self): + self.string = None + + def is_closed(self): + return self.string is None + + def getvalue(self): + return self.string + + def read(self, n=-1): + p = self.pos + count = len(self.string) - p + if n >= 0: + count = min(n, count) + self.pos = p + count + if count == len(self.string): + return self.string + else: + return self.string[p:p+count] + + def readline(self, size=-1): + p = self.pos + end = len(self.string) + if size >= 0 and size < end - p: + end = p + size + lastp = self.string.find('\n', p, end) + if lastp < 0: + endp = end + else: + endp = lastp + 1 + self.pos = endp + return self.string[p:endp] + + def seek(self, position, mode=0): + if mode == 1: + position += self.pos + elif mode == 2: + position += len(self.string) + if position < 0: + position = 0 + self.pos = position + + def tell(self): + return self.pos + +# ____________________________________________________________ + +class W_OutputType(W_InputOutputType, RStringIO): + def __init__(self, space): + RStringIO.__init__(self) + self.space = space + + def readline(self, size=-1): + p = self.tell() + bigbuffer = self.copy_into_bigbuffer() + end = len(bigbuffer) + if size >= 0 and size < end - p: + end = p + size + assert p >= 0 + i = p + while i < end: + finished = bigbuffer[i] == '\n' + i += 1 + if finished: + break + self.seek(i) + return ''.join(bigbuffer[p:i]) + def descr_truncate(self, w_size=None): # note: a wrapped size! self.check_closed() space = self.space @@ -127,6 +180,7 @@ descr_write.unwrap_spec = ['self', 'bufferstr'] def descr_writelines(self, w_lines): + self.check_closed() space = self.space w_iterator = space.iter(w_lines) while True: @@ -142,7 +196,7 @@ # ____________________________________________________________ def descr_closed(space, self): - return space.wrap(self.strings is None) + return space.wrap(self.is_closed()) def descr_softspace(space, self): return space.wrap(self.softspace) @@ -150,31 +204,46 @@ def descr_setsoftspace(space, self, w_newvalue): self.softspace = space.int_w(w_newvalue) +common_descrs = { + '__iter__': interp2app(W_InputOutputType.descr___iter__), + 'close': interp2app(W_InputOutputType.descr_close), + 'closed': GetSetProperty(descr_closed, cls=W_InputOutputType), + 'flush': interp2app(W_InputOutputType.descr_flush), + 'getvalue': interp2app(W_InputOutputType.descr_getvalue), + 'isatty': interp2app(W_InputOutputType.descr_isatty), + 'next': interp2app(W_InputOutputType.descr_next), + 'read': interp2app(W_InputOutputType.descr_read), + 'readline': interp2app(W_InputOutputType.descr_readline), + 'readlines': interp2app(W_InputOutputType.descr_readlines), + 'reset': interp2app(W_InputOutputType.descr_reset), + 'seek': interp2app(W_InputOutputType.descr_seek), + 'softspace': GetSetProperty(descr_softspace, + descr_setsoftspace, + cls=W_InputOutputType), + 'tell': interp2app(W_InputOutputType.descr_tell), +} + +W_InputType.typedef = TypeDef( + "cStringIO.StringI", + __doc__ = "Simple type for treating strings as input file streams", + **common_descrs + ) + W_OutputType.typedef = TypeDef( "cStringIO.StringO", __doc__ = "Simple type for output to strings.", - __iter__ = interp2app(W_OutputType.descr___iter__), - close = interp2app(W_OutputType.descr_close), - closed = GetSetProperty(descr_closed, cls=W_OutputType), - flush = interp2app(W_OutputType.descr_flush), - getvalue = interp2app(W_OutputType.descr_getvalue), - isatty = interp2app(W_OutputType.descr_isatty), - next = interp2app(W_OutputType.descr_next), - read = interp2app(W_OutputType.descr_read), - readline = interp2app(W_OutputType.descr_readline), - readlines = interp2app(W_OutputType.descr_readlines), - reset = interp2app(W_OutputType.descr_reset), - seek = interp2app(W_OutputType.descr_seek), - softspace = GetSetProperty(descr_softspace, - descr_setsoftspace, - cls=W_OutputType), - tell = interp2app(W_OutputType.descr_tell), truncate = interp2app(W_OutputType.descr_truncate), write = interp2app(W_OutputType.descr_write), writelines = interp2app(W_OutputType.descr_writelines), + **common_descrs ) # ____________________________________________________________ -def StringIO(space): - return space.wrap(W_OutputType(space)) +def StringIO(space, w_string=None): + if space.is_w(w_string, space.w_None): + return space.wrap(W_OutputType(space)) + else: + string = space.bufferstr_w(w_string) + return space.wrap(W_InputType(space, string)) +StringIO.unwrap_spec = [ObjSpace, W_Root] Modified: pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py Mon Apr 14 16:34:17 2008 @@ -158,3 +158,49 @@ f = self.StringIO() f.writelines(['foo', 'bar', 'baz']) assert f.getvalue() == 'foobarbaz' + + def test_stringi(self): + f = self.StringIO('hello world\nspam\n') + assert not hasattr(f, 'write') # it's a StringI + f.seek(3) + assert f.tell() == 3 + f.seek(50, 1) + assert f.tell() == 53 + f.seek(-3, 2) + assert f.tell() == 14 + assert f.read() == 'am\n' + f.seek(0) + assert f.readline() == 'hello world\n' + assert f.readline(4) == 'spam' + assert f.readline(400) == '\n' + f.reset() + assert f.readlines() == ['hello world\n', 'spam\n'] + f.seek(0, 0) + assert f.readlines(5) == ['hello world\n'] + f.seek(0) + assert list(f) == ['hello world\n', 'spam\n'] + + f.flush() + assert f.getvalue() == 'hello world\nspam\n' + assert f.isatty() is False + + assert not f.closed + f.close() + assert f.closed + raises(ValueError, f.flush) + raises(ValueError, f.getvalue) + raises(ValueError, f.isatty) + raises(ValueError, f.read) + raises(ValueError, f.readline) + raises(ValueError, f.readlines) + raises(ValueError, f.reset) + raises(ValueError, f.tell) + raises(ValueError, f.seek, 5) + assert f.closed + f.close() + assert f.closed + + def test_types(self): + import cStringIO + assert type(cStringIO.StringIO()) is cStringIO.OutputType + assert type(cStringIO.StringIO('')) is cStringIO.InputType From arigo at codespeak.net Mon Apr 14 16:46:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 16:46:45 +0200 (CEST) Subject: [pypy-svn] r53760 - in pypy/dist: lib-python pypy/module/cStringIO pypy/module/cStringIO/test pypy/rlib pypy/rlib/test Message-ID: <20080414144645.113262A00E2@codespeak.net> Author: arigo Date: Mon Apr 14 16:46:44 2008 New Revision: 53760 Modified: pypy/dist/lib-python/conftest.py pypy/dist/pypy/module/cStringIO/interp_stringio.py pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py pypy/dist/pypy/rlib/rStringIO.py pypy/dist/pypy/rlib/test/test_rStringIO.py Log: Pass CPython's test_StringIO. It turns out that truncate() has semantics that don't match the Posix ones... Modified: pypy/dist/lib-python/conftest.py ============================================================================== --- pypy/dist/lib-python/conftest.py (original) +++ pypy/dist/lib-python/conftest.py Mon Apr 14 16:46:44 2008 @@ -671,7 +671,7 @@ RegrTest('test_strftime.py', enabled=False, dumbtest=1), RegrTest('test_string.py', enabled=True, core=True), - RegrTest('test_StringIO.py', enabled=True, core=True), + RegrTest('test_StringIO.py', enabled=True, core=True, usemodules='cStringIO'), RegrTest('test_stringprep.py', enabled=True, dumbtest=1), RegrTest('test_strop.py', enabled=False), #rev 10840: ImportError: strop Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/interp_stringio.py Mon Apr 14 16:46:44 2008 @@ -227,6 +227,7 @@ "cStringIO.StringI", __doc__ = "Simple type for treating strings as input file streams", **common_descrs + # XXX CPython has the truncate() method here too, which is a bit strange ) W_OutputType.typedef = TypeDef( Modified: pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/test/test_interp_stringio.py Mon Apr 14 16:46:44 2008 @@ -139,9 +139,9 @@ def test_truncate(self): f = self.StringIO() f.truncate(20) - assert f.getvalue() == '\x00' * 20 + assert f.getvalue() == '' assert f.tell() == 0 - f.seek(0, 2) + f.write('\x00' * 20) f.write('hello') f.write(' world') f.truncate(30) @@ -151,6 +151,7 @@ f.write('baz') f.write('egg') f.truncate(3) + assert f.tell() == 3 assert f.getvalue() == '\x00' * 3 raises(IOError, f.truncate, -1) Modified: pypy/dist/pypy/rlib/rStringIO.py ============================================================================== --- pypy/dist/pypy/rlib/rStringIO.py (original) +++ pypy/dist/pypy/rlib/rStringIO.py Mon Apr 14 16:46:44 2008 @@ -174,8 +174,10 @@ return ''.join(bigbuffer[p:p+count]) def truncate(self, size): + # NB. 'size' is mandatory. This has the same un-Posix-y semantics + # than CPython: it never grows the buffer, and it sets the current + # position to the end. assert size >= 0 - self.pos = self.tell() # in case it was AT_END if size > len(self.bigbuffer): self.copy_into_bigbuffer() else: @@ -184,7 +186,6 @@ self.strings[i] = '' self.numstrings = 0 self.numbigstrings = 0 - if size <= len(self.bigbuffer): + if size < len(self.bigbuffer): del self.bigbuffer[size:] - else: - self.bigbuffer += '\x00' * (size - len(self.bigbuffer)) + self.pos = AT_END Modified: pypy/dist/pypy/rlib/test/test_rStringIO.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rStringIO.py (original) +++ pypy/dist/pypy/rlib/test/test_rStringIO.py Mon Apr 14 16:46:44 2008 @@ -80,9 +80,9 @@ def test_truncate(): f = RStringIO() f.truncate(20) - assert f.getvalue() == '\x00' * 20 + assert f.getvalue() == '' assert f.tell() == 0 - f.seek(0, 2) + f.write('\x00' * 20) f.write('hello') f.write(' world') f.truncate(30) @@ -93,6 +93,7 @@ f.write('egg') f.truncate(3) assert f.getvalue() == '\x00' * 3 + assert f.tell() == 3 def test_stress(): import cStringIO, random From arigo at codespeak.net Mon Apr 14 17:58:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 17:58:33 +0200 (CEST) Subject: [pypy-svn] r53761 - in pypy/dist/pypy: module/cStringIO rlib Message-ID: <20080414155833.490CB2A00E2@codespeak.net> Author: arigo Date: Mon Apr 14 17:58:31 2008 New Revision: 53761 Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py pypy/dist/pypy/rlib/rStringIO.py Log: Translation fixes. Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/interp_stringio.py Mon Apr 14 17:58:31 2008 @@ -108,6 +108,8 @@ count = len(self.string) - p if n >= 0: count = min(n, count) + if count <= 0: + return '' self.pos = p + count if count == len(self.string): return self.string @@ -207,7 +209,6 @@ common_descrs = { '__iter__': interp2app(W_InputOutputType.descr___iter__), 'close': interp2app(W_InputOutputType.descr_close), - 'closed': GetSetProperty(descr_closed, cls=W_InputOutputType), 'flush': interp2app(W_InputOutputType.descr_flush), 'getvalue': interp2app(W_InputOutputType.descr_getvalue), 'isatty': interp2app(W_InputOutputType.descr_isatty), @@ -217,15 +218,16 @@ 'readlines': interp2app(W_InputOutputType.descr_readlines), 'reset': interp2app(W_InputOutputType.descr_reset), 'seek': interp2app(W_InputOutputType.descr_seek), - 'softspace': GetSetProperty(descr_softspace, - descr_setsoftspace, - cls=W_InputOutputType), 'tell': interp2app(W_InputOutputType.descr_tell), } W_InputType.typedef = TypeDef( "cStringIO.StringI", __doc__ = "Simple type for treating strings as input file streams", + closed = GetSetProperty(descr_closed, cls=W_InputType), + softspace = GetSetProperty(descr_softspace, + descr_setsoftspace, + cls=W_InputType), **common_descrs # XXX CPython has the truncate() method here too, which is a bit strange ) @@ -236,6 +238,10 @@ truncate = interp2app(W_OutputType.descr_truncate), write = interp2app(W_OutputType.descr_write), writelines = interp2app(W_OutputType.descr_writelines), + closed = GetSetProperty(descr_closed, cls=W_OutputType), + softspace = GetSetProperty(descr_softspace, + descr_setsoftspace, + cls=W_OutputType), **common_descrs ) Modified: pypy/dist/pypy/rlib/rStringIO.py ============================================================================== --- pypy/dist/pypy/rlib/rStringIO.py (original) +++ pypy/dist/pypy/rlib/rStringIO.py Mon Apr 14 17:58:31 2008 @@ -97,6 +97,7 @@ # used to handle the more complicated cases. p = self.pos if p != AT_END: # slow or semi-fast paths + assert p >= 0 endp = p + len(buffer) if len(self.bigbuffer) >= endp: # semi-fast path: the write is entirely inside self.bigbuffer @@ -148,9 +149,11 @@ def tell(self): if self.pos == AT_END: - return self.getsize() + result = self.getsize() else: - return self.pos + result = self.pos + assert result >= 0 + return result def read(self, n=-1): p = self.pos @@ -159,6 +162,7 @@ return self.getvalue() # reading everything if p == AT_END: return '' + assert p >= 0 bigbuffer = self.copy_into_bigbuffer() mysize = len(bigbuffer) count = mysize - p From arigo at codespeak.net Mon Apr 14 21:04:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 21:04:56 +0200 (CEST) Subject: [pypy-svn] r53762 - in pypy/dist/pypy: module/sys objspace/std Message-ID: <20080414190456.BF277169DB7@codespeak.net> Author: arigo Date: Mon Apr 14 21:04:54 2008 New Revision: 53762 Modified: pypy/dist/pypy/module/sys/__init__.py pypy/dist/pypy/module/sys/interp_encoding.py pypy/dist/pypy/objspace/std/unicodeobject.py pypy/dist/pypy/objspace/std/unicodetype.py Log: Experimental big cuts in the amount of indirections. Modified: pypy/dist/pypy/module/sys/__init__.py ============================================================================== --- pypy/dist/pypy/module/sys/__init__.py (original) +++ pypy/dist/pypy/module/sys/__init__.py Mon Apr 14 21:04:54 2008 @@ -8,6 +8,7 @@ super(Module, self).__init__(space, w_name) self.checkinterval = 100 self.recursionlimit = 100 + self.w_default_encoder = None self.defaultencoding = "ascii" interpleveldefs = { @@ -126,3 +127,13 @@ else: return space.wrap(operror.application_traceback) return None + + def get_w_default_encoder(self): + if self.w_default_encoder is not None: + # XXX is this level of caching ok? CPython has some shortcuts + # for common encodings, but as far as I can see it has no general + # cache. + return self.w_default_encoder + else: + from pypy.module.sys.interp_encoding import get_w_default_encoder + return get_w_default_encoder(self.space) Modified: pypy/dist/pypy/module/sys/interp_encoding.py ============================================================================== --- pypy/dist/pypy/module/sys/interp_encoding.py (original) +++ pypy/dist/pypy/module/sys/interp_encoding.py Mon Apr 14 21:04:54 2008 @@ -11,4 +11,14 @@ w_lookup = space.getattr(mod, space.wrap("lookup")) # check whether the encoding is there space.call_function(w_lookup, w_encoding) + space.sys.w_default_encoder = None space.sys.defaultencoding = encoding + +def get_w_default_encoder(space): + w_encoding = space.wrap(space.sys.defaultencoding) + mod = space.getbuiltinmodule("_codecs") + w_lookup = space.getattr(mod, space.wrap("lookup")) + w_functuple = space.call_function(w_lookup, w_encoding) + w_encoder = space.getitem(w_functuple, space.wrap(0)) + space.sys.w_default_encoder = w_encoder # cache it + return w_encoder Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Mon Apr 14 21:04:54 2008 @@ -71,13 +71,14 @@ return w_uni def str_w__Unicode(space, w_uni): - return space.str_w(space.str(w_uni)) + return space.str_w(str__Unicode(space, w_uni)) def unicode_w__Unicode(space, w_uni): return w_uni._value def str__Unicode(space, w_uni): - return space.call_method(w_uni, 'encode') + from pypy.objspace.std.unicodetype import encode_object + return encode_object(space, w_uni, None, None) def eq__Unicode_Unicode(space, w_left, w_right): return space.newbool(w_left._value == w_right._value) @@ -752,11 +753,9 @@ w_encoding=None, w_errors=None): - from pypy.objspace.std.unicodetype import getdefaultencoding, \ - _get_encoding_and_errors, encode_object + from pypy.objspace.std.unicodetype import _get_encoding_and_errors + from pypy.objspace.std.unicodetype import encode_object encoding, errors = _get_encoding_and_errors(space, w_encoding, w_errors) - if encoding is None: - encoding = getdefaultencoding(space) w_retval = encode_object(space, w_unistr, encoding, errors) return w_retval Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Mon Apr 14 21:04:54 2008 @@ -165,15 +165,19 @@ return encoding, errors def encode_object(space, w_object, encoding, errors): - w_codecs = space.getbuiltinmodule("_codecs") - w_encode = space.getattr(w_codecs, space.wrap("encode")) if encoding is None: - encoding = getdefaultencoding(space) + # Get the encoder functions as a wrapped object. + # This lookup is cached. + w_encoder = space.sys.get_w_default_encoder() + else: + from pypy.module._codecs.interp_codecs import lookup_codec + w_encoder = space.getitem(lookup_codec(space, encoding), space.wrap(0)) if errors is None: - w_retval = space.call_function(w_encode, w_object, space.wrap(encoding)) + w_errors = space.wrap('strict') else: - w_retval = space.call_function(w_encode, w_object, space.wrap(encoding), - space.wrap(errors)) + w_errors = space.wrap(errors) + w_restuple = space.call_function(w_encoder, w_object, w_errors) + w_retval = space.getitem(w_restuple, space.wrap(0)) if not space.is_true(space.isinstance(w_retval, space.w_str)): raise OperationError( space.w_TypeError, From arigo at codespeak.net Mon Apr 14 21:09:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Apr 2008 21:09:50 +0200 (CEST) Subject: [pypy-svn] r53763 - pypy/dist/pypy/rlib Message-ID: <20080414190950.B7198169DB7@codespeak.net> Author: arigo Date: Mon Apr 14 21:09:48 2008 New Revision: 53763 Modified: pypy/dist/pypy/rlib/runicode.py Log: Trying to improve translation by making sure this is a list of characters. Modified: pypy/dist/pypy/rlib/runicode.py ============================================================================== --- pypy/dist/pypy/rlib/runicode.py (original) +++ pypy/dist/pypy/rlib/runicode.py Mon Apr 14 21:09:48 2008 @@ -389,7 +389,7 @@ collend += 1 r, pos = errorhandler(errors, encoding, reason, p, collstart, collend) - result.append(r) + result += r # extend 'result' as a list of characters return "".join(result) From fijal at codespeak.net Tue Apr 15 05:15:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 15 Apr 2008 05:15:28 +0200 (CEST) Subject: [pypy-svn] r53769 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080415031528.B6BA7168457@codespeak.net> Author: fijal Date: Tue Apr 15 05:15:26 2008 New Revision: 53769 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py Log: Hum. It seems I forgotten to check this one in. Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Tue Apr 15 05:15:26 2008 @@ -173,9 +173,21 @@ hop.exception_cannot_occur() return hop.genop('gc_set_max_heap_size', [v_nbytes], resulttype=lltype.Void) + +class CollectEntry(ExtRegistryEntry): + _about_ = (disable_finalizers, enable_finalizers) + + def compute_result_annotation(self): + from pypy.annotation import model as annmodel + return annmodel.s_None + + def specialize_call(self, hop): + opname = 'gc__' + self.instance.__name__ + hop.exception_cannot_occur() + return hop.genop(opname, [], resulttype=hop.r_result) + def can_move(p): return True -can_move._annspecialcase_ = 'specialize:argtype(0)' class CanMoveEntry(ExtRegistryEntry): _about_ = can_move @@ -189,14 +201,34 @@ hop.exception_cannot_occur() return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result) -class CollectEntry(ExtRegistryEntry): - _about_ = (disable_finalizers, enable_finalizers) - - def compute_result_annotation(self): - from pypy.annotation import model as annmodel - return annmodel.s_None +def malloc_nonmovable(TP, n=None): + """ Allocate a non-moving buffer or return nullptr. + When running directly, will pretend that gc is always + moving (might be configurable in a future) + """ + from pypy.rpython.lltypesystem import lltype + return lltype.nullptr(TP) + +class MallocNonMovingEntry(ExtRegistryEntry): + _about_ = malloc_nonmovable + + def compute_result_annotation(self, s_TP, s_n=None): + # basically return the same as malloc + from pypy.annotation.builtin import malloc + return malloc(s_TP, s_n) def specialize_call(self, hop): - opname = 'gc__' + self.instance.__name__ + from pypy.rpython.lltypesystem import lltype + # XXX assume flavor and zero to be None by now + assert hop.args_s[0].is_constant() + vlist = [hop.inputarg(lltype.Void, arg=0)] + opname = 'malloc_nonmovable' + flags = {'flavor': 'gc'} + vlist.append(hop.inputconst(lltype.Void, flags)) + + if hop.nb_args == 2: + vlist.append(hop.inputarg(lltype.Signed, arg=1)) + opname += '_varsize' + hop.exception_cannot_occur() - return hop.genop(opname, [], resulttype=hop.r_result) + return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) From fijal at codespeak.net Tue Apr 15 05:35:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 15 Apr 2008 05:35:49 +0200 (CEST) Subject: [pypy-svn] r53770 - in pypy/dist/pypy/rlib: . test Message-ID: <20080415033549.A4A8739B594@codespeak.net> Author: fijal Date: Tue Apr 15 05:35:47 2008 New Revision: 53770 Added: pypy/dist/pypy/rlib/rstring.py (contents, props changed) pypy/dist/pypy/rlib/test/test_rstring.py (contents, props changed) Log: string builder implementation, first steps. Added: pypy/dist/pypy/rlib/rstring.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rstring.py Tue Apr 15 05:35:47 2008 @@ -0,0 +1,22 @@ + +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.annotation import model as annmodel + +def builder(initial_space=20): + return [] + +class SomeStringBuilder(annmodel.SomeObject): + def __init__(self, initial_space=0): + self.initial_space = initial_space + +class StringBuilderEntry(ExtRegistryEntry): + _about_ = builder + + def compute_result_annotation(self, s_initial_space=None): + if s_initial_space is None: + initial_space = 0 + else: + assert s_initial_space.is_constant() + initial_space = s_initial_space.const + assert isinstance(initial_space, int) + return SomeStringBuilder(initial_space) Added: pypy/dist/pypy/rlib/test/test_rstring.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/test/test_rstring.py Tue Apr 15 05:35:47 2008 @@ -0,0 +1,16 @@ + +from pypy.translator.translator import TranslationContext +from pypy.rlib import rstring + +class TestAnnotationStringBuilder: + def annotate(self, func, args): + t = TranslationContext() + res = t.buildannotator().build_types(func, args) + return t, res + + def test_builder(self): + def f(): + return rstring.builder() + + t, res = self.annotate(f, []) + assert isinstance(res, rstring.SomeStringBuilder) From fijal at codespeak.net Tue Apr 15 05:42:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 15 Apr 2008 05:42:12 +0200 (CEST) Subject: [pypy-svn] r53771 - in pypy/dist/pypy/rlib: . test Message-ID: <20080415034212.9F74939B594@codespeak.net> Author: fijal Date: Tue Apr 15 05:42:11 2008 New Revision: 53771 Modified: pypy/dist/pypy/rlib/rstring.py pypy/dist/pypy/rlib/test/test_rstring.py Log: Method support (no unicode!) Modified: pypy/dist/pypy/rlib/rstring.py ============================================================================== --- pypy/dist/pypy/rlib/rstring.py (original) +++ pypy/dist/pypy/rlib/rstring.py Tue Apr 15 05:42:11 2008 @@ -9,6 +9,14 @@ def __init__(self, initial_space=0): self.initial_space = initial_space + def method_append(self, s_item): + if not isinstance(s_item, annmodel.SomeString): + raise TypeError("Can only append strings or characters to string builder") + return annmodel.SomeImpossibleValue() + + def method_build(self): + return annmodel.SomeString() + class StringBuilderEntry(ExtRegistryEntry): _about_ = builder Modified: pypy/dist/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rstring.py (original) +++ pypy/dist/pypy/rlib/test/test_rstring.py Tue Apr 15 05:42:11 2008 @@ -1,6 +1,7 @@ from pypy.translator.translator import TranslationContext from pypy.rlib import rstring +from pypy.annotation import model as annmodel class TestAnnotationStringBuilder: def annotate(self, func, args): @@ -14,3 +15,13 @@ t, res = self.annotate(f, []) assert isinstance(res, rstring.SomeStringBuilder) + + def test_methods(self): + def f(x): + b = rstring.builder() + for i in range(x): + b.append("abc") + return b.build() + + t, res = self.annotate(f, [int]) + assert isinstance(res, annmodel.SomeString) From arigo at codespeak.net Tue Apr 15 13:44:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Apr 2008 13:44:35 +0200 (CEST) Subject: [pypy-svn] r53779 - pypy/dist/pypy/config Message-ID: <20080415114435.B5183169E3C@codespeak.net> Author: arigo Date: Tue Apr 15 13:44:33 2008 New Revision: 53779 Modified: pypy/dist/pypy/config/pypyoption.py Log: Add cStringIO to allworkingmodules. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue Apr 15 13:44:33 2008 @@ -25,7 +25,7 @@ working_modules.update(dict.fromkeys( ["_socket", "unicodedata", "mmap", "fcntl", "rctime", "select", "crypt", "signal", "dyngram", "_rawffi", "termios", "zlib", - "struct", "md5", "sha", "bz2", "_minimal_curses", + "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO", ] )) From arigo at codespeak.net Tue Apr 15 13:44:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Apr 2008 13:44:47 +0200 (CEST) Subject: [pypy-svn] r53780 - in pypy/dist/pypy/interpreter: . test Message-ID: <20080415114447.DDADD169E35@codespeak.net> Author: arigo Date: Tue Apr 15 13:44:47 2008 New Revision: 53780 Modified: pypy/dist/pypy/interpreter/test/test_typedef.py pypy/dist/pypy/interpreter/typedef.py Log: Refactor the logic that creates interp-level subclasses of the W_XxxObject classes. It was broken because it created much more combinations than the 5 that it eventually used. Another issue was with creating a class with __slots__=[] and with a destructor. The instance could contain arbitrary attributes, which is probably wrong (and definitely unexpected). Modified: pypy/dist/pypy/interpreter/test/test_typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_typedef.py (original) +++ pypy/dist/pypy/interpreter/test/test_typedef.py Tue Apr 15 13:44:47 2008 @@ -1,3 +1,4 @@ +from pypy.interpreter import typedef # this test isn't so much to test that the objspace interface *works* # -- it's more to test that it's *there* @@ -57,3 +58,75 @@ class A(object): pass assert A.__dict__['__dict__'].__name__ == '__dict__' + + +class TestTypeDef: + + def test_subclass_cache(self): + # check that we don't create more than 6 subclasses of a + # given W_XxxObject (instead of the 16 that follow from + # all combinations) + space = self.space + sources = [] + for hasdict in [False, True]: + for wants_slots in [False, True]: + for needsdel in [False, True]: + for weakrefable in [False, True]: + print 'Testing case', hasdict, wants_slots, + print needsdel, weakrefable + slots = [] + checks = [] + + if hasdict: + slots.append('__dict__') + checks.append('x.foo=5; x.__dict__') + else: + checks.append('raises(AttributeError, "x.foo=5");' + 'raises(AttributeError, "x.__dict__")') + + if wants_slots: + slots.append('a') + checks.append('x.a=5; assert X.a.__get__(x)==5') + else: + checks.append('') + + if weakrefable: + slots.append('__weakref__') + checks.append('import _weakref;_weakref.ref(x)') + else: + checks.append('') + + if needsdel: + methodname = '__del__' + checks.append('X();X();X();' + 'import gc;gc.collect();' + 'assert seen') + else: + methodname = 'spam' + checks.append('assert "Del" not in irepr') + + assert len(checks) == 4 + space.appexec([], """(): + seen = [] + class X(list): + __slots__ = %r + def %s(self): + seen.append(1) + x = X() + import __pypy__ + irepr = __pypy__.internal_repr(x) + print irepr + %s + %s + %s + %s + """ % (slots, methodname, checks[0], checks[1], + checks[2], checks[3])) + subclasses = {} + for key, subcls in typedef._subclass_cache.items(): + cls = key[0] + subclasses.setdefault(cls, {}) + subclasses[cls][subcls] = True + for cls, set in subclasses.items(): + assert len(set) <= 6, "%s has %d subclasses:\n%r" % ( + cls, len(set), [subcls.__name__ for subcls in set]) Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Tue Apr 15 13:44:47 2008 @@ -91,62 +91,148 @@ no_hash_descr = interp2app(descr__hash__unhashable) # ____________________________________________________________ +# +# For each built-in app-level type Xxx that can be subclassed at +# app-level, the corresponding interp-level W_XxxObject class cannot +# generally represent instances of app-level subclasses of Xxx. The +# reason is that it is missing a place to store the __dict__, the slots, +# the weakref lifeline, and it typically has no interp-level __del__. +# So we create a few interp-level subclasses of W_XxxObject, which add +# some combination of features. +# +# We don't build 2**4 == 16 subclasses for all combinations of requested +# features, but limit ourselves to 6, chosen a bit arbitrarily based on +# typical usage (case 1 is the most common kind of app-level subclasses; +# case 2 is the memory-saving kind defined with __slots__). +# +# dict slots del weakrefable +# +# 1. Y N N Y UserDictWeakref +# 2. N Y N N UserSlots +# 3. Y Y N Y UserDictWeakrefSlots +# 4. N Y N Y UserSlotsWeakref +# 5. Y Y Y Y UserDictWeakrefSlotsDel +# 6. N Y Y Y UserSlotsWeakrefDel +# +# Note that if the app-level explicitly requests no dict, we should not +# provide one, otherwise storing random attributes on the app-level +# instance would unexpectedly work. We don't care too much, though, if +# an object is weakrefable when it shouldn't really be. It's important +# that it has a __del__ only if absolutely needed, as this kills the +# performance of the GCs. +# +# Interp-level inheritance is like this: +# +# W_XxxObject base +# / \ +# 1 2 +# / \ +# 3 4 +# / \ +# 5 6 + def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False, weakrefable=False): - if needsdel: - hasdict = wants_slots = weakrefable = True - if hasdict: - weakrefable = True - else: - wants_slots = True - return _get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel, weakrefable) -get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" - -def _get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel, weakrefable): "NOT_RPYTHON: initialization-time only" - typedef = cls.typedef - if hasdict and typedef.hasdict: - hasdict = False - if weakrefable and typedef.weakrefable: - weakrefable = False - key = cls, hasdict, wants_slots, needsdel, weakrefable try: return _subclass_cache[key] except KeyError: - subcls = _buildusercls(cls, hasdict, wants_slots, needsdel, weakrefable) + subcls = _getusercls(cls, hasdict, wants_slots, needsdel, weakrefable) _subclass_cache[key] = subcls return subcls +get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" _subclass_cache = {} -def _buildusercls(cls, hasdict, wants_slots, wants_del, weakrefable): - "NOT_RPYTHON: initialization-time only" - name = ['User'] - if not hasdict: - name.append('NoDict') - if wants_slots: - name.append('WithSlots') +def _getusercls(cls, wants_dict, wants_slots, wants_del, weakrefable): + typedef = cls.typedef + if wants_dict and typedef.hasdict: + wants_dict = False + # Forest of if's - see the comment above. if wants_del: - name.append('WithDel') - if weakrefable: - name.append('Weakrefable') - - name.append(cls.__name__) - - name = ''.join(name) - if weakrefable: - supercls = _get_unique_interplevel_subclass(cls, hasdict, wants_slots, - wants_del, False) + if wants_dict: + # case 5. Parent class is 3. + parentcls = get_unique_interplevel_subclass(cls, True, True, + False, True) + else: + # case 6. Parent class is 4. + parentcls = get_unique_interplevel_subclass(cls, False, True, + False, True) + return _usersubclswithfeature(parentcls, "del") + elif wants_dict: + if wants_slots: + # case 3. Parent class is 1. + parentcls = get_unique_interplevel_subclass(cls, True, False, + False, True) + return _usersubclswithfeature(parentcls, "slots") + else: + # case 1 (we need to add weakrefable unless it's already in 'cls') + if not typedef.weakrefable: + return _usersubclswithfeature(cls, "user", "dict", "weakref") + else: + return _usersubclswithfeature(cls, "user", "dict") + else: + if weakrefable and not typedef.weakrefable: + # case 4. Parent class is 2. + parentcls = get_unique_interplevel_subclass(cls, False, True, + False, False) + return _usersubclswithfeature(parentcls, "weakref") + else: + # case 2 (if the base is already weakrefable, case 2 == case 4) + return _usersubclswithfeature(cls, "user", "slots") + +def _usersubclswithfeature(parentcls, *features): + key = parentcls, features + try: + return _usersubclswithfeature_cache[key] + except KeyError: + subcls = _builduserclswithfeature(parentcls, *features) + _usersubclswithfeature_cache[key] = subcls + return subcls +_usersubclswithfeature_cache = {} +_allusersubcls_cache = {} + +def _builduserclswithfeature(supercls, *features): + "NOT_RPYTHON: initialization-time only" + name = supercls.__name__ + name += ''.join([name.capitalize() for name in features]) + body = {} + #print '..........', name, '(', supercls.__name__, ')' + + def add(Proto): + for key, value in Proto.__dict__.items(): + if not key.startswith('__') or key == '__del__': + body[key] = value + + if "user" in features: # generic feature needed by all subcls + class Proto(object): + def getclass(self, space): + return self.w__class__ + + def setclass(self, space, w_subtype): + # only used by descr_set___class__ + self.w__class__ = w_subtype + + def user_setup(self, space, w_subtype): + self.space = space + self.w__class__ = w_subtype + self.user_setup_slots(w_subtype.nslots) + + def user_setup_slots(self, nslots): + assert nslots == 0 + add(Proto) + + if "weakref" in features: class Proto(object): _lifeline_ = None def getweakref(self): return self._lifeline_ def setweakref(self, space, weakreflifeline): self._lifeline_ = weakreflifeline - elif wants_del: - supercls = _get_unique_interplevel_subclass(cls, hasdict, wants_slots, - False, False) - parent_destructor = getattr(cls, '__del__', None) + add(Proto) + + if "del" in features: + parent_destructor = getattr(supercls, '__del__', None) class Proto(object): def __del__(self): self.clear_all_weakrefs() @@ -157,23 +243,21 @@ e.clear(self.space) # break up reference cycles if parent_destructor is not None: parent_destructor(self) - elif wants_slots: - supercls = _get_unique_interplevel_subclass(cls, hasdict, False, False, False) - + add(Proto) + + if "slots" in features: class Proto(object): slots_w = [] def user_setup_slots(self, nslots): if nslots > 0: self.slots_w = [None] * nslots - def setslotvalue(self, index, w_value): self.slots_w[index] = w_value - def getslotvalue(self, index): return self.slots_w[index] - elif hasdict: - supercls = _get_unique_interplevel_subclass(cls, False, False, False, False) - + add(Proto) + + if "dict" in features: class Proto(object): def getdict(self): return self.w__dict__ @@ -216,33 +300,11 @@ if not w_dict.implementation.shadows_anything(): return None return space.finditem(w_dict, w_name) - - else: - supercls = cls - - class Proto(object): - - def getclass(self, space): - return self.w__class__ - - def setclass(self, space, w_subtype): - # only used by descr_set___class__ - self.w__class__ = w_subtype - - - def user_setup(self, space, w_subtype): - self.space = space - self.w__class__ = w_subtype - self.user_setup_slots(w_subtype.nslots) - - def user_setup_slots(self, nslots): - assert nslots == 0 - - body = dict([(key, value) - for key, value in Proto.__dict__.items() - if not key.startswith('__') or key == '__del__']) + add(Proto) + subcls = type(name, (supercls,), body) + _allusersubcls_cache[subcls] = True return subcls def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): From fijal at codespeak.net Wed Apr 16 00:13:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Apr 2008 00:13:12 +0200 (CEST) Subject: [pypy-svn] r53810 - pypy/dist/pypy/objspace/std Message-ID: <20080415221312.668FD169F08@codespeak.net> Author: fijal Date: Wed Apr 16 00:13:12 2008 New Revision: 53810 Modified: pypy/dist/pypy/objspace/std/formatting.py Log: this speeds up formatting by a tiny bit Modified: pypy/dist/pypy/objspace/std/formatting.py ============================================================================== --- pypy/dist/pypy/objspace/std/formatting.py (original) +++ pypy/dist/pypy/objspace/std/formatting.py Wed Apr 16 00:13:12 2008 @@ -6,6 +6,7 @@ from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.debug import check_annotation +from pypy.rlib.objectmodel import newlist class BaseStringFormatter(object): def __init__(self, space, values_w, w_valuedict): @@ -256,7 +257,7 @@ return result def format(self): - result = [] # list of characters or unichars + result = newlist(sizehint=100) # list of characters or unichars self.result = result while True: # fast path: consume as many characters as possible From fijal at codespeak.net Wed Apr 16 01:28:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Apr 2008 01:28:28 +0200 (CEST) Subject: [pypy-svn] r53811 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080415232828.818AC49814C@codespeak.net> Author: fijal Date: Wed Apr 16 01:28:25 2008 New Revision: 53811 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Log: add missing ops Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Wed Apr 16 01:28:25 2008 @@ -322,8 +322,8 @@ 'malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'coalloc': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'coalloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_nonmovable': LLOp(canunwindgc=True), + 'malloc_nonmovable_varsize': LLOp(canunwindgc=True), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), From docgok at codespeak.net Wed Apr 16 01:35:42 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Wed, 16 Apr 2008 01:35:42 +0200 (CEST) Subject: [pypy-svn] r53812 - in pypy/branch/io-improvements/pypy/rpython: lltypesystem module Message-ID: <20080415233542.E65D449814C@codespeak.net> Author: docgok Date: Wed Apr 16 01:35:41 2008 New Revision: 53812 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Attempted refactorization of non-moving APIs. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Wed Apr 16 01:35:41 2008 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr -from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof +from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof, raw_memcopy from pypy.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic @@ -15,7 +15,7 @@ from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer -from pypy.rpython.annlowlevel import llhelper, llstr +from pypy.rpython.annlowlevel import llhelper, llstr, hlstr import os class UnhandledRPythonException(Exception): @@ -500,7 +500,56 @@ lltype.free(buf, flavor='raw') else: keepalive_until_here(data) - + +def alloc_buffer_for_hlstr(count): + from pypy.rpython.lltypesystem.rstr import STR + buf = rgc.malloc_nonmovable(STR, count) + if buf: + offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + realbuf = cast_ptr_to_adr(buf) + offset + c_buf = cast(VOIDP, realbuf) + return c_buf, buf, True + else: + raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + return raw_buf, lltype.nullptr(STR), False + +def hlstr_from_buffer(buf, is_collected, allocated_size, needed_size): + from pypy.rpython.lltypesystem.rstr import STR, mallocstr + offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + if is_collected: + if allocated_size != needed_size: + new_buf = lltype.nullptr(STR) + try: + new_buf = mallocstr(needed_size) + dest = cast_ptr_to_adr(new_buf) + offset + source = cast_ptr_to_adr(buf) + \ + itemoffsetof(lltype.typeOf(buf).TO, 0) + ## FIXME: This is bad, because dest could potentially move + ## if there are threads involved. + raw_memcopy(source, dest, sizeof(lltype.Char) * needed_size) + return hlstr(new_buf) + finally: + keepalive_until_here(new_buf) + return hlstr(buf) + else: + new_buf = lltype.nullptr(STR) + try: + new_buf = mallocstr(needed_size) + source = cast_ptr_to_adr(buf) + \ + itemoffsetof(lltype.typeOf(buf).TO, 0) + dest = cast_ptr_to_adr(new_buf) + offset + ## FIXME: see above + raw_memcopy(source, dest, sizeof(lltype.Char) * needed_size) + return hlstr(new_buf) + finally: + keepalive_until_here(new_buf) + +def keep_buffer_for_hlstr_alive_until_here(buf, is_collected): + if is_collected: + keepalive_until_here(buf) + else: + lltype.free(buf, flavor='raw') + # char* -> str, with an upper bound on the length in case there is no \x00 def charp2strn(cp, maxlen): l = [] Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Wed Apr 16 01:35:41 2008 @@ -20,8 +20,8 @@ from pypy.tool.udir import udir from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr, llstr -from pypy.rpython.lltypesystem.llmemory import raw_memcopy, sizeof,\ +from pypy.rpython.annlowlevel import llstr +from pypy.rpython.lltypesystem.llmemory import sizeof,\ itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import llstr @@ -487,38 +487,17 @@ def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) - inbuf = rgc.malloc_nonmovable(STR, count) - if inbuf: - try: - realbuf = cast_ptr_to_adr(inbuf) + offset - c_buf = rffi.cast(rffi.VOIDP, realbuf) - got = rffi.cast(lltype.Signed, os_read(fd, c_buf, count)) - if got < 0: - raise OSError(rposix.get_errno(), "os_read failed") - if got != count: - # we need to realloc - s = mallocstr(got) - dest = cast_ptr_to_adr(s) + offset - raw_memcopy(realbuf, dest, sizeof(lltype.Char) * got) - return hlstr(s) - return hlstr(inbuf) - finally: - keepalive_until_here(inbuf) - else: - inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') - try: - got = rffi.cast(lltype.Signed, os_read(fd, inbuf, count)) - if got < 0: - raise OSError(rposix.get_errno(), "os_read failed") - s = mallocstr(got) - source = cast_ptr_to_adr(inbuf) + \ - itemoffsetof(lltype.typeOf(inbuf).TO, 0) - dest = cast_ptr_to_adr(s) + offset - raw_memcopy(source, dest, sizeof(lltype.Char) * got) - finally: - lltype.free(inbuf, flavor='raw') - return hlstr(s) - + buf = lltype.nullptr(STR) + is_collected = False + try: + c_buf, buf, is_collected = rffi.alloc_buffer_for_hlstr(count) + got = rffi.cast(lltype.Signed, os_read(fd, c_buf, count)) + if got < 0: + raise OSError(rposix.get_errno(), "os_read failed") + return rffi.hlstr_from_buffer(buf, is_collected, count, got) + finally: + rffi.keep_buffer_for_hlstr_alive_until_here(buf, is_collected) + def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) From docgok at codespeak.net Wed Apr 16 01:59:23 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Wed, 16 Apr 2008 01:59:23 +0200 (CEST) Subject: [pypy-svn] r53813 - in pypy/branch/io-improvements/pypy/rpython: lltypesystem module Message-ID: <20080415235923.C682549814E@codespeak.net> Author: docgok Date: Wed Apr 16 01:59:23 2008 New Revision: 53813 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Cleaner API, plus it works now. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Wed Apr 16 01:59:23 2008 @@ -508,25 +508,24 @@ offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) realbuf = cast_ptr_to_adr(buf) + offset c_buf = cast(VOIDP, realbuf) - return c_buf, buf, True + return c_buf, buf else: raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') - return raw_buf, lltype.nullptr(STR), False + return raw_buf, lltype.nullptr(STR) -def hlstr_from_buffer(buf, is_collected, allocated_size, needed_size): +def hlstr_from_buffer(buf, allocated_size, needed_size): from pypy.rpython.lltypesystem.rstr import STR, mallocstr offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - if is_collected: + if buf: if allocated_size != needed_size: new_buf = lltype.nullptr(STR) try: new_buf = mallocstr(needed_size) dest = cast_ptr_to_adr(new_buf) + offset - source = cast_ptr_to_adr(buf) + \ - itemoffsetof(lltype.typeOf(buf).TO, 0) + realbuf = cast_ptr_to_adr(buf) + offset ## FIXME: This is bad, because dest could potentially move ## if there are threads involved. - raw_memcopy(source, dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(realbuf, dest, sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) @@ -536,7 +535,7 @@ try: new_buf = mallocstr(needed_size) source = cast_ptr_to_adr(buf) + \ - itemoffsetof(lltype.typeOf(buf).TO, 0) + itemoffsetof(CCHARP.TO, 0) dest = cast_ptr_to_adr(new_buf) + offset ## FIXME: see above raw_memcopy(source, dest, sizeof(lltype.Char) * needed_size) @@ -544,8 +543,8 @@ finally: keepalive_until_here(new_buf) -def keep_buffer_for_hlstr_alive_until_here(buf, is_collected): - if is_collected: +def keep_buffer_for_hlstr_alive_until_here(buf): + if buf: keepalive_until_here(buf) else: lltype.free(buf, flavor='raw') Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Wed Apr 16 01:59:23 2008 @@ -488,15 +488,14 @@ if count < 0: raise OSError(errno.EINVAL, None) buf = lltype.nullptr(STR) - is_collected = False try: - c_buf, buf, is_collected = rffi.alloc_buffer_for_hlstr(count) + c_buf, buf = rffi.alloc_buffer_for_hlstr(count) got = rffi.cast(lltype.Signed, os_read(fd, c_buf, count)) if got < 0: raise OSError(rposix.get_errno(), "os_read failed") - return rffi.hlstr_from_buffer(buf, is_collected, count, got) + return rffi.hlstr_from_buffer(buf, count, got) finally: - rffi.keep_buffer_for_hlstr_alive_until_here(buf, is_collected) + rffi.keep_buffer_for_hlstr_alive_until_here(buf) def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) From fijal at codespeak.net Wed Apr 16 02:24:55 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Apr 2008 02:24:55 +0200 (CEST) Subject: [pypy-svn] r53814 - pypy/dist/pypy/objspace Message-ID: <20080416002455.9C4BC16855C@codespeak.net> Author: fijal Date: Wed Apr 16 02:24:55 2008 New Revision: 53814 Modified: pypy/dist/pypy/objspace/descroperation.py Log: pff, kill pdb invocation (commented out) Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Wed Apr 16 02:24:55 2008 @@ -474,9 +474,6 @@ left, right = specialnames op = getattr(operator, left) def comparison_impl(space, w_obj1, w_obj2): - #from pypy.objspace.std.tlistobject import W_TransparentList - #if isinstance(w_obj1, W_TransparentList): - # import pdb;pdb.set_trace() w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) From docgok at codespeak.net Wed Apr 16 02:48:26 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Wed, 16 Apr 2008 02:48:26 +0200 (CEST) Subject: [pypy-svn] r53815 - in pypy/branch/io-improvements/pypy/rpython: lltypesystem lltypesystem/test module Message-ID: <20080416004826.951EF49814C@codespeak.net> Author: docgok Date: Wed Apr 16 02:48:24 2008 New Revision: 53815 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Still doesn't work, but now I don't know why. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Wed Apr 16 02:48:24 2008 @@ -16,6 +16,7 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer from pypy.rpython.annlowlevel import llhelper, llstr, hlstr +from pypy.rpython.lltypesystem.rstr import STR, mallocstr import os class UnhandledRPythonException(Exception): @@ -501,53 +502,49 @@ else: keepalive_until_here(data) + +str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + def alloc_buffer_for_hlstr(count): - from pypy.rpython.lltypesystem.rstr import STR - buf = rgc.malloc_nonmovable(STR, count) - if buf: - offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - realbuf = cast_ptr_to_adr(buf) + offset - c_buf = cast(VOIDP, realbuf) - return c_buf, buf + gc_buf = rgc.malloc_nonmovable(STR, count) + if gc_buf: + realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset + raw_buf = cast(CCHARP.TO, realbuf) + return raw_buf, gc_buf else: raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') return raw_buf, lltype.nullptr(STR) -def hlstr_from_buffer(buf, allocated_size, needed_size): - from pypy.rpython.lltypesystem.rstr import STR, mallocstr - offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - if buf: +def hlstr_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): + if gc_buf: if allocated_size != needed_size: new_buf = lltype.nullptr(STR) try: new_buf = mallocstr(needed_size) - dest = cast_ptr_to_adr(new_buf) + offset - realbuf = cast_ptr_to_adr(buf) + offset + dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: This is bad, because dest could potentially move ## if there are threads involved. - raw_memcopy(realbuf, dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(raw_buf, dest, sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) - return hlstr(buf) + return hlstr(gc_buf) else: new_buf = lltype.nullptr(STR) try: new_buf = mallocstr(needed_size) - source = cast_ptr_to_adr(buf) + \ - itemoffsetof(CCHARP.TO, 0) - dest = cast_ptr_to_adr(new_buf) + offset + dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: see above - raw_memcopy(source, dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(raw_buf, dest, sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) -def keep_buffer_for_hlstr_alive_until_here(buf): - if buf: - keepalive_until_here(buf) +def keep_buffer_for_hlstr_alive_until_here(raw_buf, gc_buf): + if gc_buf: + keepalive_until_here(gc_buf) else: - lltype.free(buf, flavor='raw') + lltype.free(raw_buf, flavor='raw') # char* -> str, with an upper bound on the length in case there is no \x00 def charp2strn(cp, maxlen): Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Wed Apr 16 02:48:24 2008 @@ -6,6 +6,7 @@ from pypy.translator.c.test.test_genc import compile as compile_c from pypy.translator.llvm.test.runtest import compile_function as compile_llvm from pypy.rpython.lltypesystem.lltype import Signed, Ptr, Char, malloc +from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir from pypy.rpython.test.test_llinterp import interpret, MallocMismatch @@ -430,6 +431,22 @@ unregister_keepalive(pos, TP) assert res == 8 + def test_nonmoving_hlstr(self): + d = 'non-moving data stuff' + def f(): + gc_buf = lltype.nullptr(STR) + raw_buf = lltype.nullptr(CCHARP.TO) + try: + raw_buf, gc_buf = alloc_buffer_for_hlstr(len(d)) + for i in range(len(d)): + raw_buf[i] = d[i] + return hlstr_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) + finally: + keep_buffer_for_hlstr_alive_until_here(raw_buf, gc_buf) + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == d[:-1] + + def test_nonmovingbuffer(self): d = 'some cool data that should not move' def f(): Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Wed Apr 16 02:48:24 2008 @@ -487,15 +487,17 @@ def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) - buf = lltype.nullptr(STR) + raw_buf = lltype.nullptr(rffi.CCHARP.TO) + gc_buf = lltype.nullptr(STR) try: - c_buf, buf = rffi.alloc_buffer_for_hlstr(count) - got = rffi.cast(lltype.Signed, os_read(fd, c_buf, count)) + raw_buf, gc_buf = rffi.alloc_buffer_for_hlstr(count) + void_buf = rffi.cast(rffi.VOIDP, raw_buf) + got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count)) if got < 0: raise OSError(rposix.get_errno(), "os_read failed") - return rffi.hlstr_from_buffer(buf, count, got) + return rffi.hlstr_from_buffer(raw_buf, gc_buf, count, got) finally: - rffi.keep_buffer_for_hlstr_alive_until_here(buf) + rffi.keep_buffer_for_hlstr_alive_until_here(raw_buf, gc_buf) def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) From fijal at codespeak.net Wed Apr 16 03:47:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Apr 2008 03:47:01 +0200 (CEST) Subject: [pypy-svn] r53816 - pypy/branch/io-improvements/pypy/interpreter Message-ID: <20080416014701.F2B6F498152@codespeak.net> Author: fijal Date: Wed Apr 16 03:46:59 2008 New Revision: 53816 Modified: pypy/branch/io-improvements/pypy/interpreter/pyframe.py pypy/branch/io-improvements/pypy/interpreter/pyopcode.py Log: Don't globally import rstack Modified: pypy/branch/io-improvements/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/io-improvements/pypy/interpreter/pyframe.py (original) +++ pypy/branch/io-improvements/pypy/interpreter/pyframe.py Wed Apr 16 03:46:59 2008 @@ -9,8 +9,6 @@ import opcode from pypy.rlib.objectmodel import we_are_translated, instantiate from pypy.rlib.jit import we_are_jitted, hint -from pypy.rlib import rstack # for resume points - # Define some opcodes used g = globals() @@ -102,6 +100,7 @@ def execute_frame(self): """Execute this frame. Main entry point to the interpreter.""" + from pypy.rlib import rstack executioncontext = self.space.getexecutioncontext() executioncontext.enter(self) try: Modified: pypy/branch/io-improvements/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/io-improvements/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/io-improvements/pypy/interpreter/pyopcode.py Wed Apr 16 03:46:59 2008 @@ -18,7 +18,6 @@ from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from pypy.tool.stdlib_opcode import unrolling_opcode_descs from pypy.tool.stdlib_opcode import opcode_method_names -from pypy.rlib import rstack # for resume points from pypy.rlib.unroll import unrolling_iterable def unaryoperation(operationname): @@ -70,6 +69,8 @@ def dispatch(self, pycode, next_instr, ec): # For the sequel, force 'next_instr' to be unsigned for performance + from pypy.rlib import rstack # for resume points + next_instr = r_uint(next_instr) co_code = pycode.co_code @@ -82,6 +83,8 @@ return self.popvalue() def handle_bytecode(self, co_code, next_instr, ec): + from pypy.rlib import rstack # for resume points + try: next_instr = self.dispatch_bytecode(co_code, next_instr, ec) rstack.resume_point("handle_bytecode", self, co_code, ec, @@ -203,6 +206,8 @@ return next_instr if we_are_translated(): + from pypy.rlib import rstack # for resume points + for opdesc in unrolling_opcode_descs: # static checks to skip this whole case if necessary if not opdesc.is_enabled(space): @@ -850,6 +855,8 @@ f.space.w_None) def call_function(f, oparg, w_star=None, w_starstar=None): + from pypy.rlib import rstack # for resume points + n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = None @@ -863,6 +870,8 @@ f.pushvalue(w_result) def CALL_FUNCTION(f, oparg, *ignored): + from pypy.rlib import rstack # for resume points + # XXX start of hack for performance if (oparg >> 8) & 0xff == 0: # Only positional arguments From fijal at codespeak.net Wed Apr 16 03:47:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Apr 2008 03:47:37 +0200 (CEST) Subject: [pypy-svn] r53817 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080416014737.2F533498152@codespeak.net> Author: fijal Date: Wed Apr 16 03:47:36 2008 New Revision: 53817 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Log: fix tests Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Wed Apr 16 03:47:36 2008 @@ -16,7 +16,8 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer from pypy.rpython.annlowlevel import llhelper, llstr, hlstr -from pypy.rpython.lltypesystem.rstr import STR, mallocstr +from pypy.rpython.lltypesystem.rstr import STR +from pypy.rlib.objectmodel import we_are_translated import os class UnhandledRPythonException(Exception): @@ -480,7 +481,6 @@ nonmovable. Must be followed by a free_nonmovingbuffer call. """ - from pypy.rpython.lltypesystem import rstr if rgc.can_move(data): count = len(data) buf = lltype.malloc(CCHARP.TO, count, flavor='raw') @@ -489,7 +489,7 @@ return buf else: data_start = cast_ptr_to_adr(llstr(data)) + \ - offsetof(rstr.STR, 'chars') + itemoffsetof(rstr.STR.chars, 0) + offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) return cast(CCHARP, data_start) # (str, char*) -> None @@ -503,28 +503,28 @@ keepalive_until_here(data) -str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - def alloc_buffer_for_hlstr(count): + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) gc_buf = rgc.malloc_nonmovable(STR, count) if gc_buf: realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset - raw_buf = cast(CCHARP.TO, realbuf) + raw_buf = cast(CCHARP, realbuf) return raw_buf, gc_buf else: raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') return raw_buf, lltype.nullptr(STR) def hlstr_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) if gc_buf: if allocated_size != needed_size: new_buf = lltype.nullptr(STR) try: - new_buf = mallocstr(needed_size) + new_buf = lltype.malloc(STR, needed_size) dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: This is bad, because dest could potentially move ## if there are threads involved. - raw_memcopy(raw_buf, dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(cast_ptr_to_adr(raw_buf), dest, sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) @@ -532,10 +532,10 @@ else: new_buf = lltype.nullptr(STR) try: - new_buf = mallocstr(needed_size) + new_buf = lltype.malloc(STR, needed_size) dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: see above - raw_memcopy(raw_buf, dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(cast_ptr_to_adr(raw_buf), dest, sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) From fijal at codespeak.net Wed Apr 16 03:49:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Apr 2008 03:49:00 +0200 (CEST) Subject: [pypy-svn] r53818 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080416014900.46FAA498152@codespeak.net> Author: fijal Date: Wed Apr 16 03:48:59 2008 New Revision: 53818 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Log: skip those guys on top of llvm Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Wed Apr 16 03:48:59 2008 @@ -702,6 +702,8 @@ def test_nonmovingbuffer(self): py.test.skip("Somewhat buggy...") + test_nonmoving_hlstr = test_nonmovingbuffer + def test_nonmovingbuffer_semispace(self): py.test.skip("LLVM backend error - unsupported operator") From fijal at codespeak.net Thu Apr 17 11:49:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Apr 2008 11:49:05 +0200 (CEST) Subject: [pypy-svn] r53830 - in pypy/branch/io-improvements/pypy/rpython: lltypesystem lltypesystem/test module Message-ID: <20080417094905.D6603169F9E@codespeak.net> Author: fijal Date: Thu Apr 17 11:49:05 2008 New Revision: 53830 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: A bit of renaming. hlstr is just an obscure helper. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Thu Apr 17 11:49:05 2008 @@ -503,7 +503,7 @@ keepalive_until_here(data) -def alloc_buffer_for_hlstr(count): +def alloc_buffer(count): str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) gc_buf = rgc.malloc_nonmovable(STR, count) if gc_buf: @@ -514,7 +514,7 @@ raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') return raw_buf, lltype.nullptr(STR) -def hlstr_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): +def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) if gc_buf: if allocated_size != needed_size: @@ -540,7 +540,7 @@ finally: keepalive_until_here(new_buf) -def keep_buffer_for_hlstr_alive_until_here(raw_buf, gc_buf): +def keep_buffer_alive_until_here(raw_buf, gc_buf): if gc_buf: keepalive_until_here(gc_buf) else: Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Thu Apr 17 11:49:05 2008 @@ -431,18 +431,18 @@ unregister_keepalive(pos, TP) assert res == 8 - def test_nonmoving_hlstr(self): + def test_nonmoving(self): d = 'non-moving data stuff' def f(): gc_buf = lltype.nullptr(STR) raw_buf = lltype.nullptr(CCHARP.TO) try: - raw_buf, gc_buf = alloc_buffer_for_hlstr(len(d)) + raw_buf, gc_buf = alloc_buffer(len(d)) for i in range(len(d)): raw_buf[i] = d[i] - return hlstr_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) + return str_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) finally: - keep_buffer_for_hlstr_alive_until_here(raw_buf, gc_buf) + keep_buffer_alive_until_here(raw_buf, gc_buf) fn = self.compile(f, [], gcpolicy='ref') assert fn() == d[:-1] @@ -702,7 +702,7 @@ def test_nonmovingbuffer(self): py.test.skip("Somewhat buggy...") - test_nonmoving_hlstr = test_nonmovingbuffer + test_nonmoving = test_nonmovingbuffer def test_nonmovingbuffer_semispace(self): py.test.skip("LLVM backend error - unsupported operator") Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Thu Apr 17 11:49:05 2008 @@ -490,14 +490,14 @@ raw_buf = lltype.nullptr(rffi.CCHARP.TO) gc_buf = lltype.nullptr(STR) try: - raw_buf, gc_buf = rffi.alloc_buffer_for_hlstr(count) + raw_buf, gc_buf = rffi.alloc_buffer(count) void_buf = rffi.cast(rffi.VOIDP, raw_buf) got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count)) if got < 0: raise OSError(rposix.get_errno(), "os_read failed") - return rffi.hlstr_from_buffer(raw_buf, gc_buf, count, got) + return rffi.str_from_buffer(raw_buf, gc_buf, count, got) finally: - rffi.keep_buffer_for_hlstr_alive_until_here(raw_buf, gc_buf) + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) From docgok at codespeak.net Thu Apr 17 17:44:58 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 17 Apr 2008 17:44:58 +0200 (CEST) Subject: [pypy-svn] r53840 - pypy/branch/io-improvements/pypy/translator/goal Message-ID: <20080417154458.E8D71169EC4@codespeak.net> Author: docgok Date: Thu Apr 17 17:44:56 2008 New Revision: 53840 Added: pypy/branch/io-improvements/pypy/translator/goal/targetsimpleread.py Log: Simple I/O test for os_read() benchmarking. Added: pypy/branch/io-improvements/pypy/translator/goal/targetsimpleread.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/translator/goal/targetsimpleread.py Thu Apr 17 17:44:56 2008 @@ -0,0 +1,29 @@ +import os + +def main(iterations=1): + source = os.open('/dev/zero', os.O_RDWR, 0777) + + for x in xrange(1024 * 1024 * iterations): + payload = os.read(source, 1024) + + os.close(source) + +def entry_point(argv): + if len(argv) > 1: + n = int(argv[1]) + else: + n = 1 + main(n) + return 0 + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None + +if __name__ == '__main__': + import sys + if len(sys.argv) >= 2: + main(iterations = int(sys.argv[1])) + else: + main() From docgok at codespeak.net Thu Apr 17 18:04:46 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 17 Apr 2008 18:04:46 +0200 (CEST) Subject: [pypy-svn] r53841 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080417160446.B14C7169F5B@codespeak.net> Author: docgok Date: Thu Apr 17 18:04:46 2008 New Revision: 53841 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Log: A little bit of documentation never killed anyone... Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Thu Apr 17 18:04:46 2008 @@ -502,8 +502,16 @@ else: keepalive_until_here(data) - +# int -> (char*, str) def alloc_buffer(count): + """ + Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. + The raw_buffer can be safely passed to a native function which expects it + to not move. Call str_from_buffer with the returned values to get a safe + high-level string. When the garbage collector cooperates, this allows for + the process to be performed without an extra copy. + Make sure to call keep_buffer_alive_until_here on the returned values. + """ str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) gc_buf = rgc.malloc_nonmovable(STR, count) if gc_buf: @@ -514,7 +522,13 @@ raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') return raw_buf, lltype.nullptr(STR) +# (char*, str, int, int) -> None def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): + """ + Converts from a pair returned by alloc_buffer to a high-level string. + The returned string will be truncated to needed_size. + """ + assert allocated_size >= needed_size str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) if gc_buf: if allocated_size != needed_size: @@ -539,11 +553,17 @@ return hlstr(new_buf) finally: keepalive_until_here(new_buf) - + +# (char*, str) -> None def keep_buffer_alive_until_here(raw_buf, gc_buf): + """ + Keeps buffers alive or frees temporary buffers created by alloc_buffer. + This must be called after a call to alloc_buffer, usually in a try/finally + block. + """ if gc_buf: keepalive_until_here(gc_buf) - else: + elif raw_buf: lltype.free(raw_buf, flavor='raw') # char* -> str, with an upper bound on the length in case there is no \x00 From docgok at codespeak.net Fri Apr 18 02:22:19 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Fri, 18 Apr 2008 02:22:19 +0200 (CEST) Subject: [pypy-svn] r53843 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080418002219.6EC9D2D8006@codespeak.net> Author: docgok Date: Fri Apr 18 02:22:18 2008 New Revision: 53843 Modified: pypy/branch/io-improvements/pypy/rlib/rsocket.py Log: Now uses nonmoving buffer stuff for sockets. Modified: pypy/branch/io-improvements/pypy/rlib/rsocket.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rsocket.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rsocket.py Fri Apr 18 02:22:18 2008 @@ -814,14 +814,13 @@ if timeout == 1: raise SocketTimeout elif timeout == 0: - buf = mallocbuf(buffersize) + raw_buf, gc_buf = rffi.alloc_buffer(buffersize) try: - read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags) + read_bytes = _c.socketrecv(self.fd, raw_buf, buffersize, flags) if read_bytes >= 0: - assert read_bytes <= buffersize - return ''.join([buf[i] for i in range(read_bytes)]) + return rffi.str_from_buffer(raw_buf, gc_buf, buffersize, read_bytes) finally: - lltype.free(buf, flavor='raw') + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) raise self.error_handler() def recvfrom(self, buffersize, flags=0): @@ -832,11 +831,11 @@ if timeout == 1: raise SocketTimeout elif timeout == 0: - buf = mallocbuf(buffersize) + raw_buf, gc_buf = rffi.alloc_buffer(buffersize) try: address, addr_p, addrlen_p = self._addrbuf() try: - read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags, + read_bytes = _c.recvfrom(self.fd, raw_buf, buffersize, flags, addr_p, addrlen_p) addrlen = rffi.cast(lltype.Signed, addrlen_p[0]) finally: @@ -847,10 +846,10 @@ address.addrlen = addrlen else: address = None - data = ''.join([buf[i] for i in range(read_bytes)]) + data = rffi.str_from_buffer(raw_buf, gc_buf, buffersize, read_bytes) return (data, address) finally: - lltype.free(buf, flavor='raw') + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) raise self.error_handler() def send_raw(self, dataptr, length, flags=0): From arigo at codespeak.net Fri Apr 18 14:11:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Apr 2008 14:11:08 +0200 (CEST) Subject: [pypy-svn] r53846 - in pypy/dist/pypy: lib/_ctypes lib/app_test/ctypes_tests module/_rawffi module/_rawffi/test Message-ID: <20080418121108.5A89516A047@codespeak.net> Author: arigo Date: Fri Apr 18 14:11:07 2008 New Revision: 53846 Modified: pypy/dist/pypy/lib/_ctypes/basics.py pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c pypy/dist/pypy/lib/app_test/ctypes_tests/test_values.py pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: A test to access non-primitive values via ctypes's 'in_dll' method. Fix (mostly by killing some code :-) Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Fri Apr 18 14:11:07 2008 @@ -76,10 +76,7 @@ return False def in_dll(self, dll, name): - buffer = dll._handle.getprimitive(self._ffishape, name) - val = self.__new__(self) - val._buffer = buffer - return val + return self.from_address(dll._handle.getaddressindll(name)) class CArgObject(object): """ simple wrapper around buffer, just for the case of freeing Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c Fri Apr 18 14:11:07 2008 @@ -243,6 +243,13 @@ return an_integer; } +EXPORT(char) a_string[16] = "0123456789abcdef"; + +EXPORT(int) get_a_string_char(int index) +{ + return a_string[index]; +} + EXPORT(double) integrate(double a, double b, double (*f)(double), long nstep) { Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_values.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/test_values.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/test_values.py Fri Apr 18 14:11:07 2008 @@ -20,6 +20,12 @@ an_integer.value *= 2 assert x*2 == ctdll.get_an_integer() + def test_a_string(self): + a_string = (c_char * 16).in_dll(ctdll, "a_string") + assert a_string.raw == "0123456789abcdef" + a_string[15] = '$' + assert ctdll.get_a_string_char(15) == ord('$') + def test_undefined(self): raises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Fri Apr 18 14:11:07 2008 @@ -178,18 +178,15 @@ "No symbol %s found in library %s" % (name, self.name))) ptr.unwrap_spec = ['self', ObjSpace, str, W_Root, W_Root] - def getprimitive(self, space, letter, name): - from pypy.module._rawffi.array import get_array_cache - cache = get_array_cache(space) - w_array = cache.get_array_type(letter2tp(space, letter)) + def getaddressindll(self, space, name): try: address_as_uint = rffi.cast(lltype.Unsigned, self.cdll.getaddressindll(name)) except KeyError: raise OperationError(space.w_ValueError, space.wrap("Cannot find symbol %s" % (name,))) - return w_array.fromaddress(space, address_as_uint, 1) - getprimitive.unwrap_spec = ['self', ObjSpace, str, str] + return space.wrap(address_as_uint) + getaddressindll.unwrap_spec = ['self', ObjSpace, str] def descr_new_cdll(space, w_type, name): try: @@ -202,7 +199,7 @@ 'CDLL', __new__ = interp2app(descr_new_cdll), ptr = interp2app(W_CDLL.ptr), - getprimitive= interp2app(W_CDLL.getprimitive), + getaddressindll = interp2app(W_CDLL.getaddressindll), __doc__ = """ C Dynamically loaded library use CDLL(libname) to create a handle to a C library (the argument is processed the same way as dlopen processes it). On such a library you can call: Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Fri Apr 18 14:11:07 2008 @@ -636,15 +636,18 @@ assert a[0] == maxptr - 1 a.free() - def test_getprimitive(self): + def test_getaddressindll(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) - a = lib.getprimitive("l", "static_int") + def getprimitive(typecode, name): + addr = lib.getaddressindll(name) + return _rawffi.Array(typecode).fromaddress(addr, 1) + a = getprimitive("l", "static_int") assert a[0] == 42 - a = lib.getprimitive("d", "static_double") + a = getprimitive("d", "static_double") assert a[0] == 42.42 - raises(ValueError, lib.getprimitive, 'z', 'ddddddd') - raises(ValueError, lib.getprimitive, 'zzz', 'static_int') + raises(ValueError, getprimitive, 'z', 'ddddddd') + raises(ValueError, getprimitive, 'zzz', 'static_int') def test_segfault_exception(self): import _rawffi From antocuni at codespeak.net Fri Apr 18 18:30:04 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Apr 2008 18:30:04 +0200 (CEST) Subject: [pypy-svn] r53862 - in pypy/branch/jit-hotpath/pypy/jit: codegen rainbow rainbow/test timeshifter Message-ID: <20080418163004.EE3B24981CC@codespeak.net> Author: antocuni Date: Fri Apr 18 18:30:00 2008 New Revision: 53862 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/model.py pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Log: implement oosend of external methods to red variables, e.g. all the methods of ootype.String. This let test_green_char_at_merge pass. Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/model.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/model.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/model.py Fri Apr 18 18:30:00 2008 @@ -88,6 +88,7 @@ ## def genop_malloc_fixedsize(self, alloctoken): ## def genop_malloc_varsize(self, varsizealloctoken, gv_size): ## def genop_call(self, sigtoken, gv_fnptr, args_gv): +## def genop_oosend(self, methtoken, gv_self, args_gv): ## def genop_same_as(self, gv_x): ## def genop_debug_pdb(self): # may take an args_gv later ## def genop_cast_int_to_ptr(self, kind, gv_int) @@ -475,6 +476,9 @@ def genop_call(self, sigtoken, gv_fnptr, args_gv): return dummy_var + def genop_oosend(self, methtoken, gv_obj, args_gv): + return dummy_var + def genop_same_as(self, gv_x): return dummy_var Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Fri Apr 18 18:30:00 2008 @@ -166,6 +166,14 @@ self.calldesc = CallDesc(codewriter.RGenOp, codewriter.exceptiondesc, lltype.typeOf(fnptr), colororder) +class MethodDesc(object): + + def __init__(self, RGenOp, SELFTYPE, methname): + _, meth = SELFTYPE._lookup(methname) + METH = ootype.typeOf(meth) + self.methtoken = RGenOp.methToken(SELFTYPE, methname) + self.redboxbuilder = rvalue.ll_redboxbuilder(METH.RESULT) + class BytecodeWriter(object): @@ -236,6 +244,7 @@ self.indirectcalldescs = [] self.metacalldescs = [] self.strings = [] + self.methdescs = [] self.is_portal = is_portal # mapping constant -> index in constants self.const_positions = {} @@ -275,6 +284,8 @@ self.indirectcalldesc_positions = {} # mapping string to index self.string_positions = {} + # mapping methdesc to index + self.methdesc_positions = {} self.graph = graph self.mergepoint_set = {} @@ -306,6 +317,7 @@ self.sharelist("metacalldescs"), self.sharelist("indirectcalldescs"), self.sharelist("strings"), + self.sharelist("methdescs"), self.is_portal, owncalldesc, gv_ownfnptr) @@ -835,6 +847,16 @@ self.string_positions[s] = result return result + def methdesc_position(self, TYPE, name): + key = (TYPE, name) + if key in self.methdesc_positions: + return self.methdesc_positions[tok] + result = len(self.methdescs) + desc = MethodDesc(self.RGenOp, TYPE, name) + self.methdescs.append(desc) + self.methdesc_positions[key] = result + return result + def interiordesc(self, op, PTRTYPE, nb_offsets): path = [] CONTAINER = PTRTYPE.TO @@ -1649,9 +1671,11 @@ name = op.args[0].value opargs = op.args[1:] SELFTYPE = opargs[0].concretetype + has_result = (self.varcolor(op.result) != "gray" and + op.result.concretetype != lltype.Void) + if SELFTYPE.oopspec_name is not None: # we are calling a method like List.ll_getitem or so - hasresult = op.result.concretetype != lltype.Void _, meth = SELFTYPE._lookup(name) oopspecdescindex = self.oopspecdesc_position('send', meth, withexc) oopspecdesc = self.oopspecdescs[oopspecdescindex] @@ -1664,43 +1688,47 @@ hs_self = self.hannotator.binding(opargs[0]) deepfrozen = hs_self.deepfrozen - self.emit("red_oopspec_call%s_%s" % ("_noresult" * (not hasresult), + self.emit("red_oopspec_call%s_%s" % ("_noresult" * (not has_result), len(args))) self.emit(oopspecdescindex) self.emit(deepfrozen) self.emit(*args) return - # normal oosend - # XXX: share code with serialize_op_indirect_call - has_result = (self.varcolor(op.result) != "gray" and - op.result.concretetype != lltype.Void) + # real oosend, either red or const assert not self.hannotator.policy.hotpath - emitted_args = [] - for v in op.args[1:]: - if v.concretetype == lltype.Void: - continue - emitted_args.append(self.serialize_oparg("red", v)) + if kind == "residual": + # oosend to an external method (e.g. ootype.String.*) + emitted_args = [] + for v in op.args[1:]: + if v.concretetype == lltype.Void: + continue + emitted_args.append(self.serialize_oparg("red", v)) + self.emit("external_oosend") + self.emit(len(emitted_args)) + self.emit(*emitted_args) + methdescindex = self.methdesc_position(SELFTYPE, name) + self.emit(methdescindex) + self.emit(has_result) + else: + # normal oosend + graph2tsgraph = dict(self.graphs_from(op)) + self.fill_methodcodes(SELFTYPE, name, graph2tsgraph) + args = graph2tsgraph.values()[0].getargs() + emitted_args = self.args_of_call(op.args[1:], args) + self.emit("red_oosend") + self.emit(*emitted_args) + methnameindex = self.string_position(name) + self.emit(methnameindex) if has_result: self.register_redvar(op.result) - graph2tsgraph = dict(self.graphs_from(op)) - #type2graph = self.collect_graphs_and_types(op, graph2tsgraph) - self.fill_methodcodes(SELFTYPE, name, graph2tsgraph) - args = graph2tsgraph.values()[0].getargs() - emitted_args = self.args_of_call(op.args[1:], args) - self.emit("red_oosend") - self.emit(*emitted_args) - #setdescindex = self.oosenddesc_position(type2graph) - #self.emit(setdescindex) - methnameindex = self.string_position(name) - self.emit(methnameindex) if kind == "yellow": self.emit("yellow_retrieve_result_as_red") self.emit(self.type_position(op.result.concretetype)) - elif kind in ("gray", "red"): + elif kind in ("gray", "red", "residual"): pass else: assert 0, "unknown call kind %s" % (kind, ) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Fri Apr 18 18:30:00 2008 @@ -38,8 +38,8 @@ interiordescs, exceptioninstances, oopspecdescs, promotiondescs, called_bytecodes, num_mergepoints, graph_color, calldescs, metacalldescs, - indirectcalldescs, strings, is_portal, owncalldesc, - gv_ownfnptr): + indirectcalldescs, strings, methdescs, is_portal, + owncalldesc, gv_ownfnptr): # XXX quite a lot of lists of descs here... At least we # share identical lists between the numberous prebuilt # JitCode instances. @@ -63,6 +63,7 @@ self.metacalldescs = metacalldescs self.indirectcalldescs = indirectcalldescs self.strings = strings + self.methdescs = methdescs self.is_portal = is_portal self.owncalldesc = owncalldesc self.gv_ownfnptr = gv_ownfnptr @@ -172,6 +173,10 @@ index = self.load_int() string = self.getjitcode().strings[index] args += (string, ) + elif argspec == "methdesc": + index = self.load_int() + tok = self.getjitcode().methdescs[index] + args += (tok, ) elif argspec == "oopspec": oopspecindex = self.load_int() oopspec = self.getjitcode().oopspecdescs[oopspecindex] @@ -661,15 +666,6 @@ self.run(self.jitstate, bytecode, greenargs, redargs, start_bytecode_loop=False) - @arguments("green_varargs", "red_varargs", "string") - def opimpl_red_oosend(self, greenargs, redargs, methname): - selfbox = redargs[0] - vstruct = selfbox.content - assert isinstance(vstruct, rcontainer.VirtualStruct), 'TODO???' - bytecode = vstruct.typedesc.methodcodes[methname] - self.run(self.jitstate, bytecode, greenargs, redargs, - start_bytecode_loop=False) - @arguments(returns="green") def opimpl_yellow_retrieve_result(self): # XXX all this jitstate.greens business is a bit messy @@ -1088,6 +1084,21 @@ return rtimeshift.genptreq(self.jitstate, ptrbox1, ptrbox2, False) + @arguments("green_varargs", "red_varargs", "string") + def opimpl_red_oosend(self, greenargs, redargs, methname): + selfbox = redargs[0] + vstruct = selfbox.content + assert isinstance(vstruct, rcontainer.VirtualStruct), 'TODO???' + bytecode = vstruct.typedesc.methodcodes[methname] + self.run(self.jitstate, bytecode, greenargs, redargs, + start_bytecode_loop=False) + + @arguments("red_varargs", "methdesc", "bool") + def opimpl_external_oosend(self, redargs, methdesc, has_result): + result = rtimeshift.gen_external_oosend(self.jitstate, redargs, + methdesc) + if has_result: + self.red_result(result) class DebugTrace(object): def __init__(self, *args): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Fri Apr 18 18:30:00 2008 @@ -2341,4 +2341,3 @@ test_red_varsized_struct = _skip test_array_of_voids = _skip test_compile_time_const_tuple = _skip # needs vdict - test_green_char_at_merge = _skip Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Fri Apr 18 18:30:00 2008 @@ -902,7 +902,8 @@ self.ownbox.setgenvar_hint(gv, known_nonzero=True) self.ownbox.content = None return - debug_print(lltype.Void, "FORCE CONTAINER: "+ typedesc.TYPE._name) + name = getattr(typedesc.TYPE, '_name', str(typedesc.TYPE)) + debug_print(lltype.Void, "FORCE CONTAINER: "+ name) #debug_pdb(lltype.Void) genvar = jitstate.ts.genop_malloc_fixedsize(builder, typedesc.alloctoken) # force the box pointing to this VirtualStruct Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py Fri Apr 18 18:30:00 2008 @@ -595,6 +595,14 @@ ##def ll_gvar_from_constant(jitstate, ll_value): ## return jitstate.curbuilder.rgenop.genconst(ll_value) +def gen_external_oosend(jitstate, argboxes, methdesc): + builder = jitstate.curbuilder + selfbox = argboxes[0] + gv_selfbox = selfbox.getgenvar(jitstate) + args_gv = [argbox.getgenvar(jitstate) for argbox in argboxes[1:]] + jitstate.prepare_for_residual_call() # XXX? + gv_result = builder.genop_oosend(methdesc.methtoken, gv_selfbox, args_gv) + return methdesc.redboxbuilder(gv_result) def gen_residual_call(jitstate, calldesc, funcbox, argboxes): builder = jitstate.curbuilder From antocuni at codespeak.net Fri Apr 18 18:38:31 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Apr 2008 18:38:31 +0200 (CEST) Subject: [pypy-svn] r53863 - pypy/dist/pypy/jit/hintannotator Message-ID: <20080418163831.44F13169FDB@codespeak.net> Author: antocuni Date: Fri Apr 18 18:38:28 2008 New Revision: 53863 Modified: pypy/dist/pypy/jit/hintannotator/annotator.py Log: simplify consider_op_new and implement consider_op_oonewarray Modified: pypy/dist/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/annotator.py Fri Apr 18 18:38:28 2008 @@ -31,12 +31,13 @@ def consider_op_new(self, hs_TYPE): TYPE = hs_TYPE.const - if self.policy.novirtualcontainer: - return hintmodel.SomeLLAbstractVariable(TYPE) - else: - # XXX: ootype - vstructdef = self.bookkeeper.getvirtualcontainerdef(TYPE) - return hintmodel.SomeLLAbstractContainer(vstructdef) + assert self.policy.novirtualcontainer, 'not supported by ootype' + return hintmodel.SomeLLAbstractVariable(TYPE) + + def consider_op_oonewarray(self, hs_TYPE, hs_size): + TYPE = hs_TYPE.const + assert self.policy.novirtualcontainer, 'not supported by ootype' + return hintmodel.SomeLLAbstractVariable(TYPE) def consider_op_malloc(self, hs_TYPE, hs_flags): TYPE = hs_TYPE.const From antocuni at codespeak.net Sat Apr 19 15:43:08 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 19 Apr 2008 15:43:08 +0200 (CEST) Subject: [pypy-svn] r53870 - in pypy/branch/jit-hotpath/pypy: jit/rainbow jit/rainbow/test jit/timeshifter rpython/ootypesystem Message-ID: <20080419134308.9ABF71684EA@codespeak.net> Author: antocuni Date: Sat Apr 19 15:43:06 2008 New Revision: 53870 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/vdict.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Log: add support for vdicts to ootype. test_vdict passes Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Sat Apr 19 15:43:06 2008 @@ -1085,23 +1085,25 @@ self.emit(label(("after indirect call", op))) - - def handle_oopspec_call(self, op, withexc): + def serialize_argtuple(self, opargs, argtuple): from pypy.jit.timeshifter.oop import Index - fnobj = get_funcobj(op.args[0].value) - oopspecdescindex = self.oopspecdesc_position('call', fnobj, withexc) - oopspecdesc = self.oopspecdescs[oopspecdescindex] - opargs = op.args[1:] args_v = [] args = [] - for obj in oopspecdesc.argtuple: + for obj in argtuple: if isinstance(obj, Index): v = opargs[obj.n] else: v = flowmodel.Constant(obj, lltype.typeOf(obj)) args_v.append(v) args.append(self.serialize_oparg("red", v)) + return args, args_v + def handle_oopspec_call(self, op, withexc): + fnobj = get_funcobj(op.args[0].value) + oopspecdescindex = self.oopspecdesc_position('call', fnobj, withexc) + oopspecdesc = self.oopspecdescs[oopspecdescindex] + opargs = op.args[1:] + args, args_v = self.serialize_argtuple(opargs, oopspecdesc.argtuple) if oopspecdesc.is_method: hs_self = self.hannotator.binding( opargs[oopspecdesc.argtuple[0].n]) @@ -1650,12 +1652,12 @@ # XXX: works only for List oopspecdescindex = self.oopspecdesc_position('new', TYPE, False) oopspecdesc = self.oopspecdescs[oopspecdescindex] + args, args_v = self.serialize_argtuple([], oopspecdesc.argtuple) deepfrozen = False - index = self.serialize_oparg("red", flowmodel.Constant(0, lltype.Signed)) - self.emit('red_oopspec_call_1') + self.emit('red_oopspec_call_%s' % len(args)) self.emit(oopspecdescindex) self.emit(deepfrozen) - self.emit(index) + self.emit(*args) self.register_redvar(op.result) return @@ -1693,6 +1695,8 @@ self.emit(oopspecdescindex) self.emit(deepfrozen) self.emit(*args) + if has_result: + self.register_redvar(op.result) return # real oosend, either red or const Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py Sat Apr 19 15:43:06 2008 @@ -4,7 +4,7 @@ from pypy.rlib.jit import hint -class TestVDict(InterpretationTest): +class VDictTest(InterpretationTest): type_system = "lltype" def test_vdict(self): @@ -73,3 +73,10 @@ res = self.interpret(ll_function, [3, 2], [0, 1], policy=P_OOPSPEC) assert res == 54 self.check_insns({}) + + +class TestOOType(VDictTest): + type_system = "ootype" + +class TestLLType(VDictTest): + type_system = "lltype" Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py Sat Apr 19 15:43:06 2008 @@ -163,6 +163,18 @@ def __repr__(self): return '<%s(%s)>' % (self.__class__.__name__, self.method) +def parse_oopspec(oopspec, argnames): + # parse the oopspec and fill in the arguments + operation_name, args = oopspec.split('(', 1) + assert args.endswith(')') + args = args[:-1] + ',' # trailing comma to force tuple syntax + if args.strip() == ',': + args = '()' + nb_args = len(argnames) + argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)])) + argtuple = eval(args, argname2index) + return operation_name, argtuple + class CallOopSpecDesc(AbstractOopSpecDesc): def _setup_oopdesc(self, RGenOp, fnobj): @@ -172,16 +184,9 @@ ll_func = fnobj._callable nb_args = len(FUNCTYPE.ARGS) - # parse the oopspec and fill in the arguments - operation_name, args = ll_func.oopspec.split('(', 1) - assert args.endswith(')') - args = args[:-1] + ',' # trailing comma to force tuple syntax - if args.strip() == ',': - args = '()' argnames = ll_func.func_code.co_varnames[:nb_args] - argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)])) - self.argtuple = eval(args, argname2index) - # end of rather XXX'edly hackish parsing + operation_name, argtuple = parse_oopspec(ll_func.oopspec, argnames) + self.argtuple = argtuple self.OOPARGTYPES = [] arg_llsig_to_oopsig = {} @@ -245,6 +250,9 @@ self.typename = TYPE.oopspec_name self.method = 'oop_new%s' % self.typename self.is_method = False + opname, argtuple = parse_oopspec(TYPE.oopspec_new, []) + assert opname == 'new' + self.argtuple = argtuple def allocate(): return ootype.new(TYPE) @@ -262,7 +270,7 @@ METH = ootype.typeOf(meth) assert METH.SELFTYPE is not None, 'fix ootype' self.SELFTYPE = METH.SELFTYPE - self.ARGS = METH.ARGS + self.ARGS = [METH.SELFTYPE] + list(METH.ARGS) self.RESULT = METH.RESULT # we assume the number and position of the arguments are the @@ -312,8 +320,15 @@ exc_data_ptr = exceptiondesc.exc_data_ptr assert exceptiondesc.rtyper is not None llinterp = LLInterpreter(exceptiondesc.rtyper, exc_data_ptr=exc_data_ptr) - def on_top_of_llinterp(*args): - return llinterp.eval_graph(get_funcobj(fnptr).graph, list(args)) + funcobj = get_funcobj(fnptr) + if hasattr(funcobj, 'graph'): + def on_top_of_llinterp(*args): + return llinterp.eval_graph(funcobj.graph, list(args)) + else: + assert isinstance(fnptr, ootype._meth) + assert hasattr(fnptr, '_callable') + def on_top_of_llinterp(*args): + return fnptr._callable(*args) return on_top_of_llinterp class Entry(ExtRegistryEntry): Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/vdict.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/vdict.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/vdict.py Sat Apr 19 15:43:06 2008 @@ -1,6 +1,7 @@ import operator from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import rdict +from pypy.rpython.ootypesystem import ootype from pypy.jit.timeshifter.rcontainer import VirtualContainer, FrozenContainer from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, oop @@ -8,10 +9,16 @@ HASH = lltype.Signed +def TypeDesc(RGenOp, rtyper, exceptiondesc, DICT): + if rtyper.type_system.name == 'lltypesystem': + return LLTypeDictTypeDesc(RGenOp, rtyper, exceptiondesc, DICT) + else: + return OOTypeDictTypeDesc(RGenOp, rtyper, exceptiondesc, DICT) + + # XXXXXXXXXX! ARGH. # cannot use a dictionary as the item_boxes at all, because of order issues - class LLEqDesc(object): __metaclass__ = cachedtype @@ -101,37 +108,17 @@ VirtualDict.FrozenVirtualDict = FrozenVirtualDict -class DictTypeDesc(object): +class AbstractDictTypeDesc(object): __metaclass__ = cachedtype def __init__(self, RGenOp, rtyper, exceptiondesc, DICT): - bk = rtyper.annotator.bookkeeper self.DICT = DICT - self.DICTPTR = lltype.Ptr(DICT) + self.DICTPTR = self.Ptr(DICT) self.ptrkind = RGenOp.kindToken(self.DICTPTR) - argtypes = [bk.immutablevalue(DICT)] - ll_newdict_ptr = rtyper.annotate_helper_fn(rdict.ll_newdict, - argtypes) - self.gv_ll_newdict = RGenOp.constPrebuiltGlobal(ll_newdict_ptr) - self.tok_ll_newdict = RGenOp.sigToken(lltype.typeOf(ll_newdict_ptr).TO) + self._setup(RGenOp, rtyper, DICT) - argtypes = [self.DICTPTR, DICT.KEY, DICT.VALUE, HASH] - ll_insertclean = rtyper.annotate_helper_fn(rdict.ll_dict_insertclean, - argtypes) - self.gv_ll_insertclean = RGenOp.constPrebuiltGlobal(ll_insertclean) - self.tok_ll_insertclean = RGenOp.sigToken( - lltype.typeOf(ll_insertclean).TO) - - # XXX some fishing that only works if the DICT does not come from - # an r_dict - if DICT.keyeq is None: - keyeq = operator.eq - else: - assert isinstance(DICT.keyeq, lltype.staticAdtMethod) - keyeq = DICT.keyeq.__get__(42) - assert isinstance(DICT.keyhash, lltype.staticAdtMethod) - keyhash = DICT.keyhash.__get__(42) + keyeq, keyhash = self._get_eq_hash(DICT) keydesc = LLEqDesc(DICT.KEY, keyeq, keyhash) self.VirtualDict = keydesc.VirtualDict @@ -142,7 +129,7 @@ def factory(self): vdict = self.VirtualDict(self) - box = rvalue.PtrRedBox(known_nonzero=True) + box = self.PtrRedBox(known_nonzero=True) box.content = vdict vdict.ownbox = box return box @@ -165,9 +152,70 @@ self.allocate = allocate self.perform_setitem = perform_setitem -TypeDesc = DictTypeDesc + +class LLTypeDictTypeDesc(AbstractDictTypeDesc): + + Ptr = staticmethod(lltype.Ptr) + PtrRedBox = rvalue.PtrRedBox + + def _setup(self, RGenOp, rtyper, DICT): + bk = rtyper.annotator.bookkeeper + argtypes = [bk.immutablevalue(DICT)] + ll_newdict_ptr = rtyper.annotate_helper_fn(rdict.ll_newdict, + argtypes) + self.gv_ll_newdict = RGenOp.constPrebuiltGlobal(ll_newdict_ptr) + self.tok_ll_newdict = RGenOp.sigToken(lltype.typeOf(ll_newdict_ptr).TO) + + argtypes = [self.DICTPTR, DICT.KEY, DICT.VALUE, HASH] + ll_insertclean = rtyper.annotate_helper_fn(rdict.ll_dict_insertclean, + argtypes) + self.gv_ll_insertclean = RGenOp.constPrebuiltGlobal(ll_insertclean) + self.tok_ll_insertclean = RGenOp.sigToken( + lltype.typeOf(ll_insertclean).TO) + + def _get_eq_hash(self, DICT): + # XXX some fishing that only works if the DICT does not come from + # an r_dict + if DICT.keyeq is None: + keyeq = operator.eq + else: + assert isinstance(DICT.keyeq, lltype.staticAdtMethod) + keyeq = DICT.keyeq.__get__(42) + assert isinstance(DICT.keyhash, lltype.staticAdtMethod) + keyhash = DICT.keyhash.__get__(42) + return keyeq, keyhash + + def gen_newdict(self, builder, args_gv): + return builder.genop_call(self.tok_ll_newdict, + self.gv_ll_newdict, + args_gv) + + def gen_insertclean(self, builder, args_gv): + return builder.genop_call(typedesc.tok_ll_insertclean, + typedesc.gv_ll_insertclean, + args_gv) + +class OOTypeDictTypeDesc(AbstractDictTypeDesc): + + Ptr = staticmethod(lambda T: T) + PtrRedBox = rvalue.InstanceRedBox + + def _setup(self, RGenOp, rtyper, DICT): + assert not isinstance(DICT, ootype.CustomDict), 'TODO' + self.alloctoken = RGenOp.allocToken(DICT) + self.tok_ll_set = RGenOp.methToken(DICT, 'll_set') + + def _get_eq_hash(self, DICT): + return operator.eq, hash + + def gen_newdict(self, builder, args_gv): + XXX + + def gen_insertclean(self, builder, args_gv): + XXX + class AbstractFrozenVirtualDict(FrozenContainer): _attrs_ = ('typedesc',) @@ -232,18 +280,14 @@ items = self.getitems_and_makeempty(builder.rgenop) args_gv = [] - gv_dict = builder.genop_call(typedesc.tok_ll_newdict, - typedesc.gv_ll_newdict, - args_gv) + gv_dict = typedesc.gen_newdict(builder, args_gv) self.ownbox.setgenvar_hint(gv_dict, known_nonzero=True) self.ownbox.content = None for gv_key, valuebox, hash in items: gv_hash = builder.rgenop.genconst(hash) gv_value = valuebox.getgenvar(jitstate) args_gv = [gv_dict, gv_key, gv_value, gv_hash] - builder.genop_call(typedesc.tok_ll_insertclean, - typedesc.gv_ll_insertclean, - args_gv) + typedesc.gen_insertclean(builder, args_gv) def freeze(self, memo): contmemo = memo.containers @@ -333,3 +377,7 @@ return oopspecdesc.residual_call(jitstate, [selfbox, keybox], deepfrozen=deepfrozen) oop_dict_contains.couldfold = True + +oop_dict_method_set = oop_dict_setitem +oop_dict_method_get = oop_dict_getitem +oop_dict_method_contains = oop_dict_contains Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py Sat Apr 19 15:43:06 2008 @@ -489,6 +489,7 @@ SELFTYPE_T = object() ITEMTYPE_T = object() oopspec_name = 'list' + oopspec_new = 'new(0)' def __init__(self, ITEMTYPE=None): self._ITEMTYPE = ITEMTYPE @@ -578,6 +579,7 @@ KEYTYPE_T = object() VALUETYPE_T = object() oopspec_name = 'dict' + oopspec_new = 'new()' def __init__(self, KEYTYPE=None, VALUETYPE=None): self._KEYTYPE = KEYTYPE @@ -1446,6 +1448,7 @@ assert key in self._dict assert key == self._last_key return self._dict[key] + ll_get.oopargcheck = lambda d, key: bool(d) def ll_set(self, key, value): # NOT_RPYTHON @@ -1469,6 +1472,7 @@ assert typeOf(key) == self._TYPE._KEYTYPE self._last_key = key return key in self._dict + ll_contains.oopargcheck = lambda d, key: bool(d) def ll_clear(self): self._dict.clear() From fijal at codespeak.net Sun Apr 20 10:15:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Apr 2008 10:15:42 +0200 (CEST) Subject: [pypy-svn] r53898 - pypy/dist/pypy/doc Message-ID: <20080420081542.C83101683F3@codespeak.net> Author: fijal Date: Sun Apr 20 10:15:40 2008 New Revision: 53898 Added: pypy/dist/pypy/doc/extending.txt (contents, props changed) Log: Document that was laying down in my wc forever. Added: pypy/dist/pypy/doc/extending.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/extending.txt Sun Apr 20 10:15:40 2008 @@ -0,0 +1,105 @@ + +Writing extension modules for pypy +=================================== + +This document tries to explain how to interface the PyPy python interpreter +with any external library. + +Note: We try to describe state-of-the art, but it +might fade out of date as this is the front on which things are changing +in pypy rapidly. + +Possibilities +============= + +Right now, there are three posibilities of providing third-party modules +for the PyPy python interpreter (in order of usefulnes): + +* Write them in pure python and use ctypes, see ctypes_ + section + +* Write them in pure python and use direct libffi low-level bindings, See + \_rawffi_ module description. + +* Write them in RPython as mixedmodule_, using *rffi* as bindings. + +.. _ctypes: #CTypes +.. _\_rawffi: #LibFFI +.. _mixedmodule: #Mixed Modules + +CTypes +====== + +The ctypes module in PyPy is ready to use. +It's goal is to be as-compatible-as-possible with the +`CPython ctypes`_ version. Right now it's able to support large examples, +such as pyglet. PyPy is planning to have a 100% compatible ctypes +implementation, without the CPython C-level API bindings (so it is very +unlikely that direct object-manipulation trickery through this API will work). + +We also provide a `ctypes-configure`_ for overcoming the platform dependencies, +not relying on the ctypes codegen. This tool works by querying gcc about +platform-depenent details (compiling small snippets of C code and running +them), so it'll benefit not pypy-related ctypes-based modules as well. + +.. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html + +Pros +---- + +Stable, CPython-compatible API + +Cons +---- + +Only pure-python code (slow), problems with platform-dependency (although +we partially solve those). PyPy implementation is now very slow. + +_`CPython ctypes`: XXX link + +LibFFI +====== + +Mostly in order to be able to write a ctypes module, we developed a very +low-level libffi_ bindings. (libffi is a C-level library for dynamic calling, +which is used by CPython ctypes). This library provides stable and usable API, +although it's API is a very low-level one. It does not contain any +magic. + +Pros +---- + +Works. Combines disadvantages of using ctypes with disadvantages of +using mixed modules. Probably more suitable for a delicate code +where ctypes magic goes in a way. + +Cons +---- + +Slow. CPython-incompatible API, very rough and low-level + +.. _libffi: XXX link + +Mixed Modules +============= + +This is the most advanced and powerful way of writing extension modules. +It has some serious disadvantages: + +* a mixed module needs to be written in RPython, which is far more + complicated than Python (XXX link) + +* due to lack of separate compilation (as of April 2008), each + compilation-check requires to recompile whole PyPy python interpreter, + which takes 0.5-1h. We plan to solve this at some point in near future. + +* although rpython is a garabage-collected language, the border between + C and RPython needs to be managed by hand (each object that goes into the + C level must be explicitely freed) XXX we try to solve this + +Some document is available `here`_ + +.. _`here`:: rffi.html + +XXX we should provide detailed docs about lltype and rffi, especially if we + want people to follow that way. From fijal at codespeak.net Sun Apr 20 10:16:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Apr 2008 10:16:56 +0200 (CEST) Subject: [pypy-svn] r53899 - pypy/dist/pypy/doc/discussion Message-ID: <20080420081656.62D18169E09@codespeak.net> Author: fijal Date: Sun Apr 20 10:16:55 2008 New Revision: 53899 Added: pypy/dist/pypy/doc/discussion/gc.txt (contents, props changed) Log: first attempt to document new experimental gc features Added: pypy/dist/pypy/doc/discussion/gc.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/gc.txt Sun Apr 20 10:16:55 2008 @@ -0,0 +1,77 @@ + +*Note: this things are experimental and are being implemented on the +`io-improvements`_ branch* + +.. _`io-improvements`: http://codespeak.net/svn/pypy/branch/io-improvements + +============= +GC operations +============= + +This document tries to gather gc-related issues which are very recent +or in-developement. Also, it tries to document needed gc refactorings +and expected performance of certain gc-related operations. + +Problem area +============ + +Since some of our gcs are moving, we at some point decided to simplify +the issue of having care of it by always copying the contents of +data that goes to C level. This yields a performance penalty, also +because some gcs does not move data around anyway. + +So we decided to introduce new operations which will simplify issues +regarding this. + +Pure gc operations +================== + +(All available from rlib.rgc) + +* can_move(p) - returns a flag telling whether pointer p will move. + useful for example when you want to know whether memcopy is safe. + +* malloc_nonmovable(TP, n=None) - tries to allocate non-moving object. + if it succeeds, it return an object, otherwise (for whatever reasons) + returns null pointer. Does not raise! (never) + +Usage patterns +============== + +Usually those functions are used via helpers located in rffi. For things like +os.write - first get_nonmovingbuffer(data) that will give you a pointer +suitable of passing to C and finally free_nonmovingbuffer. + +For os.read like usage - you first call alloc_buffer (that will allocate a +buffer of desired size passable to C) and afterwards create str_from_buffer, +finally calling keep_buffer_alive_until_here. + +String builder +============== + +In Python strings are immutable by design. In RPython this still yields true, +but since we cooperate with lower (C/POSIX) level, which has no notion of +strings, we use buffers. Typical use case is to use list of characters l and +than ''.join(l) in order to get string. This requires a lot of unnecessary +copying, which yields performance penalty for such operations as string +formatting. Hence the idea of string builder. String builder would be an +object to which you can append strings or characters and afterwards build it +to a string. Ideally, this set of operations would not contain any copying +whatsoever. + +Low level gc operations for string builder +------------------------------------------ + +* alloc_buffer(T, size) - allocates Array(nolength=True) with possibility + of later becoming of shape T + +* realloc_buffer(buf, newsize) - tries to shrink or enlarge buffer buf. Returns + new pointer (since it might involve copying) + +* build_buffer(T, buf) - creates a type T (previously passed to alloc_buffer) + from buffer. + +Depending on a gc, those might be implemented dumb (realloc always copies) +or using C-level realloc. Might be implemented also in whatever clever way +comes to mind. + From cami at codespeak.net Sun Apr 20 10:31:10 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 20 Apr 2008 10:31:10 +0200 (CEST) Subject: [pypy-svn] r53900 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080420083110.C5D62169E11@codespeak.net> Author: cami Date: Sun Apr 20 10:31:08 2008 New Revision: 53900 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Log: introducing cartride classe which merges some functions from cartridgeStoreDriver and CartridgeFactory Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun Apr 20 10:31:08 2008 @@ -2,7 +2,7 @@ # ___________________________________________________________________________ from pypy.lang.gameboy import constants - +import os; def hasCartridgeBattery(self, cartridgeType): return (cartridgeType == constants.TYPE_MBC1_RAM_BATTERY \ @@ -33,43 +33,10 @@ class CartridgeManager(object): - def __init__(self, storeDriver, clockDriver): - self.store = storeDriver + def __init__(self, clockDriver): self.clock = clockDriver - - def getCartridgeType(self): - return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF - - def getRom(self): - return self.rom - - def getROMSize(self): - romSize = self.rom[constants.CARTRIDGE_SIZE_ADDRESS] & 0xFF - if romSize>=0x00 and romSize<=0x07: - return 32768 << romSize - return -1 + self.cartridge = None - def getRAMSize(self): - return constants.RAM_SIZE_MAPPING[self.rom[constants.RAM_SIZE_ADDRESS]] - - def getDestinationCode(self): - return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF - - def getLicenseeCode(): - return self.rom[constants.LICENSEE_ADDRESS] & 0xFF - - def getROMVersion(self): - return self.rom[constants.ROM_VERSION_ADDRESS] & 0xFF - - def getHeaderChecksum(self): - return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF - - def getChecksum(self): - return ((rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) - - def hasBattery(self): - return hasCartridgeBattery(self.getCartridgeType()) - def reset(self): if not self.hasBattery(): self.ram[0:len(self.ram):1] = 0xFF @@ -81,17 +48,13 @@ def write(self, address, data): self.mbc.write(address, data) - def load(self, cartridgeName): - self.loadROM() + def load(self, cartridge): + self.cartridge = cartridge + self.rom = self.cartridge.read() self.checkROM() self.createRAM() self.loadBattery() self.mbc = self.createBankController(self.getCartridgeType(), rom, ram, clock) - - def loadROM(self): - romSize = self.store.getCartridgeSize(cartridgeName) - self.rom = [0]*romSize - self.store.readCartridge(cartridgeName, self.rom) def checkROM(self): if not self.verifyHeader(): @@ -108,11 +71,44 @@ def loadBattery(self): if self.store.hasBattery(cartridgeName): - self.store.readBattery(cartridgeName, ram) + self.store.readBattery(cartridgeName, self.ram) def save(self, cartridgeName): if self.hasBattery(): self.store.writeBattery(cartridgeName, self.ram) + + def getCartridgeType(self): + return self.rom[constants.MEMORY_BANK_MAPPING] & 0xFF + + def getRom(self): + return self.rom + + def getROMSize(self): + romSize = self.rom[constants.CARTRIDGE_SIZE_ADDRESS] & 0xFF + if romSize>=0x00 and romSize<=0x07: + return 32768 << romSize + return -1 + + def getRAMSize(self): + return constants.RAM_SIZE_MAPPING[self.rom[constants.RAM_SIZE_ADDRESS]] + + def getDestinationCode(self): + return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF + + def getLicenseeCode(): + return self.rom[constants.LICENSEE_ADDRESS] & 0xFF + + def getROMVersion(self): + return self.rom[constants.ROM_VERSION_ADDRESS] & 0xFF + + def getHeaderChecksum(self): + return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF + + def getChecksum(self): + return ((rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) + + def hasBattery(self): + return hasCartridgeBattery(self.getCartridgeType()) def verify(self): checksum = 0 @@ -132,92 +128,55 @@ def createBankController(self, type, rom, ram, clockDriver): return MEMORY_BANK_MAPPING[type](rom, ram, clockDriver) -def CartridgeStoreManager(object): + - def __init__(self): +def Cartridge(object): + + def __init__(file=None): + if file != None: + self.load(file) + + def load(self, cartridgeFilePath): self.cartridgeName = "" + self.cartridgeFile = open(file) + self._loadBattery(cartridgeFilePath) - def setCartridgeName(self, cartridgeName): - self.cartridgeName = cartridgeName - self.batteryName = self.createBatteryName() - self.cartridgeFile = open(self.cartridgeName) - self.batteryFile = open(self.batteryName) - - def createBatteryName(self): - if self.cartridgeName.endsWith(constants.CARTRIDGE_FILE_EXTENSION): - self.batteryName = self.cartridgeName.replace(constants.CARTRIDGE_FILE_EXTENSION, + + def _loadBattery(self, cartridgeFilePath): + self.batteryFilePath = self._createBatteryFilePath(cartridgeFilePath) + if self.hasBattery(): + self.batteryFile = open(self.batteryFilePath) + + def _createBatteryFilePath(self, cartridgeFilePath): + if cartridgeFilePath.endsWith(constants.CARTRIDGE_FILE_EXTENSION): + return cartridgeFilePath.replace(constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION); - elif self.cartridgeName.endsWith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): - self.batteryName = self.cartridgeName.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, + elif cartridgeFilePath.endsWith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): + return cartridgeFilePath.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION); else: - batteryName = cartridgeName + batteryName.BATTERY_FILE_EXTENSION; - - def getCartridgeName(self): - return self.cartridgeName + return cartridgeFilePath + constants.BATTERY_FILE_EXTENSION; - def getCartridgeFile(self): - return self.cartridgeFile - - def hasCartridge(self): - return self.cartridgeFile.exists() - - def getCartridgeSize(self): - return self.cartridgeFile.length() - - def readCartridge(self, buffer): - try: - self.readFile(self.cartridgeFile, buffer); - except: - raise Exception("Could not load cartridge: " - + self.cartridgeFile.getPath()) + def hasBattery(self): + return os.path.exists(self.batteryFilePath) - def getBatteryName(self): - return self.batteryName; + def read(self): + return map(self.cartridgeFile.read(), self.mapToByte) + + def mapToByte(value): + return ord(value) & 0xFF - def getBatteryFile(self): - return self.batteryFile - - def hasBattery(self): - return self.batteryFile.exists() - - def getBatterySize(self): - return self.batteryFile.length() - - def readBattery(self, buffer): - try: - self.readFile(self.batteryFile, buffer) - except: - raise Exception("Could not load battery: " - + self.batteryFile.getPath()) - - def writeBattery(self, buffer): - try: - self.writeFile(self.batteryFile, buffer) - except: - raise Exception("Could not save battery: " - + batteryFile.getPath()) - - def removeBattery(): - if not self.batteryFile.delete(): - raise Exception("Could not delete battery: " - + batteryFile.getPath()) - - def readFile(file, buffer): - input = FileInputStream(file); - try : - if (input.read(buffer, 0, buffer.length) != buffer.length): - raise Exception("Unexpected end of file"); - finally: - input.close(); - - def writeFile(file, buffer): - output = FileOutputStream(file); - try : - output.write(buffer, 0, buffer.length); - finally: - output.close(); + def write(self, buffer): + self.cartridgeFile.read(map(buffer, chr)) + + def readBattery(self): + return map(self.batteryFile.read(), self.mapToByte) + + def writeBattery(self, ram): + self.batteryFile.write(map(ram, chr)) + + # ============================================================================== # CARTRIDGE TYPES @@ -268,7 +227,6 @@ def write(self, address, data): pass - class MBC1(MBC): """ PyBoy GameBoy (TM) Emulator @@ -372,9 +330,6 @@ if self.ramEnable: self.ram[address & 0x01FF] = (byte) (data & 0x0F) - - - class MBC3(MBC): """ PyBoy GameBoy (TM) Emulator @@ -517,8 +472,6 @@ self.clockControl |= 0x80 self.clockTime = now - - class MBC5(MBC): """ PyBoy GameBoy (TM) Emulator @@ -567,7 +520,6 @@ self.reset() super.__init__(rom, ram, clockDriver) - class HuC3(MBC): """ PyBoy GameBoy (TM) Emulator Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Sun Apr 20 10:31:08 2008 @@ -0,0 +1,24 @@ + +import py +from pypy.lang.gameboy.cartridge import * + + +ROM_PATH = py.magic.autopath().dirpath().dirpath()+"/rom" + + +# ------------------------------------------------------------------------------ + +def get_cartridge_managers(): + pass + +def get_cartridge(): + return Cartridge() + + + +# ------------------------------------------------------------------------------ + + +# STORE MANAGER TEST ----------------------------------------------------------- +def test_store_manager_init(): + cartridge = get_cartridge_managers() From cfbolz at codespeak.net Sun Apr 20 12:19:13 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 20 Apr 2008 12:19:13 +0200 (CEST) Subject: [pypy-svn] r53901 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080420101913.28277398004@codespeak.net> Author: cfbolz Date: Sun Apr 20 12:19:12 2008 New Revision: 53901 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Log: kill some semicolons ? you don't need them in Python Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun Apr 20 12:19:12 2008 @@ -2,7 +2,7 @@ # ___________________________________________________________________________ from pypy.lang.gameboy import constants -import os; +import os def hasCartridgeBattery(self, cartridgeType): return (cartridgeType == constants.TYPE_MBC1_RAM_BATTERY \ @@ -15,7 +15,7 @@ or cartridgeType == constants.TYPE_HUC1_RAM_BATTERY) def hasCartridgeType(self, catridgeType): - return constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType); + return constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType) def createBankController(self, cartridgeType, rom, ram, clock): if hasCartridgeType(cartridgeType): @@ -150,12 +150,12 @@ def _createBatteryFilePath(self, cartridgeFilePath): if cartridgeFilePath.endsWith(constants.CARTRIDGE_FILE_EXTENSION): return cartridgeFilePath.replace(constants.CARTRIDGE_FILE_EXTENSION, - constants.BATTERY_FILE_EXTENSION); + constants.BATTERY_FILE_EXTENSION) elif cartridgeFilePath.endsWith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): return cartridgeFilePath.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, - constants.BATTERY_FILE_EXTENSION); + constants.BATTERY_FILE_EXTENSION) else: - return cartridgeFilePath + constants.BATTERY_FILE_EXTENSION; + return cartridgeFilePath + constants.BATTERY_FILE_EXTENSION def hasBattery(self): return os.path.exists(self.batteryFilePath) From fijal at codespeak.net Sun Apr 20 17:26:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Apr 2008 17:26:39 +0200 (CEST) Subject: [pypy-svn] r53910 - pypy/dist/pypy/translator/c Message-ID: <20080420152639.8869E168578@codespeak.net> Author: fijal Date: Sun Apr 20 17:26:39 2008 New Revision: 53910 Modified: pypy/dist/pypy/translator/c/genc.py Log: don't prevent profopt from happening Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sun Apr 20 17:26:39 2008 @@ -850,6 +850,9 @@ clean: \trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) *.gc?? +clean_noprof: +\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) + debug: \t$(MAKE) CFLAGS="-g -DRPY_ASSERT" $(TARGET) @@ -877,6 +880,6 @@ profopt: \t$(MAKE) CFLAGS="-fprofile-generate $(CFLAGS)" LDFLAGS="-fprofile-generate $(LDFLAGS)" $(TARGET) \tcd $(PYPYDIR)/translator/goal && $(abspath $(TARGET)) $(PROFOPT) -\t$(MAKE) clean +\t$(MAKE) clean_noprof \t$(MAKE) CFLAGS="-fprofile-use $(CFLAGS)" LDFLAGS="-fprofile-use $(LDFLAGS)" $(TARGET) ''' From fijal at codespeak.net Sun Apr 20 17:27:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Apr 2008 17:27:35 +0200 (CEST) Subject: [pypy-svn] r53911 - pypy/dist/pypy/objspace Message-ID: <20080420152735.A5195168578@codespeak.net> Author: fijal Date: Sun Apr 20 17:27:35 2008 New Revision: 53911 Modified: pypy/dist/pypy/objspace/descroperation.py Log: hotpath for comparisons Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Sun Apr 20 17:27:35 2008 @@ -441,6 +441,7 @@ def _make_binop_impl(symbol, specialnames): left, right = specialnames + def binop_impl(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) @@ -468,12 +469,20 @@ return w_res raise OperationError(space.w_TypeError, space.wrap("unsupported operand type(s) for %s" % symbol)) + return func_with_new_name(binop_impl, "binop_%s_impl"%left.strip('_')) def _make_comparison_impl(symbol, specialnames): left, right = specialnames op = getattr(operator, left) def comparison_impl(space, w_obj1, w_obj2): + from pypy.objspace.std.intobject import W_IntObject + if type(w_obj1) is W_IntObject and type(w_obj2) is W_IntObject: + return space.newbool(op(w_obj1.intval, w_obj2.intval)) + return _comparison_impl(space, w_obj1, w_obj2) + comparison_impl._always_inline_ = True + + def _comparison_impl(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) @@ -499,6 +508,7 @@ w_res = _cmp(space, w_first, w_second) res = space.int_w(w_res) return space.wrap(op(res, 0)) + _comparison_impl._dont_inline_ = True return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_')) From fijal at codespeak.net Sun Apr 20 17:30:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Apr 2008 17:30:06 +0200 (CEST) Subject: [pypy-svn] r53912 - pypy/dist/pypy/interpreter Message-ID: <20080420153006.A35FC1684D0@codespeak.net> Author: fijal Date: Sun Apr 20 17:30:01 2008 New Revision: 53912 Modified: pypy/dist/pypy/interpreter/pyframe.py Log: pre-alloc 20 items here. Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Sun Apr 20 17:30:01 2008 @@ -10,7 +10,7 @@ from pypy.rlib.objectmodel import we_are_translated, instantiate from pypy.rlib.jit import we_are_jitted, hint from pypy.rlib import rstack # for resume points - +from pypy.rlib.objectmodel import newlist # Define some opcodes used g = globals() @@ -54,7 +54,7 @@ eval.Frame.__init__(self, space, w_globals, code.co_nlocals) self.valuestack_w = [None] * code.co_stacksize self.valuestackdepth = 0 - self.blockstack = [] + self.blockstack = newlist(sizehint=20) if space.config.objspace.honor__builtins__: self.builtin = space.builtin.pick_builtin(w_globals) # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. From fijal at codespeak.net Sun Apr 20 17:33:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Apr 2008 17:33:10 +0200 (CEST) Subject: [pypy-svn] r53913 - pypy/dist/pypy/interpreter Message-ID: <20080420153310.432C01684D3@codespeak.net> Author: fijal Date: Sun Apr 20 17:33:09 2008 New Revision: 53913 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: use one class instead of many. Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Sun Apr 20 17:33:09 2008 @@ -818,15 +818,16 @@ raise BytecodeCorruption, "old opcode, no longer in use" def SETUP_LOOP(f, offsettoend, next_instr, *ignored): - block = LoopBlock(f, next_instr + offsettoend) + #block = LoopBlock(f, next_instr + offsettoend) + block = FrameBlock(LOOP, f, next_instr + offsettoend) f.blockstack.append(block) def SETUP_EXCEPT(f, offsettoend, next_instr, *ignored): - block = ExceptBlock(f, next_instr + offsettoend) + block = FrameBlock(EXCEPT, f, next_instr + offsettoend) f.blockstack.append(block) def SETUP_FINALLY(f, offsettoend, next_instr, *ignored): - block = FinallyBlock(f, next_instr + offsettoend) + block = FrameBlock(FINALLY, f, next_instr + offsettoend) f.blockstack.append(block) def WITH_CLEANUP(f, *ignored): @@ -1066,15 +1067,23 @@ return SContinueLoop(space.int_w(w_jump_to)) state_pack_variables = staticmethod(state_pack_variables) +LOOP = 0 +EXCEPT = 1 +FINALLY = 2 + +HANDLING_MASKS = [SBreakLoop.kind | SContinueLoop.kind, + SApplicationException.kind, -1] 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): + def __init__(self, tp, frame, handlerposition): + self.tp = tp self.handlerposition = handlerposition self.valuestackdepth = frame.valuestackdepth + self.handling_mask = HANDLING_MASKS[tp] def __eq__(self, other): return (self.__class__ is other.__class__ and @@ -1093,6 +1102,9 @@ def cleanup(self, frame): "Clean up a frame when we normally exit the block." self.cleanupstack(frame) + if self.tp == FINALLY: + frame.pushvalue(frame.space.w_None) + frame.pushvalue(frame.space.w_None) # internal pickling interface, not using the standard protocol def _get_state_(self, space): @@ -1105,9 +1117,46 @@ return hint(next_instr, promote=True) def really_handle(self, frame, unroller): - """ Purely abstract method - """ - raise NotImplementedError + if self.tp == LOOP: + 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.append(self) + return unroller.jump_to + else: + # jump to the end of the loop + self.cleanupstack(frame) + return self.handlerposition + elif self.tp == EXCEPT: + # 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.pushvalue(frame.space.wrap(unroller)) + frame.pushvalue(operationerr.w_value) + frame.pushvalue(operationerr.w_type) + return self.handlerposition # jump to the handler + else: + # 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.pushvalue(frame.space.wrap(unroller)) + frame.pushvalue(frame.space.w_None) + frame.pushvalue(frame.space.w_None) + return self.handlerposition # jump to the handler + + #def really_handle(self, frame, unroller): + # """ Purely abstract method + # """ + # raise NotImplementedError class LoopBlock(FrameBlock): """A loop block. Stores the end-of-loop pointer in case of 'break'.""" From antocuni at codespeak.net Mon Apr 21 12:40:03 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Apr 2008 12:40:03 +0200 (CEST) Subject: [pypy-svn] r53969 - in pypy/branch/jit-hotpath/pypy: jit/rainbow/test jit/timeshifter rpython/ootypesystem Message-ID: <20080421104003.E86142A01C5@codespeak.net> Author: antocuni Date: Mon Apr 21 12:40:01 2008 New Revision: 53969 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtuple.py pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtupletype.py Log: - implement materialize() for InstanceTypeDesc - add the relevant hints to ootypesystem.tupletype - test_compile_time_const_tuple passes! Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Mon Apr 21 12:40:01 2008 @@ -2340,4 +2340,3 @@ test_red_struct_array = _skip test_red_varsized_struct = _skip test_array_of_voids = _skip - test_compile_time_const_tuple = _skip # needs vdict Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Mon Apr 21 12:40:01 2008 @@ -100,7 +100,13 @@ self.gv_null = RGenOp.constPrebuiltGlobal(self.null) self._compute_fielddescs(RGenOp) - self._define_helpers(TYPE, fixsize) + + if self._get_gckind(TYPE): # no 'allocate' for inlined substructs + if self.immutable and self.noidentity: + self._define_materialize() + if fixsize: + self._define_devirtualize() + self._define_allocate(fixsize) def Ptr(self, TYPE): @@ -197,13 +203,15 @@ def _define_materialize(self): TYPE = self.TYPE descs = unrolling_iterable(self.fielddescs) + malloc = self.malloc + cast_pointer = self.cast_pointer def materialize(rgenop, boxes): - s = lltype.malloc(TYPE) + s = malloc(TYPE) i = 0 for desc in descs: v = rvalue.ll_getvalue(boxes[i], desc.RESTYPE) - tgt = lltype.cast_pointer(desc.PTRTYPE, s) + tgt = cast_pointer(desc.PTRTYPE, s) setattr(tgt, desc.fieldname, v) i = i + 1 return rgenop.genconst(s) @@ -239,17 +247,12 @@ else: return object.__new__(StructTypeDesc) - def Ptr(self, TYPE): - return lltype.Ptr(TYPE) - - def _define_helpers(self, TYPE, fixsize): - if TYPE._gckind == 'gc': # no 'allocate' for inlined substructs - if self.immutable and self.noidentity: - self._define_materialize() - if fixsize: - self._define_devirtualize() - self._define_allocate(fixsize) + Ptr = staticmethod(lltype.Ptr) + malloc = staticmethod(lltype.malloc) + cast_pointer = staticmethod(lltype.cast_pointer) + def _get_gckind(self, TYPE): + return TYPE._gckind == 'gc' class InstanceTypeDesc(AbstractStructTypeDesc): @@ -265,8 +268,16 @@ def Ptr(self, TYPE): return TYPE - def _define_helpers(self, TYPE, fixsize): - pass + malloc = staticmethod(ootype.new) + + @staticmethod + def cast_pointer(TYPE, obj): + if isinstance(TYPE, ootype.Instance): + return ootype.ooupcast(TYPE, obj) + return obj + + def _get_gckind(self, TYPE): + return 'gc' # all instances and records are garbage collected def _iter_fields(self, TYPE): try: Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtuple.py Mon Apr 21 12:40:01 2008 @@ -2,6 +2,7 @@ from pypy.rpython.rtuple import AbstractTupleRepr, AbstractTupleIteratorRepr from pypy.rpython.ootypesystem import ootype from pypy.rpython.ootypesystem import rstr +from pypy.rpython.ootypesystem.rtupletype import TUPLE_TYPE class TupleRepr(AbstractTupleRepr): @@ -9,7 +10,7 @@ def __init__(self, rtyper, items_r): AbstractTupleRepr.__init__(self, rtyper, items_r) - self.lowleveltype = ootype.Record(dict(zip(self.fieldnames, self.lltypes))) + self.lowleveltype = TUPLE_TYPE(self.lltypes) def newtuple(cls, llops, r_tuple, items_v): # items_v should have the lowleveltype of the internal reprs Modified: pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtupletype.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtupletype.py (original) +++ pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtupletype.py Mon Apr 21 12:40:01 2008 @@ -7,7 +7,8 @@ def TUPLE_TYPE(field_lltypes): if len(field_lltypes) == 0: - return Void # empty tuple + return ootype.Void # empty tuple else: fields = [('item%d' % i, TYPE) for i, TYPE in enumerate(field_lltypes)] - return ootype.Record(dict(fields)) + hints = {'immutable': True, 'noidentity': True} + return ootype.Record(dict(fields), _hints=hints) From antocuni at codespeak.net Mon Apr 21 14:20:03 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Apr 2008 14:20:03 +0200 (CEST) Subject: [pypy-svn] r53970 - pypy/branch/jit-hotpath/pypy/jit/timeshifter Message-ID: <20080421122003.ECE142A01C4@codespeak.net> Author: antocuni Date: Mon Apr 21 14:20:02 2008 New Revision: 53970 Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Log: fix translation. Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py Mon Apr 21 14:20:02 2008 @@ -913,7 +913,8 @@ self.ownbox.setgenvar_hint(gv, known_nonzero=True) self.ownbox.content = None return - name = getattr(typedesc.TYPE, '_name', str(typedesc.TYPE)) + #name = getattr(typedesc.TYPE, '_name', str(typedesc.TYPE)) + name = str(typedesc.TYPE) debug_print(lltype.Void, "FORCE CONTAINER: "+ name) #debug_pdb(lltype.Void) genvar = jitstate.ts.genop_malloc_fixedsize(builder, typedesc.alloctoken) From antocuni at codespeak.net Mon Apr 21 16:12:41 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Apr 2008 16:12:41 +0200 (CEST) Subject: [pypy-svn] r53974 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080421141241.28977498009@codespeak.net> Author: antocuni Date: Mon Apr 21 16:12:40 2008 New Revision: 53974 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_tlr.py Log: port test_tlr to ootype, but disable it since it doesn't pass Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_tlr.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_tlr.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_tlr.py Mon Apr 21 16:12:40 2008 @@ -1,4 +1,4 @@ -from pypy.rpython.module.support import LLSupport +from pypy.rpython.module.support import LLSupport, OOSupport from pypy.jit.rainbow.test.test_portal import PortalTest from pypy.jit.rainbow.test.test_vlist import P_OOPSPEC from pypy.tool.sourcetools import func_with_new_name @@ -6,16 +6,16 @@ from pypy.jit.tl import tlr -class TestTLR(PortalTest): - type_system = "lltype" +class BaseTestTLR(PortalTest): def test_tlr(self): bytecode = ','.join([str(ord(c)) for c in tlr.SQUARE]) tlr_interpret = func_with_new_name(tlr.interpret, "tlr_interpret") + to_rstr = self.to_rstr # to stick attributes on the new function object, not on tlr.interpret def build_bytecode(s): result = ''.join([chr(int(t)) for t in s.split(',')]) - return LLSupport.to_rstr(result) + return to_rstr(result) tlr_interpret.convert_arguments = [build_bytecode, int] res = self.timeshift_from_portal(tlr_interpret, tlr_interpret, [bytecode, 1764], @@ -25,3 +25,11 @@ res = self.timeshift_from_portal(tlr_interpret, tlr_interpret, [bytecode, 9], policy=P_OOPSPEC) assert res == 81 + +class TestLLType(BaseTestTLR): + type_system = "lltype" + to_rstr = staticmethod(LLSupport.to_rstr) + +##class TestOOType(BaseTestTLR): +## type_system = "ootype" +## to_rstr = staticmethod(OOSupport.to_rstr) From antocuni at codespeak.net Mon Apr 21 19:26:24 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Apr 2008 19:26:24 +0200 (CEST) Subject: [pypy-svn] r53978 - in pypy/branch/jit-hotpath/pypy/jit: codegen/i386/test codegen/ia32/test codegen/llgraph codegen/llvm/test rainbow rainbow/test Message-ID: <20080421172624.5AD14169EC5@codespeak.net> Author: antocuni Date: Mon Apr 21 19:26:23 2008 New Revision: 53978 Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_portal.py pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/jit-hotpath/pypy/jit/codegen/llvm/test/test_genc_portal.py pypy/branch/jit-hotpath/pypy/jit/rainbow/portal.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_llinterp.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Log: port test_portal to ootype, first tests pass Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_portal.py Mon Apr 21 19:26:23 2008 @@ -93,7 +93,7 @@ class TestPortal(I386PortalTestMixin, - test_portal.TestPortal): + test_portal.TestPortalLLType): # for the individual tests see # ====> ../../../rainbow/test/test_portal.py Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/test/test_genc_portal.py Mon Apr 21 19:26:23 2008 @@ -93,7 +93,7 @@ class TestPortal(I386PortalTestMixin, - test_portal.TestPortal): + test_portal.TestPortalLLType): # for the individual tests see # ====> ../../../rainbow/test/test_portal.py Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py Mon Apr 21 19:26:23 2008 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rtupletype as llrtupletype from pypy.rpython.ootypesystem import ootype, rtupletype as oortupletype from pypy.objspace.flow import model as flowmodel -from pypy.translator.simplify import eliminate_empty_blocks +from pypy.translator.simplify import eliminate_empty_blocks, get_funcobj from pypy.translator.unsimplify import varoftype from pypy.rpython.module.support import LLSupport, OOSupport from pypy.rpython.extregistry import ExtRegistryEntry @@ -75,13 +75,19 @@ casting_link(graph.prereturnblock, [v1], graph.returnblock) substartblock = flowmodel.Block(erasedinputargs) casting_link(graph.startblock, inputargs, substartblock) - fptr = lltype.functionptr(FUNCTYPE, name, - graph=graph) + if isinstance(FUNCTYPE, lltype.FuncType): + fptr = lltype.functionptr(FUNCTYPE, name, + graph=graph) + else: + assert isinstance(FUNCTYPE, ootype.StaticMethod) + fptr = ootype.static_meth(FUNCTYPE, name, + graph=graph) return genconst(fptr) def _getgraph(gv_func): - graph = _from_opaque(gv_func).value._obj.graph - return graph + fnptr = _from_opaque(gv_func).value + graph = get_funcobj(fnptr).graph + return graph def end(gv_func): graph = _getgraph(gv_func) Modified: pypy/branch/jit-hotpath/pypy/jit/codegen/llvm/test/test_genc_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/codegen/llvm/test/test_genc_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/codegen/llvm/test/test_genc_portal.py Mon Apr 21 19:26:23 2008 @@ -9,7 +9,7 @@ RGenOp = RLLVMGenOp class TestPortal(LLVMPortalTestMixin, - test_portal.TestPortal): + test_portal.TestPortalLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_portal.py Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/portal.py Mon Apr 21 19:26:23 2008 @@ -1,11 +1,13 @@ from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.timeshifter import rvalue, rcontainer +from pypy.jit.rainbow import typesystem from pypy.objspace.flow import model as flowmodel from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.rpython.annlowlevel import llhelper, cachedtype from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.translator.simplify import get_funcobj # graph transformations for transforming the portal graph(s) class PortalRewriter(object): @@ -17,6 +19,11 @@ self.codewriter = codewriter self.RGenOp = RGenOp self.translate_support_code = translate_support_code + if rtyper.type_system.name == 'lltypesystem': + self.ts = typesystem.llhelper + else: + self.ts = typesystem.oohelper + def rewrite(self, origportalgraph, portalgraph, view=False): self.origportalgraph = origportalgraph @@ -25,7 +32,8 @@ self.readportalgraph = None self.make_args_specification() self.PortalState = make_state_class( - self.args_specification, self.RESIDUAL_FUNCTYPE, self.sigtoken, + self.args_specification, self.RESIDUAL_FUNCTYPE, + self.PTR_RESIDUAL_FUNCTYPE, self.sigtoken, self.codewriter.all_graphs[self.portalgraph], self.rtyper, self.codewriter) @@ -51,8 +59,8 @@ ARGS.extend(argdesc.residual_argtypes()) args_specification.append(arg_spec) self.args_specification = args_specification - self.RESIDUAL_FUNCTYPE = lltype.FuncType(ARGS, RESTYPE) - self.PORTAL_FUNCTYPE = lltype.FuncType(ORIGARGS, RESTYPE) + self.RESIDUAL_FUNCTYPE, self.PTR_RESIDUAL_FUNCTYPE = self.ts.get_FuncType(ARGS, RESTYPE) + self.PORTAL_FUNCTYPE, self.PTR_PORTAL_FUNCTYPE = self.ts.get_FuncType(ORIGARGS, RESTYPE) self.sigtoken = self.RGenOp.sigToken(self.RESIDUAL_FUNCTYPE) def make_state_instance(self): @@ -68,7 +76,7 @@ if not self.translate_support_code: # this case is used for most tests: the jit stuff should be run # directly to make these tests faster - portal_entry_graph_ptr = llhelper(lltype.Ptr(self.PORTAL_FUNCTYPE), + portal_entry_graph_ptr = llhelper(self.PTR_PORTAL_FUNCTYPE, self.portal_entry) else: # this translates portal_entry into low-level graphs, recursively @@ -79,7 +87,7 @@ from pypy.annotation import model as annmodel annhelper = annlowlevel.MixLevelHelperAnnotator(self.rtyper) FUNC = self.PORTAL_FUNCTYPE - RESFUNC = self.RESIDUAL_FUNCTYPE + PTR_RESFUNC = self.PTR_RESIDUAL_FUNCTYPE args_s = [annmodel.lltype_to_annotation(ARG) for ARG in FUNC.ARGS] s_result = annmodel.lltype_to_annotation(FUNC.RESULT) self.portal_entry_graph = annhelper.getgraph( @@ -92,14 +100,15 @@ return state.get_residual_fnptr() self.get_residual_fnptr_graph = annhelper.getgraph( ll_get_residual_fnptr, [], - annmodel.lltype_to_annotation(lltype.Ptr(RESFUNC))) + annmodel.lltype_to_annotation(PTR_RESFUNC)) annhelper.finish() # the following gives a pdb prompt when portal_entry raises an exception - portal_entry_graph_ptr._obj.__dict__['_debugexc'] = True + fnobj = get_funcobj(portal_entry_graph_ptr) + fnobj.__dict__['_debugexc'] = True # XXX hack hack hack args = [flowmodel.Constant(portal_entry_graph_ptr, - lltype.Ptr(self.PORTAL_FUNCTYPE))] + self.PTR_PORTAL_FUNCTYPE)] args += self.origportalgraph.getargs() result = flowmodel.Variable() result.concretetype = self.origportalgraph.getreturnvar().concretetype @@ -119,11 +128,12 @@ else: residual_graph_ptr = llinterp.eval_graph( self.get_residual_fnptr_graph, []) - residual_graph = residual_graph_ptr._obj.graph + residual_graph = get_funcobj(residual_graph_ptr).graph return residual_graph -def make_state_class(args_specification, RESIDUAL_FUNCTYPE, sigtoken, +def make_state_class(args_specification, RESIDUAL_FUNCTYPE, + PTR_RESIDUAL_FUNCTYPE, sigtoken, portal_jitcode, rtyper, codewriter): args_specification = unrolling_iterable(args_specification) class PortalState(object): @@ -194,12 +204,12 @@ gv_generated = self.compile(key, *args) residualargs = self.make_residualargs(*args) - fn = gv_generated.revealconst(lltype.Ptr(RESIDUAL_FUNCTYPE)) + fn = gv_generated.revealconst(PTR_RESIDUAL_FUNCTYPE) if not we_are_translated(): # run the generated code on top of the llinterp for testing exc_data_ptr = codewriter.exceptiondesc.exc_data_ptr llinterp = LLInterpreter(rtyper, exc_data_ptr=exc_data_ptr) - res = llinterp.eval_graph(fn._obj.graph, residualargs) + res = llinterp.eval_graph(get_funcobj(fn).graph, residualargs) return res else: return fn(*residualargs) @@ -289,11 +299,11 @@ gv_generated = cache[key] except KeyError: return lltype.nullptr(RESIDUAL_FUNCTYPE) - fn = gv_generated.revealconst(lltype.Ptr(RESIDUAL_FUNCTYPE)) + fn = gv_generated.revealconst(PTR_RESIDUAL_FUNCTYPE) return fn def readallportals(self): - return [gv_gen.revealconst(lltype.Ptr(RESIDUAL_FUNCTYPE)) + return [gv_gen.revealconst(PTR_RESIDUAL_FUNCTYPE) for gv_gen in self.cache.values()] def get_residual_fnptr(self): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Mon Apr 21 19:26:23 2008 @@ -1,6 +1,6 @@ import py from pypy.translator.translator import TranslationContext, graphof -from pypy.translator.simplify import simplify_graph +from pypy.translator.simplify import simplify_graph, get_funcobj from pypy.jit.codegen.llgraph.rgenop import RGenOp as LLRGenOp from pypy.jit.hintannotator.annotator import HintAnnotator from pypy.jit.hintannotator.policy import StopAtXPolicy, HintAnnotatorPolicy @@ -229,8 +229,8 @@ if jitstate is not None: writer.interpreter.finish_jitstate(sigtoken) builder.end() - generated = gv_generated.revealconst(lltype.Ptr(self.RESIDUAL_FUNCTYPE)) - graph = generated._obj.graph + generated = gv_generated.revealconst(self.Ptr(self.RESIDUAL_FUNCTYPE)) + graph = get_funcobj(generated).graph self.residual_graph = graph if conftest.option.view: graph.show() Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_llinterp.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_llinterp.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_llinterp.py Mon Apr 21 19:26:23 2008 @@ -7,7 +7,7 @@ -class TestLLInterpreted(test_portal.TestPortal): +class TestLLInterpreted(test_portal.TestPortalLLType): translate_support_code = True # for the individual tests see Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Mon Apr 21 19:26:23 2008 @@ -82,7 +82,7 @@ return calls -class TestPortal(PortalTest): +class BaseTestPortal(PortalTest): type_system = "lltype" def test_simple(self): @@ -601,3 +601,25 @@ res = self.timeshift_from_portal(ll_function, ll_function, []) assert res == ll_function() self.check_insns({}) + + + +class TestPortalOOType(BaseTestPortal): + type_system = 'ootype' + + def _skip(self): + py.test.skip('in progress') + + test_dfa_compile2 = _skip + test_dfa_compile3 = _skip + test_method_call_nonpromote = _skip + test_method_call_promote = _skip + test_float_promote = _skip + test_isinstance = _skip + test_greenmethod_call_nonpromote = _skip + test_virt_obj_method_call_promote = _skip + test_simple_recursive_portal_call_with_exc = _skip + +class TestPortalLLType(BaseTestPortal): + type_system = 'lltype' + From cami at codespeak.net Mon Apr 21 21:33:42 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 21 Apr 2008 21:33:42 +0200 (CEST) Subject: [pypy-svn] r53982 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . rom/rom1 rom/rom2 rom/rom3 rom/rom4 rom/rom5 rom/rom6 rom/rom7 rom/rom8 rom/rom9 test Message-ID: <20080421193342.E53FF2A00DC@codespeak.net> Author: cami Date: Mon Apr 21 21:33:40 2008 New Revision: 53982 Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/readme.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/rom1.raw pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/make.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/readme-1.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/rom2.raw (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/make-1.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/readme-2.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/rom3.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/rom3.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/readme-3.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom4.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom4.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom41.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom42.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/make-2.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/readme.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/rom5.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/rom5.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/make.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/readme-1.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/rom6.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/rom6.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/make.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/readme.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/rom7.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/rom7.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/make.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/readme.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/rom8.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/rom8.gb (contents, props changed) pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/make.bat pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/readme.txt pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/rom9.asm pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/rom9.gb (contents, props changed) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Log: added rom test files reimplemented cartridge added cartridge tests still missing cartridgeManager tests Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Mon Apr 21 21:33:40 2008 @@ -54,7 +54,7 @@ self.checkROM() self.createRAM() self.loadBattery() - self.mbc = self.createBankController(self.getCartridgeType(), rom, ram, clock) + self.mbc = self.createBankController(self.getMemoryBankType(), rom, ram, clock) def checkROM(self): if not self.verifyHeader(): @@ -64,8 +64,8 @@ def createRAM(self): ramSize = self.getRAMSize() - if (getCartridgeType() >= constants.TYPE_MBC2 - and getCartridgeType() <= constants.TYPE_MBC2_BATTERY): + if (getMemoryBankType() >= constants.TYPE_MBC2 + and getMemoryBankType() <= constants.TYPE_MBC2_BATTERY): ramSize = 512 self.ram = [0xFF]*ramSize @@ -77,7 +77,7 @@ if self.hasBattery(): self.store.writeBattery(cartridgeName, self.ram) - def getCartridgeType(self): + def getMemoryBankType(self): return self.rom[constants.MEMORY_BANK_MAPPING] & 0xFF def getRom(self): @@ -108,7 +108,7 @@ return ((rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) def hasBattery(self): - return hasCartridgeBattery(self.getCartridgeType()) + return hasCartridgeBattery(self.getMemoryBankType()) def verify(self): checksum = 0 @@ -130,28 +130,41 @@ -def Cartridge(object): +class Cartridge(object): - def __init__(file=None): + def __init__(self, file=None): + self.reset() if file != None: self.load(file) + def reset(self): + self.cartridgeName ="" + self.cartridgeFilePath = "" + self.cartridgeFile = None + + self.batteryName ="" + self.batteryFilePath = "" + self.batteryFile = None + + def load(self, cartridgeFilePath): - self.cartridgeName = "" - self.cartridgeFile = open(file) + self.cartridgeFilePath = cartridgeFilePath + self.cartridgeName = os.path.basename(cartridgeFilePath) + self.cartridgeFile = open(cartridgeFilePath) self._loadBattery(cartridgeFilePath) def _loadBattery(self, cartridgeFilePath): self.batteryFilePath = self._createBatteryFilePath(cartridgeFilePath) + self.batteryName = os.path.basename(self.batteryFilePath) if self.hasBattery(): self.batteryFile = open(self.batteryFilePath) def _createBatteryFilePath(self, cartridgeFilePath): - if cartridgeFilePath.endsWith(constants.CARTRIDGE_FILE_EXTENSION): + if cartridgeFilePath.endswith(constants.CARTRIDGE_FILE_EXTENSION): return cartridgeFilePath.replace(constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) - elif cartridgeFilePath.endsWith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): + elif cartridgeFilePath.endswith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): return cartridgeFilePath.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) else: @@ -161,22 +174,27 @@ return os.path.exists(self.batteryFilePath) def read(self): - return map(self.cartridgeFile.read(), self.mapToByte) - - def mapToByte(value): - return ord(value) & 0xFF - - def write(self, buffer): - self.cartridgeFile.read(map(buffer, chr)) - + self.cartridgeFile.seek(0) + return map(map_to_byte, self.cartridgeFile.read()) def readBattery(self): - return map(self.batteryFile.read(), self.mapToByte) + self.batteryFile.seek(0) + return map(map_to_byte, self.batteryFile.read()) def writeBattery(self, ram): - self.batteryFile.write(map(ram, chr)) + self.batteryFile = open(self.batteryFilePath, "w") + self.batteryFile.write(("").join(map(chr, ram))) + self.batteryFile = open(self.batteryFilePath, "r+") + def removeBattery(self): + if self.hasBattery(): + os.remove(self.batteryFilePath) + + +def map_to_byte(value): + return ord(value) & 0xFF + # ============================================================================== # CARTRIDGE TYPES @@ -669,9 +687,6 @@ positions = range(entry[0], entry[1]+1) for pos in positions: result[pos] = entry[-1] - # XXX the following assert is disabled because it seems bogous - # in constants, they don't have 256 types... - # assert None not in result return result MEMORY_BANK_MAPPING = initialize_mapping_table() Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/readme.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/readme.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,17 @@ +============ +Gameboy ROM1 +============ + + +Description +----------- +This is a raw ROM, meaning it contains no valid Gameboy header, just +instructions. Addressing is relative, so the ROM can be loaded anywhere in +memory. + + +Disassembly +----------- +3E 01 LD A, 1 +06 01 LD B, 1 +80 ADD A, B \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/rom1.raw ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom1/rom1.raw Mon Apr 21 21:33:40 2008 @@ -0,0 +1 @@ +>? \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/make.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/make.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom3 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/readme-1.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/readme-1.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,17 @@ +============ +Gameboy ROM2 +============ + + +Description +----------- +This is a raw ROM, meaning it contains no valid Gameboy header, just +instructions. Addressing is relative, so the ROM can be loaded anywhere in +memory. + + +Disassembly +----------- +3E 00 LD A, 0 +06 00 LD B, 0 +80 ADD A, B \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom2/rom2.raw ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/make-1.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/make-1.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom4 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/readme-2.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/readme-2.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,17 @@ +============ +Gameboy ROM3 +============ + + +Specifications +-------------- +Filename: noptest.gb +Description: Runs a series of NOP instructions and then at the end performs an + endless loop. +ROM type: NO MBC (32kB ROM, no RAM) + + +Instructions used +----------------- +jp +nop Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/rom3.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/rom3.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,41 @@ +; ========================================================================== +; Noptest ROM example +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Start a section at address $100. +SECTION "Main code section", HOME[$100] + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header (NO MBC) + ROM_HEADER ROM_NOMBC, ROM_SIZE_32KBYTE, RAM_SIZE_0KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Nop nop nop ... + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +; All done, so let's jump in an infinite loop. Note that this is NOT the +; correct way to end the CPU loop! +.hangup: + jp .hangup Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom3/rom3.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/readme-3.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/readme-3.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,45 @@ +============ +Gameboy ROM4 +============ + + +Specifications +-------------- +Filename: rom4.gb +Description: This ROM is created to test the DI and HALT instructions. It also + uses the LCDC register to turn off the screen. +ROM type: NO MBC (32kB ROM, no RAM) + + +Instructions used +----------------- +ld +jp +nop +res +di +halt + + +Memory registers used +--------------------- +$ff40 (LCDC register, used to turn of screen) + + +Short information +----------------- +HALT stops the CPU until an interrupt occurs. Nintendo recommends using this +command in your main game loop in order to save battery power while the CPU has +nothing else to do. + +When an interrupt occurs while in HALT, the CPU starts back up and pushes the +Program Counter onto the stack before servicing the interrupt(s). Except it +doesn't push the address after HALT as one might expect but rather the address +of HALT itself. + +Nintendo also recommends that you put a NOP after HALT commands. The reason for +this is that the Program Counter will not increment properly (CPU bug) if you +try to do a HALT while IME = 0 and an interrupt is pending. A single-byte +instruction immediately following HALT will get executed twice if IME = 0 and an +interrupt is pending. If the instruction following HALT is a multi-byte +instruction then the game could hang or registers could get scrambled. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom4.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom4.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,42 @@ +; ========================================================================== +; ROM4 +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Start a section at address $100. +SECTION "Main code section", HOME[$100] + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header (NO MBC) + ROM_HEADER ROM_NOMBC, ROM_SIZE_32KBYTE, RAM_SIZE_0KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Disable interupts + di + + ; Turn off screen, please know that this is actually not the correct way + ; to turn off the screen, since we normally would have to wait for vertical + ; blank. But for now, it's ok. + ld hl, rLCDC + res 7, [hl] + + ; Stop CPU + db $76 ; halt (instruction coded as data because RGBASM adds a nop after a halt) + db $76 ; halt + + ; Put $ff in a to indicate that stop did not work + ld a, $ff + +; Just do the hangup here +.hangup: + jp .hangup Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom4.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom41.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom4/rom42.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/make-2.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/make-2.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom5 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/readme.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/readme.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,35 @@ +============ +Gameboy ROM5 +============ + + +Specifications +-------------- +Filename: rom5.gb +Description: This ROM is created to test the conditional jump instructions. It + also includes an invalid opcode ($DD) which is used for debugging + purposes! +ROM type: NO MBC (32kB ROM, no RAM) + + +Special notes +------------- +IMPORTANT: This ROM contains an invalid opcode ($DD) which we use to trigger the +emulator into a "breakpoint". When executing this ROM, simply treat the $DD +bytes as NOP ($00) instructions, but also print out the registers and CPU +status. + +This ROM also uses the carry and zero flags, so make sure that the work correctly. + + +Instructions used +----------------- +ld +jp +jr +inc +dec +nop +di +halt +$DD \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/rom5.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/rom5.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,63 @@ +; ========================================================================== +; ROM5 +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Start a section at address $100. +SECTION "Main code section", HOME[$100] + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header (NO MBC) + ROM_HEADER ROM_NOMBC, ROM_SIZE_32KBYTE, RAM_SIZE_0KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Disable interupts + di + + ; Test 1: The simple loop + xor a +.loop1: + dec a + jp NZ, .loop1 + + db $dd ; dbg + + ; Test 2: The loop with relative conditional jump + xor a +.loop2: + add a, 1 + jr NC, .loop2 + + db $dd ; dbg + + ; Test 3: The loop again, but different somehow + xor a +.loop3: + inc a + jp NC, .loop3 + + db $dd ; dbg + + ; Stop CPU + db $76 ; halt (instruction coded as data because RGBASM adds a nop after a halt) + db $76 ; halt + + ; Put $ff in a to indicate that stop did not work + ld a, $ff + + ; Breakpoint + db $dd ; dbg + +; Just do the hangup here +.hangup: + jp .hangup Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom5/rom5.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/make.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/make.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom6 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/readme-1.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/readme-1.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,31 @@ +============ +Gameboy ROM6 +============ + + +Specifications +-------------- +Filename: rom6.gb +Description: This ROM is created to test the implementation of ROM cartridge + with an MBC1 controller. +ROM type: MBC1 + RAM (64kB ROM, 32kB RAM) + + +Special notes +------------- +This ROM uses call and ret instructions, so this means that the emulator will +also need to implement and support a stack. + +Instructions used +----------------- +ld +jp +jr +inc +dec +nop +di +halt +$DD +call +ret \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/rom6.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/rom6.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,128 @@ +; ========================================================================== +; ROM6 +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Start a section at address $0. +SECTION "Main code section", HOME[$0] + +RST_00: jp main + DS 5 +RST_08: jp main + DS 5 +RST_10: jp main + DS 5 +RST_18: jp main + DS 5 +RST_20: jp main + DS 5 +RST_28: jp main + DS 5 +RST_30: jp main + DS 5 +RST_38: jp main + DS 5 + jp main ;irq_VBlank + DS 5 + jp main ;irq_LCDC + DS 5 + jp main ;irq_Timer + DS 5 + jp main ;irq_Serial + DS 5 + jp main ;irq_HiLo + DS 5 + + DS $100-$68 + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header (MBC1, 64kB ROM, 32kB RAM) + ROM_HEADER ROM_MBC1_RAM, ROM_SIZE_64KBYTE, RAM_SIZE_32KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Disable interupts + di + + ; Initialize stack + ld hl, topOfStack + ld sp, hl + + CART_MBC1_SELECT_MEMORY_MODE CART_MBC1_MODE_4MBIT + + CART_MBC1_SELECT_BANK_5BIT 1 ; selects ROM bank 1 + CART_MBC1_SELECT_BANK_2BIT 0 ; selects RAM bank 0 + + CART_MBC1_ENABLE_RAM ; enable RAM + + ; Write cartridge RAM full of $ff + ld hl, _CART_RAM + ld bc, $20 ;$2000 + ld a, $ff + call memSet + + CART_MBC1_SELECT_BANK_2BIT 1 ; selects RAM bank 1 + + ; Write cartridge RAM full of $22 + ld hl, _CART_RAM + ld bc, $20 ;$2000 + ld a, $22 + call memSet + + CART_MBC1_SELECT_BANK_2BIT 0 ; selects RAM bank 0 + + ; Compare the first byte of the RAM + ld a, $ff + ld hl, _CART_RAM + cp [hl] + jr NZ, .not_equal ; content was not ok, then jump + + xor a + +.not_equal: + + ; Stop CPU + db $76 ; halt (instruction coded as data because RGBASM adds a nop after a halt) + db $76 ; halt + + ; Breakpoint + db $dd ; dbg + +; Just do the hangup here +.hangup: + jp .hangup + + +; -------------------------------------------------------------------------- +; memSet - Set a memory region +; +; input: +; a - value to write +; hl - memory address +; bc - bytecount +; -------------------------------------------------------------------------- +memSet: + inc b + inc c + jr .skip +.loop ld [hl+],a +.skip dec c + jr nz,.loop + dec b + jr nz,.loop + ret + +SECTION "Stack",BSS + +stack: + DS $200 +topOfStack: \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom6/rom6.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/make.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/make.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom7 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/readme.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/readme.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,10 @@ +============ +Gameboy ROM7 +============ + + +Specifications +-------------- +Filename: rom7.gb +Description: This ROM is created to test the screen background. +ROM type: NOMBC \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/rom7.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/rom7.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,207 @@ +; ========================================================================== +; ROM7 +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Also include a file that can generate a set of characters in the IBM PC1 +; font face. +INCLUDE "../include/ibmpc1.inc" + +; SECTION ------------------------------------------------------------------ + +; Start a section at address $0. +SECTION "Main code section", HOME[$0] + +RST_00: jp main + DS 5 +RST_08: jp main + DS 5 +RST_10: jp main + DS 5 +RST_18: jp main + DS 5 +RST_20: jp main + DS 5 +RST_28: jp main + DS 5 +RST_30: jp main + DS 5 +RST_38: jp main + DS 5 + jp main ;irq_VBlank + DS 5 + jp main ;irq_LCDC + DS 5 + jp main ;irq_Timer + DS 5 + jp main ;irq_Serial + DS 5 + jp main ;irq_HiLo + DS 5 + + DS $100-$68 + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header + ROM_HEADER ROM_NOMBC, ROM_SIZE_32KBYTE, RAM_SIZE_0KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Disable interupts + di + + ; Initialize stack + ld sp, topOfStack + + CART_MBC1_SELECT_BANK_5BIT 1 ; selects ROM bank 1 + + ; Stop the LCD + call stopLCD + + ; Set the palette to shades of grey + ld a, $e4 + ld [rBGP], a ; Setup the default background palette + + ; We set the scroll registers to 0 so that we can + ; view the upper left corner of the background. + ld a, 0 + ld [rSCX], a + ld [rSCY], a + + ; Copy four characters to the VRAM (in order) + ld hl, font + ld de, _VRAM + ld bc, 32 ; length (8 bytes per tile) + call memCopyMono ; copy tile data to memory + + ; Clear tile map memory with tile 0 + ld a, $02 + ld hl, _SCRN0 + ld bc, SCRN_VX_B * SCRN_VY_B + call memSet + + ; Turn on the screen + call startLCD + +; Just do the hangup here +.hangup: + jp .hangup + + +; -------------------------------------------------------------------------- +; memSet - Set a memory region +; +; input: +; a - value to write +; hl - memory address +; bc - bytecount +; -------------------------------------------------------------------------- +memSet: + inc b + inc c + jr .skip +.loop ld [hl+], a +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; memCopy - Copy memory from ROM/RAM to RAM + +; input: +; hl - source address +; de - destination address +; bc - bytecount of source +; -------------------------------------------------------------------------- +memCopy: + inc b + inc c + jr .skip +.loop ld a, [hl+] + ld [de], a + inc de +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; memCopyMono - "Copy" a monochrome font from ROM to RAM (it basically +; writes every byte of the source twice to the destination, so +; the destination space is double of the source space) +; input: +; hl - source address +; de - destination address +; bc - bytecount of source +; -------------------------------------------------------------------------- +memCopyMono: + inc b + inc c + jr .skip +.loop ld a, [hl+] + ld [de], a + inc de + ld [de], a + inc de +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; stopLCD - Stops the LCD (turn off screen) +; -------------------------------------------------------------------------- +stopLCD: + ld a, [rLCDC] + rlca ; Put the high bit of LCDC into the Carry flag + ret nc ; Screen is off already. Exit. +; Loop until we are in VBlank +.wait: + ld a, [rLY] + cp 145 ; Is display on scan line 145 yet? + jr nz, .wait ; no, keep waiting +; Turn off the LCD + ld a, [rLCDC] + res 7, a ; Reset bit 7 of LCDC + ld [rLCDC], a +; Return + ret + + +; -------------------------------------------------------------------------- +; startLCD - Start the LCD (turn on screen) +; -------------------------------------------------------------------------- +startLCD: + ld a, LCDCF_ON | LCDCF_BG8000 | LCDCF_BG9800 | LCDCF_BGON | LCDCF_OBJ16 | LCDCF_OBJOFF + ld [rLCDC], a ; Turn screen on + ret + + +; Generate a partial character font set. +font: + chr_IBMPC1 1,2 + + +; SECTION ------------------------------------------------------------------ + +SECTION "Stack",BSS + +stack: + DS $200 +topOfStack: \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom7/rom7.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/make.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/make.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom8 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/readme.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/readme.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,10 @@ +============ +Gameboy ROM8 +============ + + +Specifications +-------------- +Filename: rom8.gb +Description: This ROM is created to test graphics background of a Gameboy. +ROM type: MBC1 + RAM (64kB ROM, 32kB RAM) \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/rom8.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/rom8.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,219 @@ +; ========================================================================== +; ROM8 +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Also include a file that can generate a set of characters in the IBM PC1 +; font face. +INCLUDE "../include/ibmpc1.inc" + +; SECTION ------------------------------------------------------------------ + +; Start a section at address $0. +SECTION "Main code section", HOME[$0] + +RST_00: jp main + DS 5 +RST_08: jp main + DS 5 +RST_10: jp main + DS 5 +RST_18: jp main + DS 5 +RST_20: jp main + DS 5 +RST_28: jp main + DS 5 +RST_30: jp main + DS 5 +RST_38: jp main + DS 5 + jp main ;irq_VBlank + DS 5 + jp main ;irq_LCDC + DS 5 + jp main ;irq_Timer + DS 5 + jp main ;irq_Serial + DS 5 + jp main ;irq_HiLo + DS 5 + + DS $100-$68 + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header (MBC1, 64kB ROM, 32kB RAM) + ROM_HEADER ROM_MBC1_RAM, ROM_SIZE_64KBYTE, RAM_SIZE_32KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Disable interupts + di + + ; Initialize stack + ld sp, topOfStack + + ; Stop the LCD + call stopLCD + + ; Setup cart controller + CART_MBC1_SELECT_MEMORY_MODE CART_MBC1_MODE_4MBIT + CART_MBC1_SELECT_BANK_5BIT 1 ; selects ROM bank 1 + CART_MBC1_SELECT_BANK_2BIT 0 ; selects RAM bank 0 + CART_MBC1_ENABLE_RAM ; enable RAM + + ; Set the palette to shades of grey + ld a, $e4 + ld [rBGP], a ; Setup the default background palette + + ; We set the scroll registers to 0 so that we can + ; view the upper left corner of the background. + ld a, 0 + ld [rSCX], a + ld [rSCY], a + + ; Copy the 256 character font data to the VRAM (in order) + ld hl, font + ld de, _VRAM + ld bc, 8 * 256 ; length (8 bytes per tile) x (256 tiles) + call memCopyMono ; copy tile data to memory + + ; Clear tile map memory with 'spaces' ($20) + ld a, $20 + ld hl, _SCRN0 + ld bc, SCRN_VX_B * SCRN_VY_B + call memSet + + ; Write the Hello world string + ld hl, helloWorld + ld de, _SCRN0 + 4 + (SCRN_VY_B * 7) + ld bc, 12 + call memCopy + + ; Turn on the screen + call startLCD + +; Just do the hangup here +.hangup: + jp .hangup + + +; -------------------------------------------------------------------------- +; memSet - Set a memory region +; +; input: +; a - value to write +; hl - memory address +; bc - bytecount +; -------------------------------------------------------------------------- +memSet: + inc b + inc c + jr .skip +.loop ld [hl+], a +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; memCopy - Copy memory from ROM/RAM to RAM + +; input: +; hl - source address +; de - destination address +; bc - bytecount of source +; -------------------------------------------------------------------------- +memCopy: + inc b + inc c + jr .skip +.loop ld a, [hl+] + ld [de], a + inc de +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; memCopyMono - "Copy" a monochrome font from ROM to RAM (it basically +; writes every byte of the source twice to the destination, so +; the destination space is double of the source space) +; input: +; hl - source address +; de - destination address +; bc - bytecount of source +; -------------------------------------------------------------------------- +memCopyMono: + inc b + inc c + jr .skip +.loop ld a, [hl+] + ld [de], a + inc de + ld [de], a + inc de +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; stopLCD - Stops the LCD (turn off screen) +; -------------------------------------------------------------------------- +stopLCD: + ld a, [rLCDC] + rlca ; Put the high bit of LCDC into the Carry flag + ret nc ; Screen is off already. Exit. +; Loop until we are in VBlank +.wait: + ld a, [rLY] + cp 145 ; Is display on scan line 145 yet? + jr nz, .wait ; no, keep waiting +; Turn off the LCD + ld a, [rLCDC] + res 7, a ; Reset bit 7 of LCDC + ld [rLCDC], a +; Return + ret + + +; -------------------------------------------------------------------------- +; startLCD - Start the LCD (turn on screen) +; -------------------------------------------------------------------------- +startLCD: + ld a, LCDCF_ON | LCDCF_BG8000 | LCDCF_BG9800 | LCDCF_BGON | LCDCF_OBJ16 | LCDCF_OBJOFF + ld [rLCDC], a ; Turn screen on + ret + + +; Generate a full 256 character font set. +font: + chr_IBMPC1 1,8 + +helloWorld: + db "Hello world!" + +; SECTION ------------------------------------------------------------------ + +SECTION "Stack",BSS + +stack: + DS $200 +topOfStack: \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom8/rom8.gb ============================================================================== Binary file. No diff available. Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/make.bat ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/make.bat Mon Apr 21 21:33:40 2008 @@ -0,0 +1,29 @@ + at echo off + +SET ROMNAME=rom9 + +echo -- COMPILING +for %%S in (*.asm) do ( +..\bin\rgbasm -o%%S.obj %%S +) +echo. + +echo -- LINK FILE +echo [Objects] > link.txt +dir /b *.obj >> link.txt +echo [Output] >> link.txt +echo %ROMNAME%.gb >> link.txt +type link.txt +echo. + +echo -- LINKING +..\bin\xlink -m%ROMNAME%.txt -n%ROMNAME%.sym link.txt +del link.txt +echo. + +echo -- FIXING ROM +..\bin\rgbfix -v -p -t%ROMNAME% %ROMNAME%.gb +del *.obj +echo. + +echo -- DONE \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/readme.txt ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/readme.txt Mon Apr 21 21:33:40 2008 @@ -0,0 +1,10 @@ +============ +Gameboy ROM9 +============ + + +Specifications +-------------- +Filename: rom9.gb +Description: This ROM is created to test graphics background of a Gameboy and sprites. +ROM type: MBC1 + RAM (64kB ROM, 32kB RAM) \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/rom9.asm ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/rom9.asm Mon Apr 21 21:33:40 2008 @@ -0,0 +1,255 @@ +; ========================================================================== +; ROM9 +; ========================================================================== + +; First we includ the Gameboy Hardware Definitions +; into our assembly file, so that we get some nice +; constants and macros available. +INCLUDE "../include/gbhd.inc" + +; Also include a file that can generate a set of characters in the IBM PC1 +; font face. +INCLUDE "../include/ibmpc1.inc" + +; SECTION ------------------------------------------------------------------ + +; Start a section at address $0. +SECTION "Main code section", HOME[$0] + +RST_00: jp main + DS 5 +RST_08: jp main + DS 5 +RST_10: jp main + DS 5 +RST_18: jp main + DS 5 +RST_20: jp main + DS 5 +RST_28: jp main + DS 5 +RST_30: jp main + DS 5 +RST_38: jp main + DS 5 + jp main ;irq_VBlank + DS 5 + jp main ;irq_LCDC + DS 5 + jp main ;irq_Timer + DS 5 + jp main ;irq_Serial + DS 5 + jp main ;irq_HiLo + DS 5 + + DS $100-$68 + + ; Start with a nop and a jump + nop + jp main + + ; Create a ROM header (MBC1, 64kB ROM, 32kB RAM) + ROM_HEADER ROM_MBC1_RAM, ROM_SIZE_64KBYTE, RAM_SIZE_32KBYTE + +; -------------------------------------------------------------------------- +; Main code entry point +; -------------------------------------------------------------------------- +main: + ; Disable interupts + di + + ; Initialize stack + ld sp, topOfStack + + ; Stop the LCD + call stopLCD + + ; Setup cart controller + CART_MBC1_SELECT_MEMORY_MODE CART_MBC1_MODE_4MBIT + CART_MBC1_SELECT_BANK_5BIT 1 ; selects ROM bank 1 + CART_MBC1_SELECT_BANK_2BIT 0 ; selects RAM bank 0 + CART_MBC1_ENABLE_RAM ; enable RAM + + ; Set the palette to shades of grey + ld a, $e4 + ld [rBGP], a ; Setup the default background palette + + ; We set the scroll registers to 0 so that we can + ; view the upper left corner of the background. + ld a, 0 + ld [rSCX], a + ld [rSCY], a + + ; Copy the 256 character font data to the VRAM (in order) + ld hl, font + ld de, _VRAM + ld bc, 8 * 256 ; length (8 bytes per tile) x (256 tiles) + call memCopyMono ; copy tile data to memory + + ; Clear tile map memory with 'spaces' ($20) + ld a, $20 + ld hl, _SCRN0 + ld bc, SCRN_VX_B * SCRN_VY_B + call memSet + + ; Setup Sprite 0 + ld hl, _OAMRAM + ld a, 70 + ld [hl+], a + xor a + ld [hl+], a + ld a, 1 + ld [hl+], a + xor a + ld [hl+], a + + ; Turn on the screen + call startLCD + + ; Write the Hello world string + ld hl, helloWorld + ld de, _SCRN0 + 4 + (SCRN_VY_B * 7) + ld b, 12 +.loop12: + call waitVBE + ld a, [hl+] + ld [de], a + inc de + dec b + jr nz, .loop12 + + +; Just loop +.hangup: + ld hl, _OAMRAM + 1 + ld a, [hl] + inc a + ld [hl], a + call waitVBE + jp .hangup + + +; -------------------------------------------------------------------------- +; memSet - Set a memory region +; +; input: +; a - value to write +; hl - memory address +; bc - bytecount +; -------------------------------------------------------------------------- +memSet: + inc b + inc c + jr .skip +.loop ld [hl+], a +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; memCopy - Copy memory from ROM/RAM to RAM + +; input: +; hl - source address +; de - destination address +; bc - bytecount of source +; -------------------------------------------------------------------------- +memCopy: + inc b + inc c + jr .skip +.loop ld a, [hl+] + ld [de], a + inc de +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; memCopyMono - "Copy" a monochrome font from ROM to RAM (it basically +; writes every byte of the source twice to the destination, so +; the destination space is double of the source space) +; input: +; hl - source address +; de - destination address +; bc - bytecount of source +; -------------------------------------------------------------------------- +memCopyMono: + inc b + inc c + jr .skip +.loop ld a, [hl+] + ld [de], a + inc de + ld [de], a + inc de +.skip dec c + jr nz, .loop + dec b + jr nz, .loop + ret + + +; -------------------------------------------------------------------------- +; waitVBE - Wait for Vertical Blank +; -------------------------------------------------------------------------- +waitVBE: +; Loop until we are in VBlank + push af +.wait: + ld a, [rLY] + cp 145 ; Is display on scan line 145 yet? + jr nz, .wait ; no, keep waiting + pop af + ret + +; -------------------------------------------------------------------------- +; stopLCD - Stops the LCD (turn off screen) +; -------------------------------------------------------------------------- +stopLCD: + ld a, [rLCDC] + rlca ; Put the high bit of LCDC into the Carry flag + ret nc ; Screen is off already. Exit. +; Loop until we are in VBlank +.wait: + ld a, [rLY] + cp 145 ; Is display on scan line 145 yet? + jr nz, .wait ; no, keep waiting +; Turn off the LCD + ld a, [rLCDC] + res 7, a ; Reset bit 7 of LCDC + ld [rLCDC], a +; Return + ret + + +; -------------------------------------------------------------------------- +; startLCD - Start the LCD (turn on screen) +; -------------------------------------------------------------------------- +startLCD: + ld a, LCDCF_ON | LCDCF_BG8000 | LCDCF_BG9800 | LCDCF_BGON | LCDCF_OBJ8 | LCDCF_OBJON + ld [rLCDC], a ; Turn screen on + ret + + +; Generate a full 256 character font set. +font: + chr_IBMPC1 1,8 + +helloWorld: + db "Hello world!" + +; SECTION ------------------------------------------------------------------ + +SECTION "Stack",BSS + +stack: + DS $200 +topOfStack: \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/rom/rom9/rom9.gb ============================================================================== Binary file. No diff available. Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Mon Apr 21 21:33:40 2008 @@ -1,10 +1,16 @@ import py +from pypy.lang.gameboy import constants from pypy.lang.gameboy.cartridge import * +# ------------------------------------------------------------------------------ -ROM_PATH = py.magic.autopath().dirpath().dirpath()+"/rom" +def mapToByte(value): + return ord(value) & 0xFF +ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" +CONTENT = "abcdefghijklmnopqrstuvwxyz1234567890" +MAPPED_CONTENT = map(mapToByte, CONTENT) # ------------------------------------------------------------------------------ @@ -12,13 +18,92 @@ pass def get_cartridge(): - return Cartridge() - + ctrg = Cartridge() + return ctrg +class File(object): + def __init__(self, data): + self.data = data + + def read(self, size=0): + if size == 0: + return self.data + + def write(self, data): + self.data = data + + def seek(self, value): + pass # ------------------------------------------------------------------------------ # STORE MANAGER TEST ----------------------------------------------------------- -def test_store_manager_init(): - cartridge = get_cartridge_managers() + +def test_cartridge_init(): + cartridge = get_cartridge() + + assert cartridge.cartridgeName == "" + assert cartridge.cartridgeFilePath == "" + assert cartridge.cartridgeFile == None + + assert cartridge.batteryName == "" + assert cartridge.batteryFilePath == "" + assert cartridge.batteryFile == None + + +def rest_cartridge_load(): + cartridge = get_cartridge() + romName = "rom1.raw" + romFilePath = ROM_PATH+"/rom1/"+romName + + cartridge.load(romFilePath) + assert cartridge.cartridgeName == romName + assert cartridge.cartridgeFilePath == romFilePath + assert cartridge.cartridgeFile != None + + assert cartridge.batteryName == romFile+constants.BATTERY_FILE_EXTENSION + assert cartridge.batteryFilePath == romFilePath+constants.BATTERY_FILE_EXTENSION + assert cartridge.hasBattery() == False + assert cartridge.batteryFile == None + + +def test_cartridge_hasBattery(): + cartridge = get_cartridge() + + romName = "rom1.raw" + romFilePath = ROM_PATH+"/rom1/"+romName + + cartridge.load(romFilePath) + assert cartridge.hasBattery() == False + + +def test_cartridge_read(): + cartridge = get_cartridge() + cartridge.cartridgeFile = File(CONTENT) + + assert cartridge.read() == MAPPED_CONTENT + + +def test_cartridge_remove_write_read_Battery(): + cartridge = get_cartridge() + + romName = "rom1.raw" + romFilePath = ROM_PATH + "/rom1/"+romName + + cartridge.load(romFilePath) + cartridge.removeBattery() + assert cartridge.hasBattery() == False + + cartridge.writeBattery(MAPPED_CONTENT) + assert cartridge.hasBattery() == True + print cartridge.batteryFile + assert cartridge.batteryFile.read() == CONTENT + assert cartridge.readBattery() == MAPPED_CONTENT + + cartridge.removeBattery() + assert cartridge.hasBattery() == False + + + + \ No newline at end of file From cami at codespeak.net Mon Apr 21 21:36:33 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 21 Apr 2008 21:36:33 +0200 (CEST) Subject: [pypy-svn] r53983 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080421193633.6B6ED2A00DC@codespeak.net> Author: cami Date: Mon Apr 21 21:36:30 2008 New Revision: 53983 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Log: the semicolon killer was here ;) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Mon Apr 21 21:36:30 2008 @@ -219,13 +219,13 @@ self.cycles = 0 def resetRegisters(self): - self.a.reset(); - self.f.reset(); - self.bc.reset(); - self.de.reset(); - self.hl.reset(); - self.sp.reset(); - self.pc.reset(); + self.a.reset() + self.f.reset() + self.bc.reset() + self.de.reset() + self.hl.reset() + self.sp.reset() + self.pc.reset() def getAF(self): return self.af @@ -442,7 +442,7 @@ self.f.reset(keepZ=True) self.f.hFlagCompare((added >> 8), self.hl) self.f.cFlagCompare(added, self.hl) - self.hl.set(added); + self.hl.set(added) self.cycles -= 1 # 1 cycle @@ -759,7 +759,7 @@ # CCF/SCF def complementCarryFlag(self): self.f.reset(keepZ=True, keepC=True) - self.f.cFlag = not self.f.cFlag; + self.f.cFlag = not self.f.cFlag def setCarryFlag(self): self.f.reset(keepZ=True) @@ -832,7 +832,7 @@ # DI/EI 1 cycle def disableInterrupts(self): self.ime = False - self.cycles -= 1; + self.cycles -= 1 # 1 cycle def enableInterrupts(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Mon Apr 21 21:36:30 2008 @@ -102,7 +102,7 @@ return code def isRaised(self): - raised = self.raised; + raised = self.raised self.raised = False return raised Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Mon Apr 21 21:36:30 2008 @@ -113,8 +113,8 @@ self.frames = 0 self.audio1Index = self.audio2Index = self.audio3Index = self.audio4Index = 0 self.write(constants.NR10, 0x80) - self.write(constants.NR11, 0x3F); # 0xBF - self.write(constants.NR12, 0x00); # 0xF3 + self.write(constants.NR11, 0x3F) # 0xBF + self.write(constants.NR12, 0x00) # 0xF3 self.write(constants.NR13, 0xFF) self.write(constants.NR14, 0xBF) @@ -134,9 +134,9 @@ self.write(constants.NR43, 0x00) self.write(constants.NR44, 0xBF) - self.write(constants.NR50, 0x00); # 0x77 + self.write(constants.NR50, 0x00) # 0x77 self.write(constants.NR51, 0xF0) - self.write(constants.NR52, 0xFF); # 0xF0 + self.write(constants.NR52, 0xFF) # 0xF0 for address in range(0xFF30, 0xFF3F): write = 0xFF From antocuni at codespeak.net Tue Apr 22 10:54:24 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Apr 2008 10:54:24 +0200 (CEST) Subject: [pypy-svn] r53989 - pypy/branch/jit-hotpath/pypy/translator/backendopt/test Message-ID: <20080422085424.64943168440@codespeak.net> Author: antocuni Date: Tue Apr 22 10:54:22 2008 New Revision: 53989 Modified: pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py Log: TestOOType passes out of the box; I couldn't find any test that passes on lltype but fails on ootype due to lack of "pure" annotation to builtin methods Modified: pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py Tue Apr 22 10:54:22 2008 @@ -61,11 +61,20 @@ res = impurity.analyze_direct_call(self.translator.graphs[0]) assert res is False # not impure +# XXX failing test +## def test_builtin_method(self): +## def fn(flag): +## if flag: +## s = "foo" + str(flag) +## else: +## s = "bar" + str(flag) +## return len(s) +## impurity = self.translate(fn, [bool]) +## res = impurity.analyze_direct_call(self.translator.graphs[0]) +## assert res is False # not impure class TestLLType(LLRtypeMixin, BaseTestImpurityAnalyzer): pass -# no chance on OOType before we add "pure" annotations on -# all the relevant built-in methods -#class TestOOType(OORtypeMixin, BaseTestImpurityAnalyzer): -# pass +class TestOOType(OORtypeMixin, BaseTestImpurityAnalyzer): + pass From arigo at codespeak.net Tue Apr 22 10:54:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 10:54:39 +0200 (CEST) Subject: [pypy-svn] r53990 - pypy/branch/io-improvements/pypy/rpython/memory/gctransform Message-ID: <20080422085439.4E859168441@codespeak.net> Author: arigo Date: Tue Apr 22 10:54:38 2008 New Revision: 53990 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py Log: Revert no-op changes. Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py Tue Apr 22 10:54:38 2008 @@ -4,7 +4,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rpython import rmodel class BoehmGCTransformer(GCTransformer): malloc_zero_filled = True @@ -141,6 +140,7 @@ resulttype = lltype.Signed) hop.genop('int_invert', [v_int], resultvar=hop.spaceop.result) + ########## weakrefs ########## # Boehm: weakref objects are small structures containing only a Boehm # disappearing link. We don't have to hide the link's value with From arigo at codespeak.net Tue Apr 22 10:58:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 10:58:11 +0200 (CEST) Subject: [pypy-svn] r53991 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080422085811.5865B168441@codespeak.net> Author: arigo Date: Tue Apr 22 10:58:10 2008 New Revision: 53991 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Log: In the way gct_malloc_nonmovable is defined in the default gc transformer class, these operations can also raise MemoryError. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Tue Apr 22 10:58:10 2008 @@ -322,8 +322,8 @@ 'malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'malloc_nonmovable': LLOp(canunwindgc=True), - 'malloc_nonmovable_varsize': LLOp(canunwindgc=True), + 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), From arigo at codespeak.net Tue Apr 22 11:11:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:11:03 +0200 (CEST) Subject: [pypy-svn] r53992 - pypy/branch/io-improvements/pypy/rpython/memory/gctransform Message-ID: <20080422091103.C6517168506@codespeak.net> Author: arigo Date: Tue Apr 22 11:11:03 2008 New Revision: 53992 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Log: Clean-ups to minimize the diff. Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Tue Apr 22 11:11:03 2008 @@ -491,10 +491,8 @@ assert not TYPE._is_varsize() flags = hop.spaceop.args[1].value flavor = flags['flavor'] - if flavor == 'nonmovable': - flavor = 'gc' meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) - assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) + assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) v_raw = meth(hop, flags, TYPE, c_size) hop.cast_result(v_raw) @@ -511,16 +509,15 @@ resulttype=llmemory.Address) if flags.get('zero'): hop.genop("raw_memclear", [v_raw, c_size]) - return v_raw + return v_raw def gct_malloc_varsize(self, hop): - op = hop.spaceop - TYPE = op.result.concretetype.TO + flags = hop.spaceop.args[1].value flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) - assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) + assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) gct_malloc_nonmovable = gct_malloc From arigo at codespeak.net Tue Apr 22 11:15:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:15:23 +0200 (CEST) Subject: [pypy-svn] r53993 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080422091523.D32B0168508@codespeak.net> Author: arigo Date: Tue Apr 22 11:15:23 2008 New Revision: 53993 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Log: This is not much code, but let's make sure it is inlined to avoid the allocation of the tuple. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Tue Apr 22 11:15:23 2008 @@ -521,6 +521,7 @@ else: raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') return raw_buf, lltype.nullptr(STR) +alloc_buffer._always_inline_ = True # to get rid of the returned tuple obj # (char*, str, int, int) -> None def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): From arigo at codespeak.net Tue Apr 22 11:27:16 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:27:16 +0200 (CEST) Subject: [pypy-svn] r53994 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080422092716.4458C1684D8@codespeak.net> Author: arigo Date: Tue Apr 22 11:27:15 2008 New Revision: 53994 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Log: Cancel no-op diff. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Tue Apr 22 11:27:15 2008 @@ -761,7 +761,7 @@ return dwn OUTSIDE = getattr(OUTSIDE, first) return -1 - + def castable(PTRTYPE, CURTYPE): if CURTYPE.TO._gckind != PTRTYPE.TO._gckind: raise TypeError("cast_pointer() cannot change the gc status: %s to %s" From arigo at codespeak.net Tue Apr 22 11:32:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:32:12 +0200 (CEST) Subject: [pypy-svn] r53995 - in pypy/branch/io-improvements/pypy: rlib rpython/lltypesystem rpython/lltypesystem/test rpython/module Message-ID: <20080422093212.5E0A81684D9@codespeak.net> Author: arigo Date: Tue Apr 22 11:32:09 2008 New Revision: 53995 Modified: pypy/branch/io-improvements/pypy/rlib/rzlib.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Log: Use the simpler try:finally: style where we allocate on the line before the try:, instead of initializing the variable with NULL. Modified: pypy/branch/io-improvements/pypy/rlib/rzlib.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rzlib.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rzlib.py Tue Apr 22 11:32:09 2008 @@ -154,8 +154,8 @@ Compute the CRC32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ + bytes = rffi.get_nonmovingbuffer(string) try: - bytes = rffi.get_nonmovingbuffer(string) checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) finally: rffi.free_nonmovingbuffer(string, bytes) @@ -169,8 +169,8 @@ Compute the Adler-32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ + bytes = rffi.get_nonmovingbuffer(string) try: - bytes = rffi.get_nonmovingbuffer(string) checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) finally: rffi.free_nonmovingbuffer(string, bytes) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Tue Apr 22 11:32:09 2008 @@ -533,9 +533,8 @@ str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) if gc_buf: if allocated_size != needed_size: - new_buf = lltype.nullptr(STR) + new_buf = lltype.malloc(STR, needed_size) try: - new_buf = lltype.malloc(STR, needed_size) dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: This is bad, because dest could potentially move ## if there are threads involved. @@ -545,9 +544,8 @@ keepalive_until_here(new_buf) return hlstr(gc_buf) else: - new_buf = lltype.nullptr(STR) + new_buf = lltype.malloc(STR, needed_size) try: - new_buf = lltype.malloc(STR, needed_size) dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: see above raw_memcopy(cast_ptr_to_adr(raw_buf), dest, sizeof(lltype.Char) * needed_size) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Tue Apr 22 11:32:09 2008 @@ -434,10 +434,8 @@ def test_nonmoving(self): d = 'non-moving data stuff' def f(): - gc_buf = lltype.nullptr(STR) - raw_buf = lltype.nullptr(CCHARP.TO) + raw_buf, gc_buf = alloc_buffer(len(d)) try: - raw_buf, gc_buf = alloc_buffer(len(d)) for i in range(len(d)): raw_buf[i] = d[i] return str_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) @@ -450,9 +448,8 @@ def test_nonmovingbuffer(self): d = 'some cool data that should not move' def f(): - buf = lltype.nullptr(CCHARP.TO) + buf = get_nonmovingbuffer(d) try: - buf = get_nonmovingbuffer(d) counter = 0 for i in range(len(d)): if buf[i] == d[i]: @@ -466,9 +463,8 @@ def test_nonmovingbuffer_semispace(self): d = 'some cool data that should not move' def f(): - buf = lltype.nullptr(CCHARP.TO) + buf = get_nonmovingbuffer(d) try: - buf = get_nonmovingbuffer(d) counter = 0 for i in range(len(d)): if buf[i] == d[i]: Modified: pypy/branch/io-improvements/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/io-improvements/pypy/rpython/module/ll_os.py Tue Apr 22 11:32:09 2008 @@ -487,10 +487,8 @@ def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) - raw_buf = lltype.nullptr(rffi.CCHARP.TO) - gc_buf = lltype.nullptr(STR) + raw_buf, gc_buf = rffi.alloc_buffer(count) try: - raw_buf, gc_buf = rffi.alloc_buffer(count) void_buf = rffi.cast(rffi.VOIDP, raw_buf) got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count)) if got < 0: @@ -512,10 +510,9 @@ rffi.SIZE_T) def os_write_llimpl(fd, data): - buf = lltype.nullptr(rffi.CCHARP.TO) + count = len(data) + buf = rffi.get_nonmovingbuffer(data) try: - count = len(data) - buf = rffi.get_nonmovingbuffer(data) written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), buf, rffi.cast(rffi.SIZE_T, count))) From arigo at codespeak.net Tue Apr 22 11:39:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:39:04 +0200 (CEST) Subject: [pypy-svn] r53996 - pypy/branch/io-improvements/pypy/rpython/memory/gc Message-ID: <20080422093904.7CF4A168509@codespeak.net> Author: arigo Date: Tue Apr 22 11:39:02 2008 New Revision: 53996 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py Log: Move the 'can_move' method in the base classes. Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py Tue Apr 22 11:39:02 2008 @@ -105,6 +105,9 @@ def id(self, ptr): return lltype.cast_ptr_to_int(ptr) + def can_move(self, addr): + return False + def set_max_heap_size(self, size): pass @@ -260,6 +263,9 @@ self.object_id_dict_ends_at = i + 1 return i + 1 # this produces id() values 1, 2, 3, 4... + def can_move(self, addr): + return True + def notify_objects_just_moved(self): self.object_id_dict_ends_at = -1 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/marksweep.py Tue Apr 22 11:39:02 2008 @@ -38,6 +38,7 @@ POOLNODEPTR = lltype.Ptr(POOLNODE) POOLNODE.become(lltype.Struct('gc_pool_node', ('linkedlist', HDRPTR), ('nextnode', POOLNODEPTR))) + def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096): self.heap_usage = 0 # at the end of the latest collection self.bytes_malloced = 0 # since the latest collection @@ -692,8 +693,6 @@ # reinstall the pool that was current at the beginning of x_clone() clonedata.pool = self.x_swap_pool(curpool) - def can_move(self, addr): - return False class PrintingMarkSweepGC(MarkSweepGC): _alloc_flavor_ = "raw" Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/semispace.py Tue Apr 22 11:39:02 2008 @@ -537,8 +537,5 @@ finally: self.finalizer_lock_count -= 1 - def can_move(self, addr): - return True - STATISTICS_NUMBERS = 0 From arigo at codespeak.net Tue Apr 22 11:42:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:42:09 +0200 (CEST) Subject: [pypy-svn] r53997 - in pypy/branch/io-improvements/pypy/rpython: . lltypesystem memory test Message-ID: <20080422094209.BA0B21683E4@codespeak.net> Author: arigo Date: Tue Apr 22 11:42:09 2008 New Revision: 53997 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py Log: Don't pass this as yet another flag. The way it's supposed to be done is by delegating to the 'heap' object, which can itself delegate to the gc (or use a default impl in llheap.py). Note that gc_can_move cannot easily be marked as 'can_fold' because it can only be folded if a specific GC was choosen and is accessible. Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Tue Apr 22 11:42:09 2008 @@ -43,7 +43,7 @@ """ low level interpreter working with concrete values. """ def __init__(self, typer, tracing=True, exc_data_ptr=None, - malloc_check=True, moving_gc=True): + malloc_check=True): self.bindings = {} self.typer = typer # 'heap' is module or object that provides malloc, etc for lltype ops @@ -54,7 +54,6 @@ self.malloc_check = malloc_check self.frame_class = LLFrame self.mallocs = {} - self.moving_gc = moving_gc if tracing: self.tracer = Tracer() @@ -754,15 +753,15 @@ def op_gc__collect(self): self.heap.collect() - def op_gc_can_move(self, p): - return self.llinterpreter.moving_gc - def op_gc__disable_finalizers(self): self.heap.disable_finalizers() def op_gc__enable_finalizers(self): self.heap.enable_finalizers() + def op_gc_can_move(self, addr): + return self.heap.can_move(addr) + def op_gc_free(self, addr): # what can you do? pass Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py Tue Apr 22 11:42:09 2008 @@ -6,6 +6,7 @@ setfield = setattr from operator import setitem as setarrayitem from pypy.rlib.rgc import collect, disable_finalizers, enable_finalizers +from pypy.rlib.rgc import can_move def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue): assert typeOf(newvalue) == INNERTYPE Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Tue Apr 22 11:42:09 2008 @@ -399,7 +399,7 @@ 'gc_reload_possibly_moved': LLOp(), 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False), 'gc_set_max_heap_size': LLOp(), - 'gc_can_move' : LLOp(canfold=True, sideeffects=False), + 'gc_can_move' : LLOp(sideeffects=False), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), Modified: pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py Tue Apr 22 11:42:09 2008 @@ -87,6 +87,9 @@ def enable_finalizers(self): self.gc.enable_finalizers() + def can_move(self, addr): + return self.gc.can_move(addr) + def weakref_create_getlazy(self, objgetter): # we have to be lazy in reading the llinterp variable containing # the 'obj' pointer, because the gc.malloc() call below could Modified: pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_llinterp.py Tue Apr 22 11:42:09 2008 @@ -72,8 +72,7 @@ def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", backendopt=False, - config=None, malloc_check=True, - moving_gc=True, **extraconfigopts): + config=None, malloc_check=True, **extraconfigopts): extra_key = [(key, value) for key, value in extraconfigopts.iteritems()] extra_key.sort() extra_key = tuple(extra_key) @@ -98,8 +97,7 @@ viewbefore, policy, type_system=type_system, backendopt=backendopt, config=config, **extraconfigopts) - interp = LLInterpreter(typer, malloc_check=malloc_check, - moving_gc=moving_gc) + interp = LLInterpreter(typer, malloc_check=malloc_check) _tcache[key] = (t, interp, graph) # keep the cache small _lastinterpreted.append(key) @@ -113,12 +111,11 @@ def interpret(func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", backendopt=False, - config=None, malloc_check=True, moving_gc=True): + config=None, malloc_check=True): interp, graph = get_interpreter(func, values, view, viewbefore, policy, someobjects, type_system=type_system, backendopt=backendopt, config=config, - malloc_check=malloc_check, - moving_gc=moving_gc) + malloc_check=malloc_check) result = interp.eval_graph(graph, values) if malloc_check and interp.mallocs: raise MallocMismatch(interp.mallocs) @@ -126,11 +123,10 @@ def interpret_raises(exc, func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", - backendopt=False, moving_gc=True): + backendopt=False): interp, graph = get_interpreter(func, values, view, viewbefore, policy, someobjects, type_system=type_system, - backendopt=backendopt, - moving_gc=moving_gc) + backendopt=backendopt) info = py.test.raises(LLException, "interp.eval_graph(graph, values)") try: got = interp.find_exception(info.value) From arigo at codespeak.net Tue Apr 22 11:44:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:44:02 +0200 (CEST) Subject: [pypy-svn] r53998 - pypy/branch/io-improvements/pypy/rpython/test Message-ID: <20080422094402.18D7C168570@codespeak.net> Author: arigo Date: Tue Apr 22 11:44:02 2008 New Revision: 53998 Modified: pypy/branch/io-improvements/pypy/rpython/test/tool.py Log: Forgot to revert this file along with the previous checkin. Modified: pypy/branch/io-improvements/pypy/rpython/test/tool.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/tool.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/tool.py Tue Apr 22 11:44:02 2008 @@ -6,7 +6,6 @@ class BaseRtypingTest(object): FLOAT_PRECISION = 8 - MOVING_GC = True def gengraph(self, func, argtypes=[], viewbefore='auto', policy=None, backendopt=False, config=None): @@ -14,12 +13,10 @@ backendopt=backendopt, config=config) def interpret(self, fn, args, **kwds): - return interpret(fn, args, type_system=self.type_system, - moving_gc=self.MOVING_GC, **kwds) + return interpret(fn, args, type_system=self.type_system, **kwds) def interpret_raises(self, exc, fn, args, **kwds): - return interpret_raises(exc, fn, args, type_system=self.type_system, - moving_gc=self.MOVING_GC, **kwds) + return interpret_raises(exc, fn, args, type_system=self.type_system, **kwds) def float_eq(self, x, y): return x == y @@ -43,7 +40,7 @@ if skipLL and self.type_system == 'lltype': py.test.skip("lltypesystem doesn't support %s, yet" % reason) if skipOO and self.type_system == 'ootype': - py.test.skip("ootypesystem doesn't support %s, yet" % reason) + py.test.skip("ootypesystem doesn't support %s, yet" % reason) class LLRtypeMixin(object): type_system = 'lltype' From arigo at codespeak.net Tue Apr 22 11:44:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:44:40 +0200 (CEST) Subject: [pypy-svn] r53999 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080422094440.29D02168572@codespeak.net> Author: arigo Date: Tue Apr 22 11:44:39 2008 New Revision: 53999 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py Log: Kill kill Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Tue Apr 22 11:44:39 2008 @@ -673,13 +673,6 @@ self.llinterpreter.remember_malloc(ptr, self) return ptr - def op_coalloc(self, obj, coallocator, flags): - flavor = flags['flavor'] - assert flavor == "gc" - zero = flags.get('zero', False) - ptr = self.heap.coalloc(obj, coallocator, zero=zero) - return ptr - def op_malloc_varsize(self, obj, flags, size): flavor = flags['flavor'] zero = flags.get('zero', False) @@ -692,14 +685,6 @@ except MemoryError: self.make_llexception() - def op_coalloc_varsize(self, obj, coallocator, flags, size): - flavor = flags['flavor'] - zero = flags.get('zero', False) - assert flavor == "gc" - zero = flags.get('zero', False) - ptr = self.heap.coalloc(obj, coallocator, size, zero=zero) - return ptr - def op_free(self, obj, flavor): assert isinstance(flavor, str) if flavor == 'raw' and self.llinterpreter.malloc_check: From arigo at codespeak.net Tue Apr 22 11:48:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:48:58 +0200 (CEST) Subject: [pypy-svn] r54000 - in pypy/branch/io-improvements/pypy: config rpython/lltypesystem rpython/memory rpython/memory/gc rpython/memory/test translator/backendopt translator/backendopt/test Message-ID: <20080422094858.8378C168572@codespeak.net> Author: arigo Date: Tue Apr 22 11:48:57 2008 New Revision: 54000 Removed: pypy/branch/io-improvements/pypy/translator/backendopt/coalloc.py pypy/branch/io-improvements/pypy/translator/backendopt/test/test_coalloc.py Modified: pypy/branch/io-improvements/pypy/config/translationoption.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py pypy/branch/io-improvements/pypy/rpython/memory/gc/generation.py pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py pypy/branch/io-improvements/pypy/translator/backendopt/all.py Log: Kill all references to coalloc. Modified: pypy/branch/io-improvements/pypy/config/translationoption.py ============================================================================== --- pypy/branch/io-improvements/pypy/config/translationoption.py (original) +++ pypy/branch/io-improvements/pypy/config/translationoption.py Tue Apr 22 11:48:57 2008 @@ -174,9 +174,6 @@ BoolOption("heap2stack", "Escape analysis and stack allocation", default=False, requires=[("translation.stackless", False)]), - BoolOption("coalloc", "Try to replace mallocs by coallocation", - default=False, - suggests=[("translation.gc", "generation")]), # control profile based inlining StrOption("profile_based_inline", "Use call count profiling to drive inlining" Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py Tue Apr 22 11:48:57 2008 @@ -17,7 +17,3 @@ def weakref_create_getlazy(objgetter): return weakref_create(objgetter()) - -def coalloc(T, coallocator, n=None, zero=True): - # ignore the coallocator - return malloc(T, n, zero=zero) Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py Tue Apr 22 11:48:57 2008 @@ -44,16 +44,13 @@ def size_gc_header(self, typeid=0): return self.gcheaderbuilder.size_gc_header - def malloc(self, typeid, length=0, zero=False, coallocator=None): + def malloc(self, typeid, length=0, zero=False): """For testing. The interface used by the gctransformer is the four malloc_[fixed,var]size[_clear]() functions. - And (if they exist) to the coalloc_[fixed,var]size_clear functions """ # Rules about fallbacks in case of missing malloc methods: # * malloc_fixedsize_clear() and malloc_varsize_clear() are mandatory # * malloc_fixedsize() and malloc_varsize() fallback to the above - # * coalloc_fixedsize_clear() and coalloc_varsize_clear() are optional - # There is no non-clear version of coalloc for now. # XXX: as of r49360, gctransformer.framework never inserts calls # to malloc_varsize(), but always uses malloc_varsize_clear() @@ -72,33 +69,19 @@ assert not contains_weakptr itemsize = self.varsize_item_sizes(typeid) offset_to_length = self.varsize_offset_to_length(typeid) - if (coallocator is not None and - hasattr(self, "coalloc_varsize_clear")): - assert not needs_finalizer - coallocator = llmemory.cast_ptr_to_adr(coallocator) - ref = self.coalloc_varsize_clear(coallocator, typeid, - length, size, - itemsize, offset_to_length) + if zero or not hasattr(self, 'malloc_varsize'): + malloc_varsize = self.malloc_varsize_clear else: - if zero or not hasattr(self, 'malloc_varsize'): - malloc_varsize = self.malloc_varsize_clear - else: - malloc_varsize = self.malloc_varsize - ref = malloc_varsize(typeid, length, size, itemsize, - offset_to_length, True, needs_finalizer) + malloc_varsize = self.malloc_varsize + ref = malloc_varsize(typeid, length, size, itemsize, + offset_to_length, True, needs_finalizer) else: - if (coallocator is not None and - hasattr(self, "coalloc_fixedsize_clear")): - assert not needs_finalizer - coallocator = llmemory.cast_ptr_to_adr(coallocator) - ref = self.coalloc_fixedsize_clear(coallocator, typeid, size) + if zero or not hasattr(self, 'malloc_fixedsize'): + malloc_fixedsize = self.malloc_fixedsize_clear else: - if zero or not hasattr(self, 'malloc_fixedsize'): - malloc_fixedsize = self.malloc_fixedsize_clear - else: - malloc_fixedsize = self.malloc_fixedsize - ref = malloc_fixedsize(typeid, size, True, needs_finalizer, - contains_weakptr) + malloc_fixedsize = self.malloc_fixedsize + ref = malloc_fixedsize(typeid, size, True, needs_finalizer, + contains_weakptr) # lots of cast and reverse-cast around... return llmemory.cast_ptr_to_adr(ref) Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/generation.py Tue Apr 22 11:48:57 2008 @@ -146,18 +146,6 @@ self.young_objects_with_weakrefs.append(result + size_gc_header) return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - def coalloc_fixedsize_clear(self, coallocator, typeid, size): - # note: a coallocated object can never return a weakref, since the - # coallocation analysis is done at a time where weakrefs are - # represented as opaque objects which aren't allocated using malloc but - # with weakref_create - if self.is_in_nursery(coallocator): - return self.malloc_fixedsize_clear(typeid, size, - True, False, False) - else: - return SemiSpaceGC.malloc_fixedsize_clear(self, typeid, size, - True, False, False) - def malloc_varsize_clear(self, typeid, length, size, itemsize, offset_to_length, can_collect, has_finalizer=False): @@ -205,17 +193,6 @@ self.nursery_free = result + llarena.round_up_for_allocation(totalsize) return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - def coalloc_varsize_clear(self, coallocator, typeid, - length, size, itemsize, - offset_to_length): - if self.is_in_nursery(coallocator): - return self.malloc_varsize_clear(typeid, length, size, itemsize, - offset_to_length, True, False) - else: - return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size, - itemsize, offset_to_length, - True, False) - # override the init_gc_object methods to change the default value of 'flags', # used by objects that are directly created outside the nursery by the SemiSpaceGC. # These objects must have the GCFLAG_NO_YOUNG_PTRS flag set immediately. Modified: pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py Tue Apr 22 11:48:57 2008 @@ -46,17 +46,6 @@ assert flavor != 'gc' return lltype.free(TYPE, flavor=flavor) - def coalloc(self, TYPE, coallocator, size=None, zero=False): - if hasattr(self.gc, "coalloc_fixedsize_clear"): - typeid = self.get_type_id(TYPE) - addr = self.gc.malloc(typeid, size, zero=zero, - coallocator=coallocator) - result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) - if not self.gc.malloc_zero_filled: - gctypelayout.zero_gc_pointers(result) - return result - return self.malloc(TYPE, size, 'gc', zero) - def setfield(self, obj, fieldname, fieldvalue): STRUCT = lltype.typeOf(obj).TO addr = llmemory.cast_ptr_to_adr(obj) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Tue Apr 22 11:48:57 2008 @@ -400,17 +400,3 @@ class TestGenerationalGC(TestSemiSpaceGC): from pypy.rpython.memory.gc.generation import GenerationGC as GCClass - - def test_coalloc(self): - def malloc_a_lot(): - i = 0 - while i < 10: - i += 1 - a = [1] * 10 - j = 0 - while j < 30: - j += 1 - a.append(j) - return 0 - res = self.interpret(malloc_a_lot, [], backendopt=True, coalloc=True) - assert res == 0 Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Tue Apr 22 11:48:57 2008 @@ -762,22 +762,6 @@ res = run([3, 0]) assert res == 1 - def test_coalloc(self): - def malloc_a_lot(): - i = 0 - while i < 10: - i += 1 - a = [1] * 10 - j = 0 - while j < 30: - j += 1 - a.append(j) - return 0 - run, statistics = self.runner(malloc_a_lot, statistics=True, - backendopt=True, coalloc=True) - run([]) - - class TestStacklessMarkSweepGC(TestMarkSweepGC): gcname = "marksweep" Modified: pypy/branch/io-improvements/pypy/translator/backendopt/all.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/backendopt/all.py (original) +++ pypy/branch/io-improvements/pypy/translator/backendopt/all.py Tue Apr 22 11:48:57 2008 @@ -130,10 +130,6 @@ print "after if-to-switch:" print_statistics(translator.graphs[0], translator) - if config.coalloc and not secondary: - from pypy.translator.backendopt import coalloc - coalloc.malloc_to_coalloc(translator) - remove_obvious_noops() for graph in graphs: From arigo at codespeak.net Tue Apr 22 11:51:41 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 11:51:41 +0200 (CEST) Subject: [pypy-svn] r54001 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080422095141.DBB11168573@codespeak.net> Author: arigo Date: Tue Apr 22 11:51:41 2008 New Revision: 54001 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py Log: This was a nice wish but it's not implemented. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py Tue Apr 22 11:51:41 2008 @@ -204,11 +204,6 @@ assert typeOf(p3) == Ptr(S3) assert p1b == cast_pointer(Ptr(S1bis), p3) py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") - A1 = FixedSizeArray(Char, 1) - A2 = Array(Char, hints={'nolength':True}) - p = malloc(A1, flavor='raw') - p2 = cast_pointer(Ptr(A2), p) - assert p2 == p def test_best_effort_gced_parent_detection(): py.test.skip("test not relevant any more") From antocuni at codespeak.net Tue Apr 22 12:23:31 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Apr 2008 12:23:31 +0200 (CEST) Subject: [pypy-svn] r54002 - pypy/branch/jit-hotpath/pypy/translator/backendopt/test Message-ID: <20080422102331.9139016843C@codespeak.net> Author: antocuni Date: Tue Apr 22 12:23:31 2008 New Revision: 54002 Modified: pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py Log: this test cannot really pass Modified: pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py (original) +++ pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py Tue Apr 22 12:23:31 2008 @@ -61,18 +61,6 @@ res = impurity.analyze_direct_call(self.translator.graphs[0]) assert res is False # not impure -# XXX failing test -## def test_builtin_method(self): -## def fn(flag): -## if flag: -## s = "foo" + str(flag) -## else: -## s = "bar" + str(flag) -## return len(s) -## impurity = self.translate(fn, [bool]) -## res = impurity.analyze_direct_call(self.translator.graphs[0]) -## assert res is False # not impure - class TestLLType(LLRtypeMixin, BaseTestImpurityAnalyzer): pass From arigo at codespeak.net Tue Apr 22 12:53:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 12:53:39 +0200 (CEST) Subject: [pypy-svn] r54003 - pypy/dist/pypy/doc Message-ID: <20080422105339.7AADF1684C8@codespeak.net> Author: arigo Date: Tue Apr 22 12:53:37 2008 New Revision: 54003 Modified: pypy/dist/pypy/doc/extending.txt Log: ReST fixes. Modified: pypy/dist/pypy/doc/extending.txt ============================================================================== --- pypy/dist/pypy/doc/extending.txt (original) +++ pypy/dist/pypy/doc/extending.txt Tue Apr 22 12:53:37 2008 @@ -55,13 +55,13 @@ Only pure-python code (slow), problems with platform-dependency (although we partially solve those). PyPy implementation is now very slow. -_`CPython ctypes`: XXX link +_`CPython ctypes`: http://python.net/crew/theller/ctypes/ LibFFI ====== Mostly in order to be able to write a ctypes module, we developed a very -low-level libffi_ bindings. (libffi is a C-level library for dynamic calling, +low-level libffi bindings. (libffi is a C-level library for dynamic calling, which is used by CPython ctypes). This library provides stable and usable API, although it's API is a very low-level one. It does not contain any magic. @@ -78,8 +78,6 @@ Slow. CPython-incompatible API, very rough and low-level -.. _libffi: XXX link - Mixed Modules ============= @@ -99,7 +97,7 @@ Some document is available `here`_ -.. _`here`:: rffi.html +.. _`here`: rffi.html XXX we should provide detailed docs about lltype and rffi, especially if we want people to follow that way. From arigo at codespeak.net Tue Apr 22 12:57:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 12:57:07 +0200 (CEST) Subject: [pypy-svn] r54004 - pypy/dist/pypy/interpreter Message-ID: <20080422105707.458F91684C8@codespeak.net> Author: arigo Date: Tue Apr 22 12:57:06 2008 New Revision: 54004 Modified: pypy/dist/pypy/interpreter/pyframe.py Log: Reverting unless there is evidence that it's an improvement. To me it looks like the result is worse: * allocating an empty list is faster than pre-allocating items, so for frames that don't contain loops we loose * if there are loops, it's very uncommon to have more than 4 nested levels (which is the default allocation size). Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Tue Apr 22 12:57:06 2008 @@ -10,7 +10,7 @@ from pypy.rlib.objectmodel import we_are_translated, instantiate from pypy.rlib.jit import we_are_jitted, hint from pypy.rlib import rstack # for resume points -from pypy.rlib.objectmodel import newlist + # Define some opcodes used g = globals() @@ -54,7 +54,7 @@ eval.Frame.__init__(self, space, w_globals, code.co_nlocals) self.valuestack_w = [None] * code.co_stacksize self.valuestackdepth = 0 - self.blockstack = newlist(sizehint=20) + self.blockstack = [] if space.config.objspace.honor__builtins__: self.builtin = space.builtin.pick_builtin(w_globals) # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. From arigo at codespeak.net Tue Apr 22 13:01:16 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 13:01:16 +0200 (CEST) Subject: [pypy-svn] r54005 - pypy/dist/pypy/interpreter Message-ID: <20080422110116.024921684C8@codespeak.net> Author: arigo Date: Tue Apr 22 13:01:16 2008 New Revision: 54005 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: Revert r53913: its purpose is unknown and I doubt it gives any speed-up in a faassen build (feel free to prove me wrong, but please say so in the check-in message itself). Most importantly, it breaks existing tests (in interpreter/test/). Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Tue Apr 22 13:01:16 2008 @@ -818,16 +818,15 @@ raise BytecodeCorruption, "old opcode, no longer in use" def SETUP_LOOP(f, offsettoend, next_instr, *ignored): - #block = LoopBlock(f, next_instr + offsettoend) - block = FrameBlock(LOOP, f, next_instr + offsettoend) + block = LoopBlock(f, next_instr + offsettoend) f.blockstack.append(block) def SETUP_EXCEPT(f, offsettoend, next_instr, *ignored): - block = FrameBlock(EXCEPT, f, next_instr + offsettoend) + block = ExceptBlock(f, next_instr + offsettoend) f.blockstack.append(block) def SETUP_FINALLY(f, offsettoend, next_instr, *ignored): - block = FrameBlock(FINALLY, f, next_instr + offsettoend) + block = FinallyBlock(f, next_instr + offsettoend) f.blockstack.append(block) def WITH_CLEANUP(f, *ignored): @@ -1067,23 +1066,15 @@ return SContinueLoop(space.int_w(w_jump_to)) state_pack_variables = staticmethod(state_pack_variables) -LOOP = 0 -EXCEPT = 1 -FINALLY = 2 - -HANDLING_MASKS = [SBreakLoop.kind | SContinueLoop.kind, - SApplicationException.kind, -1] class FrameBlock: """Abstract base class for frame blocks from the blockstack, used by the SETUP_XXX and POP_BLOCK opcodes.""" - def __init__(self, tp, frame, handlerposition): - self.tp = tp + def __init__(self, frame, handlerposition): self.handlerposition = handlerposition self.valuestackdepth = frame.valuestackdepth - self.handling_mask = HANDLING_MASKS[tp] def __eq__(self, other): return (self.__class__ is other.__class__ and @@ -1102,9 +1093,6 @@ def cleanup(self, frame): "Clean up a frame when we normally exit the block." self.cleanupstack(frame) - if self.tp == FINALLY: - frame.pushvalue(frame.space.w_None) - frame.pushvalue(frame.space.w_None) # internal pickling interface, not using the standard protocol def _get_state_(self, space): @@ -1117,46 +1105,9 @@ return hint(next_instr, promote=True) def really_handle(self, frame, unroller): - if self.tp == LOOP: - 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.append(self) - return unroller.jump_to - else: - # jump to the end of the loop - self.cleanupstack(frame) - return self.handlerposition - elif self.tp == EXCEPT: - # 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.pushvalue(frame.space.wrap(unroller)) - frame.pushvalue(operationerr.w_value) - frame.pushvalue(operationerr.w_type) - return self.handlerposition # jump to the handler - else: - # 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.pushvalue(frame.space.wrap(unroller)) - frame.pushvalue(frame.space.w_None) - frame.pushvalue(frame.space.w_None) - return self.handlerposition # jump to the handler - - #def really_handle(self, frame, unroller): - # """ Purely abstract method - # """ - # raise NotImplementedError + """ Purely abstract method + """ + raise NotImplementedError class LoopBlock(FrameBlock): """A loop block. Stores the end-of-loop pointer in case of 'break'.""" From arigo at codespeak.net Tue Apr 22 13:12:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 13:12:38 +0200 (CEST) Subject: [pypy-svn] r54006 - pypy/branch/io-improvements/pypy/translator/c/test Message-ID: <20080422111238.625B42A00E1@codespeak.net> Author: arigo Date: Tue Apr 22 13:12:38 2008 New Revision: 54006 Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py Log: Fix test. Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_newgc.py Tue Apr 22 13:12:38 2008 @@ -829,7 +829,7 @@ assert data == "ello world\n" os.close(fd) - f1 = self.getcompiled(does_stuff, []) + f1 = self.getcompiled(does_stuff) f1() assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) From arigo at codespeak.net Tue Apr 22 13:14:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 13:14:44 +0200 (CEST) Subject: [pypy-svn] r54007 - pypy/branch/io-improvements/pypy Message-ID: <20080422111444.BEEA62A00E1@codespeak.net> Author: arigo Date: Tue Apr 22 13:14:44 2008 New Revision: 54007 Added: pypy/branch/io-improvements/pypy/FAILURES Log: These tests need to be fixed. Added: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/FAILURES Tue Apr 22 13:14:44 2008 @@ -0,0 +1,3 @@ +rpython/memory/test/test_transformed_gc.py -k test_tree_cloning +rpython/test/test_rbuiltin.py +rpython/module/test/test_posix.py From arigo at codespeak.net Tue Apr 22 13:15:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 13:15:23 +0200 (CEST) Subject: [pypy-svn] r54008 - pypy/branch/io-improvements/pypy Message-ID: <20080422111523.3CADC2A0190@codespeak.net> Author: arigo Date: Tue Apr 22 13:15:22 2008 New Revision: 54008 Modified: pypy/branch/io-improvements/pypy/FAILURES Log: This one too. Modified: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- pypy/branch/io-improvements/pypy/FAILURES (original) +++ pypy/branch/io-improvements/pypy/FAILURES Tue Apr 22 13:15:22 2008 @@ -1,3 +1,4 @@ rpython/memory/test/test_transformed_gc.py -k test_tree_cloning rpython/test/test_rbuiltin.py rpython/module/test/test_posix.py +rpython/lltypesystem/test/test_lloperation.py From arigo at codespeak.net Tue Apr 22 14:10:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 14:10:17 +0200 (CEST) Subject: [pypy-svn] r54009 - pypy/branch/io-improvements/pypy/rpython/memory/test Message-ID: <20080422121017.1A3EF168511@codespeak.net> Author: arigo Date: Tue Apr 22 14:10:16 2008 New Revision: 54009 Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: Failing test showing a missing zero_gc_pointers_inside. Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Tue Apr 22 14:10:16 2008 @@ -476,11 +476,13 @@ return run([]) def _test_malloc_nonmovable_fixsize(self): - TP = lltype.GcStruct('T', ('x', lltype.Float)) + S = lltype.GcStruct('S', ('x', lltype.Float)) + TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) def func(): try: from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP) + rgc.collect() if a: assert not rgc.can_move(a) return 0 From arigo at codespeak.net Tue Apr 22 14:12:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 14:12:07 +0200 (CEST) Subject: [pypy-svn] r54010 - pypy/branch/io-improvements/pypy Message-ID: <20080422121207.295EE1683DD@codespeak.net> Author: arigo Date: Tue Apr 22 14:12:06 2008 New Revision: 54010 Modified: pypy/branch/io-improvements/pypy/FAILURES Log: Mention it here. Modified: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- pypy/branch/io-improvements/pypy/FAILURES (original) +++ pypy/branch/io-improvements/pypy/FAILURES Tue Apr 22 14:12:06 2008 @@ -2,3 +2,4 @@ rpython/test/test_rbuiltin.py rpython/module/test/test_posix.py rpython/lltypesystem/test/test_lloperation.py +rpython/memory/test/test_transformed_gc.py -k test_malloc_nonmovable_fixsize From arigo at codespeak.net Tue Apr 22 14:19:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 14:19:30 +0200 (CEST) Subject: [pypy-svn] r54011 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080422121930.07E2016851F@codespeak.net> Author: arigo Date: Tue Apr 22 14:19:29 2008 New Revision: 54011 Modified: pypy/branch/io-improvements/pypy/rpython/rpbc.py Log: ll_str'ing a None is needed by test_asmgcroot.py, for some reason. Modified: pypy/branch/io-improvements/pypy/rpython/rpbc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/rpbc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/rpbc.py Tue Apr 22 14:19:29 2008 @@ -11,6 +11,7 @@ mangle, inputdesc, warning, impossible_repr from pypy.rpython import rclass from pypy.rpython import robject +from pypy.rpython.annlowlevel import llstr from pypy.rpython import callparse @@ -605,6 +606,9 @@ def none_call(self, hop): raise TyperError("attempt to call constant None") + def ll_str(self, none): + return llstr("None") + rtype_simple_call = none_call rtype_call_args = none_call From fijal at codespeak.net Tue Apr 22 14:48:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Apr 2008 14:48:34 +0200 (CEST) Subject: [pypy-svn] r54012 - pypy/dist/pypy/translator/c/test Message-ID: <20080422124834.8E92F2A00E1@codespeak.net> Author: fijal Date: Tue Apr 22 14:48:32 2008 New Revision: 54012 Modified: pypy/dist/pypy/translator/c/test/test_newgc.py Log: A test for gc.collect in callback 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 Tue Apr 22 14:48:32 2008 @@ -813,6 +813,50 @@ c_fn = self.getcompiled(f) assert c_fn() == 0 + def test_callback_with_collect(self): + py.test.skip("Segfaults") + from pypy.rlib.libffi import ffi_type_pointer, ffi_type_slong,\ + CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint + from pypy.rpython.lltypesystem import rffi + from pypy.rlib import rgc + import gc + + def callback(ll_args, ll_res, stuff): + a1 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[0])[0] + a2 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[1])[0] + res = rffi.cast(rffi.INTP, ll_res) + if a1 > a2: + res[0] = 1 + else: + res[0] = -1 + gc.collect() + + def f(): + libc = CDLL('libc.so.6') + qsort = libc.getpointer('qsort', [ffi_type_pointer, ffi_type_slong, + ffi_type_slong, ffi_type_pointer], + ffi_type_void) + + ptr = CallbackFuncPtr([ffi_type_pointer, ffi_type_pointer], + ffi_type_sint, callback) + + TP = rffi.CArray(rffi.INT) + to_sort = lltype.malloc(TP, 4, flavor='raw') + to_sort[0] = 4 + to_sort[1] = 3 + to_sort[2] = 1 + to_sort[3] = 2 + qsort.push_arg(rffi.cast(rffi.VOIDP, to_sort)) + qsort.push_arg(rffi.sizeof(rffi.INT)) + qsort.push_arg(4) + qsort.push_arg(rffi.cast(rffi.VOIDP, ptr.ll_closure)) + qsort.call(lltype.Void) + result = [to_sort[i] for i in range(4)] == [1,2,3,4] + lltype.free(to_sort, flavor='raw') + return int(result) + + c_fn = self.getcompiled(f) + assert c_fn() == 1 class TestUsingStacklessFramework(TestUsingFramework): From arigo at codespeak.net Tue Apr 22 14:56:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 14:56:38 +0200 (CEST) Subject: [pypy-svn] r54013 - pypy/dist/pypy/config Message-ID: <20080422125638.386F52A00E1@codespeak.net> Author: arigo Date: Tue Apr 22 14:56:37 2008 New Revision: 54013 Modified: pypy/dist/pypy/config/translationoption.py Log: Whack at the gc options a bit more. Now, if unspecified, the gcrootfinder should default to "shadowstack" (it defaulted to "ref" even when using a framework gc...). Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Tue Apr 22 14:56:37 2008 @@ -57,14 +57,18 @@ cmdline="--gc"), ChoiceOption("gctransformer", "GC transformer that is used - internal", ["boehm", "ref", "framework", "none"], - default="ref", cmdline=None), - ChoiceOption("gcrootfinder", "Strategy for finding GC Roots", - ["ref", "boehm", "shadowstack", "stackless", "llvmgc", - "asmgcc"], "ref", + default="ref", cmdline=None, + requires={ + "boehm": [("translation.gcrootfinder", "n/a")], + "ref": [("translation.gcrootfinder", "n/a")], + "none": [("translation.gcrootfinder", "n/a")], + }), + ChoiceOption("gcrootfinder", + "Strategy for finding GC Roots (framework GCs only)", + ["n/a", "shadowstack", "stackless", "llvmgc", "asmgcc"], + "shadowstack", cmdline="--gcrootfinder", requires={ - "ref": [("translation.gc", "ref")], - "boehm": [("translation.gc", "boehm")], "shadowstack": [("translation.gctransformer", "framework")], "stackless": [("translation.gctransformer", "framework"), ("translation.stackless", True)], From antocuni at codespeak.net Tue Apr 22 15:05:15 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 22 Apr 2008 15:05:15 +0200 (CEST) Subject: [pypy-svn] r54014 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080422130515.C4E3E2A018D@codespeak.net> Author: antocuni Date: Tue Apr 22 15:05:15 2008 New Revision: 54014 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Log: refactor a bit how oosends are handled by codewriter; introduce a new kind of call, "builtin", to be used for oosends to builtin methods like ootype.String.*; write a failing test that shows we need to implement green oosends. Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Tue Apr 22 15:05:15 2008 @@ -1009,8 +1009,7 @@ return self.handle_green_call(op, withexc, exclude_last=True) targets = dict(self.graphs_from(op)) fnptrindex = self.serialize_oparg("red", op.args[0]) - has_result = (self.varcolor(op.result) != "gray" and - op.result.concretetype != lltype.Void) + has_result = self.has_result(op) if self.hannotator.policy.hotpath: if not targets: @@ -1149,8 +1148,7 @@ graphs, args_v = self.decompose_call_op(op) fnptr = op.args[0] pos = self.calldesc_position(fnptr.concretetype) - has_result = (self.varcolor(op.result) != "gray" and - op.result.concretetype != lltype.Void) + has_result = self.has_result(op) func = self.serialize_oparg("red", fnptr) emitted_args = [] for v in args_v: @@ -1483,6 +1481,15 @@ tsgraph = self.specialized_graph_of(graph, args_v, spaceop.result) yield graph, tsgraph + def check_green_deepfrozen_call(self, spaceop): + hs_result = self.hannotator.binding(spaceop.result) + return (hs_result.is_green() and + hs_result.concretetype is not lltype.Void) + + def has_result(self, op): + return (self.varcolor(op.result) != "gray" and + op.result.concretetype != lltype.Void) + def guess_call_kind(self, spaceop): if spaceop.opname == 'direct_call': c_func = spaceop.args[0] @@ -1493,11 +1500,17 @@ self.hannotator.policy.oopspec): if fnobj._callable.oopspec.startswith('vable.'): return 'vable', None - hs_result = self.hannotator.binding(spaceop.result) - if (hs_result.is_green() and - hs_result.concretetype is not lltype.Void): + if self.check_green_deepfrozen_call(spaceop): + return 'green', self.can_raise(spaceop) + return 'oopspec', self.can_raise(spaceop) + elif spaceop.opname == 'oosend': + SELFTYPE, methname, opargs = self.decompose_oosend(spaceop) + if SELFTYPE.oopspec_name is not None: + if self.check_green_deepfrozen_call(spaceop): return 'green', self.can_raise(spaceop) return 'oopspec', self.can_raise(spaceop) + if not SELFTYPE._lookup_graphs(methname): + return 'builtin', self.can_raise(spaceop) if self.hannotator.bookkeeper.is_green_call(spaceop): return 'green', None withexc = self.can_raise(spaceop) @@ -1628,6 +1641,12 @@ ExceptionDesc = exception.OOTypeExceptionDesc StructTypeDesc = rcontainer.InstanceTypeDesc + def decompose_oosend(self, op): + name = op.args[0].value + opargs = op.args[1:] + SELFTYPE = opargs[0].concretetype + return SELFTYPE, name, opargs + def cast_fnptr_to_root(self, fnptr): return ootype.cast_to_object(fnptr) @@ -1666,76 +1685,71 @@ self.register_redvar(op.result) def serialize_op_oosend(self, op): + assert not self.hannotator.policy.hotpath, 'TODO' kind, withexc = self.guess_call_kind(op) - if kind == 'green': - assert False, 'TODO' - - name = op.args[0].value - opargs = op.args[1:] - SELFTYPE = opargs[0].concretetype - has_result = (self.varcolor(op.result) != "gray" and - op.result.concretetype != lltype.Void) + handler = getattr(self, "handle_%s_oosend" % (kind, )) + return handler(op, withexc) - if SELFTYPE.oopspec_name is not None: - # we are calling a method like List.ll_getitem or so - _, meth = SELFTYPE._lookup(name) - oopspecdescindex = self.oopspecdesc_position('send', meth, withexc) - oopspecdesc = self.oopspecdescs[oopspecdescindex] - args_v = [] - args = [] - for v in opargs: - args_v.append(v) - args.append(self.serialize_oparg("red", v)) - - hs_self = self.hannotator.binding(opargs[0]) - deepfrozen = hs_self.deepfrozen - - self.emit("red_oopspec_call%s_%s" % ("_noresult" * (not has_result), - len(args))) - self.emit(oopspecdescindex) - self.emit(deepfrozen) - self.emit(*args) - if has_result: - self.register_redvar(op.result) - return + def handle_green_oosend(self, op, withexc): + assert False, 'TODO' - # real oosend, either red or const - assert not self.hannotator.policy.hotpath + def handle_oopspec_oosend(self, op, withexc): + SELFTYPE, name, opargs = self.decompose_oosend(op) + has_result = self.has_result(op) + assert SELFTYPE.oopspec_name is not None + _, meth = SELFTYPE._lookup(name) + oopspecdescindex = self.oopspecdesc_position('send', meth, withexc) + oopspecdesc = self.oopspecdescs[oopspecdescindex] + args_v = [] + args = [] + for v in opargs: + args_v.append(v) + args.append(self.serialize_oparg("red", v)) + hs_self = self.hannotator.binding(opargs[0]) + deepfrozen = hs_self.deepfrozen + self.emit("red_oopspec_call%s_%s" % ("_noresult" * (not has_result), + len(args))) + self.emit(oopspecdescindex) + self.emit(deepfrozen) + self.emit(*args) + if has_result: + self.register_redvar(op.result) - if kind == "residual": - # oosend to an external method (e.g. ootype.String.*) - emitted_args = [] - for v in op.args[1:]: - if v.concretetype == lltype.Void: - continue - emitted_args.append(self.serialize_oparg("red", v)) - self.emit("external_oosend") - self.emit(len(emitted_args)) - self.emit(*emitted_args) - methdescindex = self.methdesc_position(SELFTYPE, name) - self.emit(methdescindex) - self.emit(has_result) - else: - # normal oosend - graph2tsgraph = dict(self.graphs_from(op)) - self.fill_methodcodes(SELFTYPE, name, graph2tsgraph) - args = graph2tsgraph.values()[0].getargs() - emitted_args = self.args_of_call(op.args[1:], args) - self.emit("red_oosend") - self.emit(*emitted_args) - methnameindex = self.string_position(name) - self.emit(methnameindex) + def handle_builtin_oosend(self, op, withexc): + SELFTYPE, name, opargs = self.decompose_oosend(op) + has_result = self.has_result(op) + emitted_args = [] + for v in op.args[1:]: + if v.concretetype == lltype.Void: + continue + emitted_args.append(self.serialize_oparg("red", v)) + self.emit("builtin_oosend") + self.emit(len(emitted_args)) + self.emit(*emitted_args) + methdescindex = self.methdesc_position(SELFTYPE, name) + self.emit(methdescindex) + self.emit(has_result) + if has_result: + self.register_redvar(op.result) + def handle_red_oosend(self, op, withexc): + SELFTYPE, name, opargs = self.decompose_oosend(op) + has_result = self.has_result(op) + graph2tsgraph = dict(self.graphs_from(op)) + self.fill_methodcodes(SELFTYPE, name, graph2tsgraph) + args = graph2tsgraph.values()[0].getargs() + emitted_args = self.args_of_call(op.args[1:], args) + self.emit("red_oosend") + self.emit(*emitted_args) + methnameindex = self.string_position(name) + self.emit(methnameindex) if has_result: self.register_redvar(op.result) - if kind == "yellow": - self.emit("yellow_retrieve_result_as_red") - self.emit(self.type_position(op.result.concretetype)) - elif kind in ("gray", "red", "residual"): - pass - else: - assert 0, "unknown call kind %s" % (kind, ) + def handle_yellow_oosend(self, op, withexc): + self.handle_red_oosend(op, withexc) + self.emit("yellow_retrieve_result_as_red") + self.emit(self.type_position(op.result.concretetype)) def fill_methodcodes(self, INSTANCE, methname, graph2tsgraph): TYPES = [INSTANCE] + INSTANCE._subclasses Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Tue Apr 22 15:05:15 2008 @@ -1094,7 +1094,7 @@ start_bytecode_loop=False) @arguments("red_varargs", "methdesc", "bool") - def opimpl_external_oosend(self, redargs, methdesc, has_result): + def opimpl_builtin_oosend(self, redargs, methdesc, has_result): result = rtimeshift.gen_external_oosend(self.jitstate, redargs, methdesc) if has_result: Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Tue Apr 22 15:05:15 2008 @@ -1003,6 +1003,17 @@ assert res == 42 self.check_insns({}) + def test_green_deepfrozen_oosend(self): + py.test.skip('in progress') + d = {1: 2, 2: 4, 3: 9} + def f(k): + d1 = hint(d, deepfreeze=True) + k1 = hint(k, concrete=True) + return d1[k1] + res = self.interpret(f, [3], []) + assert res == 9 + self.check_insns({}) + def test_residual_red_call(self): def g(x): return x+1 @@ -2198,7 +2209,7 @@ self.check_insns({}) -class TestOOType(SimpleTests): +class OOTypeMixin(object): type_system = "ootype" @staticmethod @@ -2239,6 +2250,8 @@ del insns[a] return insns +class TestOOType(OOTypeMixin, SimpleTests): + def test_degenerated_before_return(self): S = ootype.Instance('S', ootype.ROOT, {'x': ootype.Signed}) T = ootype.Instance('T', S, {'y': ootype.Float}) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vdict.py Tue Apr 22 15:05:15 2008 @@ -1,6 +1,7 @@ import py from pypy.jit.hintannotator.policy import HintAnnotatorPolicy from pypy.jit.rainbow.test.test_interpreter import InterpretationTest, P_OOPSPEC +from pypy.jit.rainbow.test.test_interpreter import OOTypeMixin from pypy.rlib.jit import hint @@ -75,7 +76,7 @@ self.check_insns({}) -class TestOOType(VDictTest): +class TestOOType(OOTypeMixin, VDictTest): type_system = "ootype" class TestLLType(VDictTest): Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_vlist.py Tue Apr 22 15:05:15 2008 @@ -1,6 +1,7 @@ import py from pypy.jit.hintannotator.policy import HintAnnotatorPolicy from pypy.jit.rainbow.test.test_interpreter import InterpretationTest, P_OOPSPEC +from pypy.jit.rainbow.test.test_interpreter import OOTypeMixin from pypy.rlib.jit import hint @@ -189,7 +190,7 @@ assert res == -7 -class TestOOType(VListTest): +class TestOOType(OOTypeMixin, VListTest): type_system = "ootype" class TestLLType(VListTest): From arigo at codespeak.net Tue Apr 22 15:49:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 15:49:07 +0200 (CEST) Subject: [pypy-svn] r54015 - in pypy/branch/io-improvements/pypy/rpython: lltypesystem test Message-ID: <20080422134907.176D516850E@codespeak.net> Author: arigo Date: Tue Apr 22 15:49:05 2008 New Revision: 54015 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll_str.py pypy/branch/io-improvements/pypy/rpython/test/test_rlist.py Log: A test and a fix, unrelated to the rest of this branch, but easy to fix with the very convenient llstr() helper. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll_str.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll_str.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll_str.py Tue Apr 22 15:49:05 2008 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem.lltype import GcArray, Array, Char, malloc +from pypy.rpython.annlowlevel import llstr from pypy.rlib.rarithmetic import r_uint, formatd CHAR_ARRAY = GcArray(Char) @@ -115,5 +116,5 @@ return result def ll_float_str(repr, f): - return formatd("%f", f) + return llstr(formatd("%f", f)) Modified: pypy/branch/io-improvements/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_rlist.py Tue Apr 22 15:49:05 2008 @@ -730,6 +730,12 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == fn() + def fn(): + return str([1.25]) + + res = self.interpret(fn, []) + assert eval(self.ll_to_string(res)) == [1.25] + def test_list_or_None(self): empty_list = [] nonempty_list = [1, 2] From arigo at codespeak.net Tue Apr 22 15:51:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 15:51:09 +0200 (CEST) Subject: [pypy-svn] r54016 - pypy/dist/demo Message-ID: <20080422135109.3EA51168525@codespeak.net> Author: arigo Date: Tue Apr 22 15:51:08 2008 New Revision: 54016 Modified: pypy/dist/demo/bpnn.py Log: Change this demo to turn it into a target for translate.py. Modified: pypy/dist/demo/bpnn.py ============================================================================== --- pypy/dist/demo/bpnn.py (original) +++ pypy/dist/demo/bpnn.py Tue Apr 22 15:51:08 2008 @@ -2,11 +2,17 @@ """ Translator Demo - Run this file -- over regular Python! -- to analyse and type-annotate - the functions and class defined in this module, starting from the - entry point function demo(). + To analyse and type-annotate the functions and class defined in + this module, starting from the entry point function demo(), + use the following command line: - Requires Pygame. + ../pypy/translator/goal/translate.py bpnn.py + + Insert '--help' before 'bpnn.py' for a list of translation options, + or see the Overview of Command Line Options for translation at + http://codespeak.net/pypy/dist/pypy/doc/config/commandline.html + + Use '--text' before 'bpnn.py' if you don't have Pygame installed. """ # Back-Propagation Neural Networks # @@ -17,7 +23,7 @@ # Modifications to the original (Armin Rigo): # * import random from PyPy's lib, which is Python 2.2's plain # Python implementation -# * starts the Translator instead of the demo by default. +# * print a doc about how to start the Translator import sys import math @@ -162,7 +168,7 @@ self.update(inputs) error = error + self.backPropagate(targets, N, M) if PRINT_IT and i % 100 == 0: - print 'error %f' % error + print 'error', error def demo(): @@ -182,33 +188,24 @@ n.test(pat) +# __________ Entry point for stand-alone builds __________ -if __name__ == '__main__': - print 'Loading...' - from pypy.translator.interactive import Translation - t = Translation(demo) - - print 'Annotating...' - t.annotate([]) - t.viewcg() - - print 'Specializing...' - t.rtype() # enable this to see (some) lower-level Cish operations - - print 'Compiling...' - f = t.compile_c() +import time - print 'Running...' +def entry_point(argv): + N = 200 T = time.time() - for i in range(10): - f() + for i in range(N): + demo() t1 = time.time() - T - print "that took", t1 + print "%d iterations, %s milliseconds per iteration" % (N, 1000.0*t1/N) + return 0 - T = time.time() - for i in range(10): - demo() - t2 = time.time() - T - print "compared to", t2 - print "a speed-up of", t2/t1 - +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None + +if __name__ == '__main__': + #demo() + print __doc__ From cfbolz at codespeak.net Tue Apr 22 17:04:19 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 22 Apr 2008 17:04:19 +0200 (CEST) Subject: [pypy-svn] r54017 - pypy/branch/2.5-features Message-ID: <20080422150419.024FD2A0193@codespeak.net> Author: cfbolz Date: Tue Apr 22 17:04:17 2008 New Revision: 54017 Added: pypy/branch/2.5-features/ - copied from r54016, pypy/dist/ Log: make a branch for bruno's summer of code work From arigo at codespeak.net Tue Apr 22 17:11:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 17:11:36 +0200 (CEST) Subject: [pypy-svn] r54018 - in pypy/dist/pypy: module/_rawffi rlib rlib/test translator/c/test Message-ID: <20080422151136.437812A01E8@codespeak.net> Author: arigo Date: Tue Apr 22 17:11:35 2008 New Revision: 54018 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/test/test_libffi.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: Never never never use ffi_type_ulong and ffi_type_slong. On 32-bit machines it's sometimes of size 4 and sometimes of size 8. Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Tue Apr 22 17:11:35 2008 @@ -13,18 +13,6 @@ from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat from pypy.module._rawffi.tracker import tracker -def _signed_type_for(TYPE): - sz = rffi.sizeof(TYPE) - if sz == 4: return ffi_type_sint32 - elif sz == 8: return ffi_type_sint64 - else: raise ValueError("unsupported type size for %r" % (TYPE,)) - -def _unsigned_type_for(TYPE): - sz = rffi.sizeof(TYPE) - if sz == 4: return ffi_type_uint32 - elif sz == 8: return ffi_type_uint64 - else: raise ValueError("unsupported type size for %r" % (TYPE,)) - TYPEMAP = { # XXX A mess with unsigned/signed/normal chars :-/ 'c' : ffi_type_uchar, @@ -33,14 +21,12 @@ 'h' : ffi_type_sshort, 'u' : ffi_type_uint, # XXX think deeper how to map it properly 'H' : ffi_type_ushort, - 'i' : ffi_type_sint, - 'I' : ffi_type_uint, - # xxx don't use ffi_type_slong and ffi_type_ulong - their meaning - # changes from a libffi version to another :-(( - 'l' : _signed_type_for(rffi.LONG), - 'L' : _unsigned_type_for(rffi.ULONG), - 'q' : _signed_type_for(rffi.LONGLONG), - 'Q' : _unsigned_type_for(rffi.ULONGLONG), + 'i' : cast_type_to_ffitype(rffi.INT), + 'I' : cast_type_to_ffitype(rffi.UINT), + 'l' : cast_type_to_ffitype(rffi.LONG), + 'L' : cast_type_to_ffitype(rffi.ULONG), + 'q' : cast_type_to_ffitype(rffi.LONGLONG), + 'Q' : cast_type_to_ffitype(rffi.ULONGLONG), 'f' : ffi_type_float, 'd' : ffi_type_double, 's' : ffi_type_pointer, Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Tue Apr 22 17:11:35 2008 @@ -70,7 +70,10 @@ return l base_names = ['double', 'uchar', 'schar', 'sshort', 'ushort', 'uint', 'sint', - 'ulong', 'slong', 'float', 'pointer', 'void', + # ffi_type_slong and ffi_type_ulong are omitted because + # their meaning changes too much from one libffi version to + # another. DON'T USE THEM! use cast_type_to_ffitype(). + 'float', 'pointer', 'void', # by size 'sint8', 'uint8', 'sint16', 'uint16', 'sint32', 'uint32', 'sint64', 'uint64'] @@ -90,6 +93,18 @@ for name in type_names: locals()[name] = configure_simple_type(name) +def _signed_type_for(TYPE): + sz = rffi.sizeof(TYPE) + if sz == 4: return ffi_type_sint32 + elif sz == 8: return ffi_type_sint64 + else: raise ValueError("unsupported type size for %r" % (TYPE,)) + +def _unsigned_type_for(TYPE): + sz = rffi.sizeof(TYPE) + if sz == 4: return ffi_type_uint32 + elif sz == 8: return ffi_type_uint64 + else: raise ValueError("unsupported type size for %r" % (TYPE,)) + TYPE_MAP = { rffi.DOUBLE : ffi_type_double, rffi.FLOAT : ffi_type_float, @@ -99,8 +114,12 @@ rffi.USHORT : ffi_type_ushort, rffi.UINT : ffi_type_uint, rffi.INT : ffi_type_sint, - rffi.ULONG : ffi_type_ulong, - rffi.LONG : ffi_type_slong, + # xxx don't use ffi_type_slong and ffi_type_ulong - their meaning + # changes from a libffi version to another :-(( + rffi.ULONG : _unsigned_type_for(rffi.ULONG), + rffi.LONG : _signed_type_for(rffi.LONG), + rffi.ULONGLONG : _unsigned_type_for(rffi.ULONGLONG), + rffi.LONGLONG : _signed_type_for(rffi.LONGLONG), lltype.Void : ffi_type_void, } Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Tue Apr 22 17:11:35 2008 @@ -5,6 +5,7 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.translator.c.test.test_genc import compile from pypy.rlib.libffi import * +from pypy.rlib.objectmodel import keepalive_until_here from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED from pypy.rpython.lltypesystem import rffi, lltype import os, sys @@ -78,7 +79,8 @@ def test_wrong_args(self): libc = CDLL('libc.so.6') # XXX assume time_t is long - ctime = libc.getpointer('time', [ffi_type_pointer], ffi_type_ulong) + ulong = cast_type_to_ffitype(rffi.ULONG) + ctime = libc.getpointer('time', [ffi_type_pointer], ulong) x = lltype.malloc(lltype.GcStruct('xxx')) y = lltype.malloc(lltype.GcArray(rffi.LONG), 3) z = lltype.malloc(lltype.Array(rffi.LONG), 4, flavor='raw') @@ -93,7 +95,8 @@ def test_call_time(self): libc = CDLL('libc.so.6') # XXX assume time_t is long - ctime = libc.getpointer('time', [ffi_type_pointer], ffi_type_ulong) + ulong = cast_type_to_ffitype(rffi.ULONG) + ctime = libc.getpointer('time', [ffi_type_pointer], ulong) ctime.push_arg(lltype.nullptr(rffi.CArray(rffi.LONG))) t0 = ctime.call(rffi.LONG) time.sleep(2) @@ -140,14 +143,17 @@ assert snd == rffi.cast(rffi.VOIDP, a) def test_callback(self): + slong = cast_type_to_ffitype(rffi.LONG) libc = CDLL('libc.so.6') - qsort = libc.getpointer('qsort', [ffi_type_pointer, ffi_type_slong, - ffi_type_slong, ffi_type_pointer], + qsort = libc.getpointer('qsort', [ffi_type_pointer, slong, + slong, ffi_type_pointer], ffi_type_void) def callback(ll_args, ll_res, stuff): - a1 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[0])[0] - a2 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[1])[0] + p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0] + p_a2 = rffi.cast(rffi.VOIDPP, ll_args[1])[0] + a1 = rffi.cast(rffi.INTP, p_a1)[0] + a2 = rffi.cast(rffi.INTP, p_a2)[0] res = rffi.cast(rffi.INTP, ll_res) if a1 > a2: res[0] = 1 @@ -170,6 +176,8 @@ qsort.call(lltype.Void) assert [to_sort[i] for i in range(4)] == [1,2,3,4] lltype.free(to_sort, flavor='raw') + keepalive_until_here(ptr) # <= this test is not translated, but don't + # forget this in code that is meant to be def test_compile(self): import py @@ -241,11 +249,12 @@ lib = CDLL(lib_name) - size = ffi_type_slong.c_size*2 - alignment = ffi_type_slong.c_alignment + slong = cast_type_to_ffitype(rffi.LONG) + size = slong.c_size*2 + alignment = slong.c_alignment tp = make_struct_ffitype(size, alignment) - sum_x_y = lib.getrawpointer('sum_x_y', [tp], ffi_type_slong) + sum_x_y = lib.getrawpointer('sum_x_y', [tp], slong) buffer = lltype.malloc(rffi.LONGP.TO, 3, flavor='raw') buffer[0] = 200 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 Tue Apr 22 17:11:35 2008 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.memory.test import snippet +from pypy.rlib.objectmodel import keepalive_until_here from pypy import conftest def compile_func(fn, inputtypes, t=None, gcpolicy="ref"): @@ -815,15 +816,18 @@ def test_callback_with_collect(self): py.test.skip("Segfaults") - from pypy.rlib.libffi import ffi_type_pointer, ffi_type_slong,\ + from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint from pypy.rpython.lltypesystem import rffi from pypy.rlib import rgc import gc + slong = cast_type_to_ffitype(rffi.LONG) def callback(ll_args, ll_res, stuff): - a1 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[0])[0] - a2 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[1])[0] + p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0] + p_a2 = rffi.cast(rffi.VOIDPP, ll_args[1])[0] + a1 = rffi.cast(rffi.INTP, p_a1)[0] + a2 = rffi.cast(rffi.INTP, p_a2)[0] res = rffi.cast(rffi.INTP, ll_res) if a1 > a2: res[0] = 1 @@ -833,8 +837,8 @@ def f(): libc = CDLL('libc.so.6') - qsort = libc.getpointer('qsort', [ffi_type_pointer, ffi_type_slong, - ffi_type_slong, ffi_type_pointer], + qsort = libc.getpointer('qsort', [ffi_type_pointer, slong, + slong, ffi_type_pointer], ffi_type_void) ptr = CallbackFuncPtr([ffi_type_pointer, ffi_type_pointer], @@ -853,6 +857,7 @@ qsort.call(lltype.Void) result = [to_sort[i] for i in range(4)] == [1,2,3,4] lltype.free(to_sort, flavor='raw') + keepalive_until_here(ptr) return int(result) c_fn = self.getcompiled(f) From arigo at codespeak.net Tue Apr 22 17:21:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 17:21:20 +0200 (CEST) Subject: [pypy-svn] r54019 - pypy/dist/pypy/translator/c Message-ID: <20080422152120.CE7D339B59B@codespeak.net> Author: arigo Date: Tue Apr 22 17:21:20 2008 New Revision: 54019 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: Found a (large) case in which heapblock.operations is empty, causing invalid C code to be generated. (but C sucks) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Tue Apr 22 17:21:20 2008 @@ -375,9 +375,12 @@ for op in self.gen_link(enterlink): yield '\t' + op yield '\t block%d_back:' % self.blocknum[headblock] - for i, op in enumerate(headblock.operations): - for line in self.gen_op(op): - yield '\t' + line + if headblock.operations: + for i, op in enumerate(headblock.operations): + for line in self.gen_op(op): + yield '\t' + line + else: + yield '\t;' yield '}' for op in self.gen_link(exitlink): yield op From arigo at codespeak.net Tue Apr 22 17:43:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 17:43:39 +0200 (CEST) Subject: [pypy-svn] r54020 - in pypy/dist/pypy: config config/test module/_stackless/test rpython/memory/gctransform rpython/memory/gctransform/test rpython/memory/test translator/c translator/c/test Message-ID: <20080422154339.2F998169E8C@codespeak.net> Author: arigo Date: Tue Apr 22 17:43:37 2008 New Revision: 54020 Removed: pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py pypy/dist/pypy/rpython/memory/gctransform/test/test_stacklessframework.py Modified: pypy/dist/pypy/config/test/test_pypyoption.py pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/module/_stackless/test/test_interp_clonable.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/translator/c/gc.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: The "stackless" gcrootfinder wasn't working for a long time (it was simply using the "shadowstack" too). Remove the corresponding code for now; there is no reason to keep the stackless gcrootfinder around given that it was just slower than a regular stackless build using the shadowstack. 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 Tue Apr 22 17:43:37 2008 @@ -16,16 +16,10 @@ conf.objspace.std.withprebuiltint = True py.test.raises(ConfigError, "conf.objspace.std.withsmallint = True") -def test_stacklessgc_required(): - conf = get_pypy_config() - conf.translation.gcrootfinder = "stackless" - assert conf.translation.stackless - assert conf.translation.type_system == "lltype" - assert conf.translation.gctransformer == "framework" - assert conf.translation.gc == "generation" +def test_conflicting_gcrootfinder(): conf = get_pypy_config() conf.translation.gc = "boehm" - py.test.raises(ConfigError, "conf.translation.gcrootfinder = 'stackless'") + py.test.raises(ConfigError, "conf.translation.gcrootfinder = 'asmgcc'") def test_frameworkgc(): Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Tue Apr 22 17:43:37 2008 @@ -65,13 +65,11 @@ }), ChoiceOption("gcrootfinder", "Strategy for finding GC Roots (framework GCs only)", - ["n/a", "shadowstack", "stackless", "llvmgc", "asmgcc"], + ["n/a", "shadowstack", "llvmgc", "asmgcc"], "shadowstack", cmdline="--gcrootfinder", requires={ "shadowstack": [("translation.gctransformer", "framework")], - "stackless": [("translation.gctransformer", "framework"), - ("translation.stackless", True)], "llvmgc": [("translation.gctransformer", "framework"), ("translation.backend", "llvm")], "asmgcc": [("translation.gctransformer", "framework"), @@ -79,7 +77,6 @@ }, suggests={ "shadowstack": [("translation.gc", "generation")], - "stackless": [("translation.gc", "generation")], "llvmgc": [("translation.gc", "generation")], "asmgcc": [("translation.gc", "generation")], }), Modified: pypy/dist/pypy/module/_stackless/test/test_interp_clonable.py ============================================================================== --- pypy/dist/pypy/module/_stackless/test/test_interp_clonable.py (original) +++ pypy/dist/pypy/module/_stackless/test/test_interp_clonable.py Tue Apr 22 17:43:37 2008 @@ -1,6 +1,7 @@ """ testing cloning """ +import py; py.test.skip("clonable coroutines not really maintained any more") from pypy import conftest; conftest.translation_test_so_skip_if_appdirect() from pypy.translator.c import gc 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 Apr 22 17:43:37 2008 @@ -5,7 +5,6 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.memory.gctransform import framework -from pypy.rpython.memory.gctransform import stacklessframework from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.memory.gc.marksweep import X_CLONE, X_POOL, X_POOL_PTR from pypy.rlib.objectmodel import compute_unique_id @@ -716,20 +715,6 @@ run([]) - -class TestStacklessMarkSweepGC(TestMarkSweepGC): - gcname = "marksweep" - - stacklessgc = True - class gcpolicy(gc.StacklessFrameworkGcPolicy): - class transformerclass(stacklessframework.StacklessFrameworkGCTransformer): - GC_PARAMS = {'start_heap_size': 4096 } - root_stack_depth = 200 - - def test_instances(self): - py.test.skip("fails for a stupid reasons") - - class TestPrintingGC(GenericGCTests): gcname = "statistics" Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Tue Apr 22 17:43:37 2008 @@ -5,7 +5,7 @@ typeOf, Ptr, ContainerType, RttiStruct, \ RuntimeTypeInfo, getRuntimeTypeInfo, top_container from pypy.rpython.memory.gctransform import \ - refcounting, boehm, framework, stacklessframework, llvmgcroot, asmgcroot + refcounting, boehm, framework, llvmgcroot, asmgcroot from pypy.rpython.lltypesystem import lltype, llmemory class BasicGcPolicy(object): @@ -305,10 +305,6 @@ o = top_container(defnode.obj) return defnode.db.gctransformer.gc_field_values_for(o) -class StacklessFrameworkGcPolicy(FrameworkGcPolicy): - transformerclass = stacklessframework.StacklessFrameworkGCTransformer - requires_stackless = True - class LLVMGcRootFrameworkGcPolicy(FrameworkGcPolicy): transformerclass = llvmgcroot.LLVMGcRootFrameworkGCTransformer @@ -321,7 +317,6 @@ 'ref': RefcountingGcPolicy, 'none': NoneGcPolicy, 'framework': FrameworkGcPolicy, - 'framework+stacklessgc': StacklessFrameworkGcPolicy, 'framework+llvmgcroot': LLVMGcRootFrameworkGcPolicy, 'framework+asmgcroot': AsmGcRootFrameworkGcPolicy, } Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Tue Apr 22 17:43:37 2008 @@ -92,9 +92,7 @@ def get_gcpolicyclass(self): if self.gcpolicy is None: name = self.config.translation.gctransformer - if self.config.translation.gcrootfinder == "stackless": - name = "%s+stacklessgc" % (name,) - elif self.config.translation.gcrootfinder == "llvmgc": + if self.config.translation.gcrootfinder == "llvmgc": name = "%s+llvmgcroot" % (name,) elif self.config.translation.gcrootfinder == "asmgcc": name = "%s+asmgcroot" % (name,) 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 Tue Apr 22 17:43:37 2008 @@ -824,6 +824,7 @@ slong = cast_type_to_ffitype(rffi.LONG) def callback(ll_args, ll_res, stuff): + gc.collect() p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0] p_a2 = rffi.cast(rffi.VOIDPP, ll_args[1])[0] a1 = rffi.cast(rffi.INTP, p_a1)[0] @@ -833,7 +834,6 @@ res[0] = 1 else: res[0] = -1 - gc.collect() def f(): libc = CDLL('libc.so.6') @@ -863,31 +863,6 @@ c_fn = self.getcompiled(f) assert c_fn() == 1 -class TestUsingStacklessFramework(TestUsingFramework): - - def getcompiled(self, f): - # XXX quick hack - from pypy.translator.c.test.test_stackless import StacklessTest - runner = StacklessTest() - runner.gcpolicy = self.gcpolicy - runner.stacklessgc = True - try: - res = runner.wrap_stackless_function(f) - except py.process.cmdexec.Error, e: - if 'Fatal RPython error: MemoryError' in e.err: - res = MemoryError - else: - raise - self.t = runner.t - def compiled(): - if res is MemoryError: - raise MemoryError - else: - return res - return compiled - - def test_weakref(self): - py.test.skip("fails for some reason I couldn't figure out yet :-(") class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTests): gcpolicy = "semispace" From arigo at codespeak.net Tue Apr 22 17:46:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 17:46:49 +0200 (CEST) Subject: [pypy-svn] r54021 - in pypy/dist/pypy/translator/c: gcc/test test Message-ID: <20080422154649.21098169EC7@codespeak.net> Author: arigo Date: Tue Apr 22 17:46:48 2008 New Revision: 54021 Modified: pypy/dist/pypy/translator/c/gcc/test/test_asmgcroot.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: This test no longer segfaults; it passes everywhere except with the asmgcc gcrootfinder. Modified: pypy/dist/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/dist/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/dist/pypy/translator/c/gcc/test/test_asmgcroot.py Tue Apr 22 17:46:48 2008 @@ -88,3 +88,6 @@ pass # for the individual tests see # ====> ../../test/test_newgc.py + + def test_callback_with_collect(self): + py.test.skip("in-progress") 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 Tue Apr 22 17:46:48 2008 @@ -815,7 +815,6 @@ assert c_fn() == 0 def test_callback_with_collect(self): - py.test.skip("Segfaults") from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint from pypy.rpython.lltypesystem import rffi From arigo at codespeak.net Tue Apr 22 19:05:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Apr 2008 19:05:38 +0200 (CEST) Subject: [pypy-svn] r54023 - in pypy/branch/io-improvements/pypy: rpython rpython/lltypesystem rpython/lltypesystem/test translator/c translator/c/test Message-ID: <20080422170538.38F7C169FAD@codespeak.net> Author: arigo Date: Tue Apr 22 19:05:37 2008 New Revision: 54023 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py pypy/branch/io-improvements/pypy/translator/c/funcgen.py pypy/branch/io-improvements/pypy/translator/c/test/test_lltyped.py Log: (docgok, arigo) Yet Another Casting Operation. This one corresponds to rffi.cast (ll2ctypes.force_cast). It's needed to run on top the llinter the tests using this kind of cast. Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Tue Apr 22 19:05:37 2008 @@ -701,6 +701,11 @@ lltype.ContainerType) return getattr(obj, field) + def op_force_cast(self, RESTYPE, obj): + from pypy.rpython.lltypesystem import ll2ctypes + return ll2ctypes.force_cast(RESTYPE, obj) + op_force_cast.need_result_type = True + def op_cast_int_to_ptr(self, RESTYPE, int1): return lltype.cast_int_to_ptr(RESTYPE, int1) op_cast_int_to_ptr.need_result_type = True Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py Tue Apr 22 19:05:37 2008 @@ -704,14 +704,12 @@ return annmodel.lltype_to_annotation(RESTYPE) def specialize_call(self, hop): - from pypy.rpython.rbuiltin import gen_cast hop.exception_cannot_occur() s_RESTYPE = hop.args_s[0] assert s_RESTYPE.is_constant() RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) - TYPE1 = v_arg.concretetype - return gen_cast(hop.llops, RESTYPE, v_arg) + return hop.genop('force_cast', [v_arg], resulttype = RESTYPE) def typecheck_ptradd(T): # --- ptradd() is only for pointers to non-GC, no-length arrays. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Tue Apr 22 19:05:37 2008 @@ -317,6 +317,7 @@ 'cast_float_to_uint': LLOp(canfold=True), # XXX need OverflowError? 'cast_float_to_longlong':LLOp(canfold=True), 'truncate_longlong_to_int':LLOp(canfold=True), + 'force_cast': LLOp(sideeffects=False), # only for rffi.cast() # __________ pointer operations __________ Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Tue Apr 22 19:05:37 2008 @@ -382,9 +382,8 @@ buf = rffi.cast(rffi.VOIDP, b) return buf[2] assert f() == 'z' - # XXX let's say we don't run it on top of llinterp - #res = interpret(f, []) - #assert res == 'z' + res = interpret(f, []) + assert res == 'z' def test_funcptr1(self): def dummy(n): Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Tue Apr 22 19:05:37 2008 @@ -527,8 +527,8 @@ graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - expected = {'cast_int_to_uint': 1, 'direct_call': 1, - 'cast_primitive': 2, 'cast_int_to_float': 1} + print s + expected = {'force_cast': 3, 'cast_int_to_float': 1, 'direct_call': 1} for k, v in expected.items(): assert s[k] == v Modified: pypy/branch/io-improvements/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/funcgen.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/funcgen.py Tue Apr 22 19:05:37 2008 @@ -696,6 +696,8 @@ typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals() + OP_FORCE_CAST = OP_CAST_PRIMITIVE # xxx the same logic works + def OP_RESUME_POINT(self, op): return '/* resume point %s */'%(op.args[0],) Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_lltyped.py Tue Apr 22 19:05:37 2008 @@ -304,6 +304,23 @@ res = fn(100) assert res == 100 + len(list(names)) + def test_force_cast(self): + from pypy.rpython.annlowlevel import llstr + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.lltypesystem import rffi, llmemory, lltype + P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)) + + def f(): + a = llstr("xyz") + b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + buf = rffi.cast(rffi.VOIDP, b) + return buf[2] + + fn = self.getcompiled(f, []) + res = fn() + assert res == 'z' + def test_array_nolength(self): A = Array(Signed, hints={'nolength': True}) a1 = malloc(A, 3, immortal=True) From docgok at codespeak.net Tue Apr 22 22:48:26 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Tue, 22 Apr 2008 22:48:26 +0200 (CEST) Subject: [pypy-svn] r54024 - pypy/branch/io-improvements/pypy/rpython/lltypesystem/test Message-ID: <20080422204826.1388016A13F@codespeak.net> Author: docgok Date: Tue Apr 22 22:48:25 2008 New Revision: 54024 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Log: Little bit of debugging code we don't need any more. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_rffi.py Tue Apr 22 22:48:25 2008 @@ -527,7 +527,6 @@ graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - print s expected = {'force_cast': 3, 'cast_int_to_float': 1, 'direct_call': 1} for k, v in expected.items(): assert s[k] == v From docgok at codespeak.net Wed Apr 23 05:47:40 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Wed, 23 Apr 2008 05:47:40 +0200 (CEST) Subject: [pypy-svn] r54026 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080423034740.00BD316A17E@codespeak.net> Author: docgok Date: Wed Apr 23 05:47:38 2008 New Revision: 54026 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py Log: Stubs for non-moving allocation llops Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Wed Apr 23 05:47:38 2008 @@ -684,6 +684,12 @@ return ptr except MemoryError: self.make_llexception() + + def op_malloc_nonmovable(self, obj, flags, size): + raise NotImplementedError + + def op_malloc_nonmovable_varsize(self, obj, flags, size): + raise NotImplementedError def op_free(self, obj, flavor): assert isinstance(flavor, str) From arigo at codespeak.net Wed Apr 23 11:30:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 11:30:55 +0200 (CEST) Subject: [pypy-svn] r54032 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080423093055.AB0C916A277@codespeak.net> Author: arigo Date: Wed Apr 23 11:30:54 2008 New Revision: 54032 Modified: pypy/dist/pypy/rlib/parsing/test/test_deterministic.py Log: Fix test to run on 2.4 too. (personally, I also think that this change makes the code quite a bit more readable) Modified: pypy/dist/pypy/rlib/parsing/test/test_deterministic.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_deterministic.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_deterministic.py Wed Apr 23 11:30:54 2008 @@ -175,6 +175,6 @@ nice = make_nice_charset_repr(string.printable) chunks = ['A-Z','a-z','0-9','\\t','\\x0b','\\n','\\r','\\x0c','\\\\','\\-'] chunks += list('! #"%$\'&)(+*,/.;:=@[]_^`{}|~') - assert all([chunk in nice for chunk in chunks]) # make sure every unit is in there, in some order + for chunk in chunks: + assert chunk in nice # make sure every unit is in there, in some order assert len(''.join(chunks))==len(nice) # make sure that's all that's in there - \ No newline at end of file From arigo at codespeak.net Wed Apr 23 11:33:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 11:33:51 +0200 (CEST) Subject: [pypy-svn] r54033 - pypy/dist/pypy/module/_stackless/test Message-ID: <20080423093351.1F5B616A277@codespeak.net> Author: arigo Date: Wed Apr 23 11:33:50 2008 New Revision: 54033 Modified: pypy/dist/pypy/module/_stackless/test/test_choicepoint.py pypy/dist/pypy/module/_stackless/test/test_clonable.py Log: Skip more tests for now. Modified: pypy/dist/pypy/module/_stackless/test/test_choicepoint.py ============================================================================== --- pypy/dist/pypy/module/_stackless/test/test_choicepoint.py (original) +++ pypy/dist/pypy/module/_stackless/test/test_choicepoint.py Wed Apr 23 11:33:50 2008 @@ -1,3 +1,5 @@ +import py; py.test.skip("clonable coroutines not really maintained any more") + from pypy.rlib.rcoroutine import AbstractThunk from pypy.module._stackless.rclonable import InterpClonableCoroutine as ClonableCoroutine Modified: pypy/dist/pypy/module/_stackless/test/test_clonable.py ============================================================================== --- pypy/dist/pypy/module/_stackless/test/test_clonable.py (original) +++ pypy/dist/pypy/module/_stackless/test/test_clonable.py Wed Apr 23 11:33:50 2008 @@ -1,3 +1,5 @@ +import py; py.test.skip("clonable coroutines not really maintained any more") + from pypy.conftest import gettestobjspace, option import py, sys From arigo at codespeak.net Wed Apr 23 11:34:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 11:34:59 +0200 (CEST) Subject: [pypy-svn] r54034 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080423093459.6CEFB16A27E@codespeak.net> Author: arigo Date: Wed Apr 23 11:34:59 2008 New Revision: 54034 Added: pypy/dist/pypy/rlib/parsing/test/autopath.py - copied unchanged from r54031, pypy/dist/pypy/tool/autopath.py Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Log: Fix this test to make it independent on the current working directory (e.g. when typing: py.test test/test_pcre_regtest.py). Modified: pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pcre_regtest.py Wed Apr 23 11:34:59 2008 @@ -84,6 +84,8 @@ from pypy.rlib.parsing.regexparse import make_runner, unescape import string import re +import autopath +this_dir = py.path.local(autopath.this_dir) #py.test.skip("Still in progress") @@ -123,7 +125,8 @@ def generate_output7(): """Create the testoutput7.py file from the PCRE file testoutput7""" - create_pcre_pickle(open('testoutput7','r'), PythonDumper(open('pcre_test_7.py','w'))) + create_pcre_pickle(this_dir.join('testoutput7').open(), + PythonDumper(this_dir.join('pcre_test_7.py').open('w'))) def create_pcre_pickle(file, dumper): """Create a filtered PCRE test file for the test.""" @@ -295,11 +298,11 @@ assert match is None def test_output7(): - suite = PythonDumper(open('pcre_test_7.py','r')).load() + suite = PythonDumper(this_dir.join('pcre_test_7.py').open()).load() while suite: regex, flags, tests = suite.pop(0) yield run_individual_test, regex, tests if __name__=="__main__": for fcn, regex, tests in test_output7(): - fcn(regex,tests) \ No newline at end of file + fcn(regex,tests) From arigo at codespeak.net Wed Apr 23 11:38:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 11:38:36 +0200 (CEST) Subject: [pypy-svn] r54035 - pypy/dist/pypy/lib/app_test Message-ID: <20080423093836.7F62116A274@codespeak.net> Author: arigo Date: Wed Apr 23 11:38:35 2008 New Revision: 54035 Modified: pypy/dist/pypy/lib/app_test/test_ctypes_support.py Log: Fix this test to run on top of CPython too (i.e. when run simply with 'py.test test_ctypes_support.py'). Modified: pypy/dist/pypy/lib/app_test/test_ctypes_support.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_ctypes_support.py (original) +++ pypy/dist/pypy/lib/app_test/test_ctypes_support.py Wed Apr 23 11:38:35 2008 @@ -1,6 +1,10 @@ from ctypes import * -from ctypes_support import standard_c_lib, get_errno, set_errno +try: + from ctypes_support import standard_c_lib, get_errno, set_errno +except ImportError: # on top of cpython + from pypy.lib.ctypes_support import standard_c_lib, get_errno, set_errno + def test_stdlib_and_errno(): write = standard_c_lib.write From fijal at codespeak.net Wed Apr 23 11:54:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 11:54:42 +0200 (CEST) Subject: [pypy-svn] r54036 - in pypy/dist/pypy: config objspace objspace/std objspace/std/test Message-ID: <20080423095442.5C6AC16A3DF@codespeak.net> Author: fijal Date: Wed Apr 23 11:54:41 2008 New Revision: 54036 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/objspace/descroperation.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_intobject.py Log: * Create an option for optimized comparison op * Use this option instead of hacks in descroperation * test_loop is faster, but will measure it exactly how much. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Wed Apr 23 11:54:41 2008 @@ -272,6 +272,9 @@ BoolOption("optimized_int_add", "special case the addition of two integers in BINARY_ADD", default=False), + BoolOption("optimized_comparison_op", + "special case the comparison of integers", + default=False), BoolOption("optimized_list_getitem", "special case the 'list[integer]' expressions", default=False), Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Wed Apr 23 11:54:41 2008 @@ -475,14 +475,8 @@ def _make_comparison_impl(symbol, specialnames): left, right = specialnames op = getattr(operator, left) + def comparison_impl(space, w_obj1, w_obj2): - from pypy.objspace.std.intobject import W_IntObject - if type(w_obj1) is W_IntObject and type(w_obj2) is W_IntObject: - return space.newbool(op(w_obj1.intval, w_obj2.intval)) - return _comparison_impl(space, w_obj1, w_obj2) - comparison_impl._always_inline_ = True - - def _comparison_impl(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) w_typ2 = space.type(w_obj2) w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left) @@ -508,11 +502,9 @@ w_res = _cmp(space, w_first, w_second) res = space.int_w(w_res) return space.wrap(op(res, 0)) - _comparison_impl._dont_inline_ = True return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_')) - def _make_inplace_impl(symbol, specialnames): specialname, = specialnames assert specialname.startswith('__i') and specialname.endswith('__') Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Apr 23 11:54:41 2008 @@ -4,6 +4,7 @@ from pypy.interpreter.typedef import get_unique_interplevel_subclass from pypy.interpreter.argument import Arguments from pypy.interpreter import pyframe +from pypy.interpreter.pyopcode import unrolling_compare_dispatch_table from pypy.rlib.objectmodel import instantiate from pypy.interpreter.gateway import PyPyCacheDir from pypy.tool.cache import Cache @@ -17,6 +18,7 @@ r_longlong, r_ulonglong from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.jit import hint, we_are_jitted +from pypy.rlib.unroll import unrolling_iterable import sys import os import __builtin__ @@ -40,6 +42,19 @@ assert issubclass(implcls, W_Object) _registered_implementations[implcls] = True + +compare_table = [ + "lt", # "<" + "le", # "<=" + "eq", # "==" + "ne", # "!=" + "gt", # ">" + "ge", # ">=" + ] + +unrolling_compare_ops = unrolling_iterable( + enumerate(compare_table)) + ################################################################## class StdObjSpace(ObjSpace, DescrOperation): @@ -149,6 +164,29 @@ # def CALL_METHOD(...): from pypy.objspace.std.callmethod import CALL_METHOD + if self.config.objspace.std.optimized_comparison_op: + def COMPARE_OP(f, testnum, *ignored): + import operator + w_2 = f.popvalue() + w_1 = f.popvalue() + w_result = None + if (type(w_2) is W_IntObject and type(w_1) is W_IntObject + and testnum < len(compare_table)): + for i, attr in unrolling_compare_ops: + if i == testnum: + op = getattr(operator, attr) + w_result = f.space.newbool(op(w_1.intval, + w_2.intval)) + break + else: + for i, attr in unrolling_compare_dispatch_table: + if i == testnum: + w_result = getattr(f, attr)(w_1, w_2) + break + else: + raise BytecodeCorruption, "bad COMPARE_OP oparg" + f.pushvalue(w_result) + if self.config.objspace.std.logspaceoptypes: _space_op_types = [] for name, func in pyframe.PyFrame.__dict__.iteritems(): @@ -182,7 +220,7 @@ w_result = operation(w_1) f.pushvalue(w_result) return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) - locals()[name] = make_opimpl(operationname) + locals()[name] = make_opimpl(operationname) self.FrameClass = StdObjSpaceFrame Modified: pypy/dist/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_intobject.py Wed Apr 23 11:54:41 2008 @@ -418,3 +418,9 @@ def setup_class(cls): from pypy.conftest import gettestobjspace cls.space = gettestobjspace(**{"objspace.std.optimized_int_add": True}) + +class AppTestIntOptimizedComp(AppTestInt): + def setup_class(cls): + from pypy.conftest import gettestobjspace + cls.space = gettestobjspace(**{"objspace.std.optimized_comparison_op": True}) + From fijal at codespeak.net Wed Apr 23 12:09:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 12:09:41 +0200 (CEST) Subject: [pypy-svn] r54037 - pypy/dist/pypy/objspace/std Message-ID: <20080423100941.E839E16A16E@codespeak.net> Author: fijal Date: Wed Apr 23 12:09:41 2008 New Revision: 54037 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: oops, missing import Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Apr 23 12:09:41 2008 @@ -4,7 +4,8 @@ from pypy.interpreter.typedef import get_unique_interplevel_subclass from pypy.interpreter.argument import Arguments from pypy.interpreter import pyframe -from pypy.interpreter.pyopcode import unrolling_compare_dispatch_table +from pypy.interpreter.pyopcode import unrolling_compare_dispatch_table, \ + BytecodeCorruption from pypy.rlib.objectmodel import instantiate from pypy.interpreter.gateway import PyPyCacheDir from pypy.tool.cache import Cache From arigo at codespeak.net Wed Apr 23 12:34:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 12:34:34 +0200 (CEST) Subject: [pypy-svn] r54038 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080423103434.0992416A3E5@codespeak.net> Author: arigo Date: Wed Apr 23 12:34:32 2008 New Revision: 54038 Modified: pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/gc/hybrid.py pypy/dist/pypy/rpython/memory/gc/marksweep.py pypy/dist/pypy/rpython/memory/gc/semispace.py Log: Move the translation parameters of each GC out of base.py and into each GC class. Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Wed Apr 23 12:34:32 2008 @@ -269,31 +269,19 @@ """ if config.translation.gctransformer != "framework": # for tests config.translation.gc = "marksweep" # crash if inconsistent - if config.translation.gc == "marksweep": - GC_PARAMS = {'start_heap_size': 8*1024*1024} # XXX adjust - from pypy.rpython.memory.gc.marksweep import MarkSweepGC - return MarkSweepGC, GC_PARAMS - if config.translation.gc == "statistics": - GC_PARAMS = {'start_heap_size': 8*1024*1024} # XXX adjust - from pypy.rpython.memory.gc.marksweep import PrintingMarkSweepGC - return PrintingMarkSweepGC, GC_PARAMS - elif config.translation.gc == "semispace": - GC_PARAMS = {'space_size': 8*1024*1024} # XXX adjust - from pypy.rpython.memory.gc.semispace import SemiSpaceGC - return SemiSpaceGC, GC_PARAMS - elif config.translation.gc in ("generation", "hybrid"): - GC_PARAMS = {'space_size': 8*1024*1024, # XXX adjust - 'nursery_size': 896*1024, - 'min_nursery_size': 48*1024, - 'auto_nursery_size': True} - if config.translation.gc == "generation": - from pypy.rpython.memory.gc.generation import GenerationGC - return GenerationGC, GC_PARAMS - else: - GC_PARAMS['large_object'] = 1024 # XXX adjust - GC_PARAMS['large_object_gcptrs'] = 8192 # XXX adjust - from pypy.rpython.memory.gc.hybrid import HybridGC - return HybridGC, GC_PARAMS - else: + + classes = {"marksweep": "marksweep.MarkSweepGC", + "statistics": "marksweep.PrintingMarkSweepGC", + "semispace": "semispace.SemiSpaceGC", + "generation": "generation.GenerationGC", + "hybrid": "hybrid.HybridGC", + } + try: + modulename, classname = classes[config.translation.gc].split('.') + except KeyError: raise ValueError("unknown value for translation.gc: %r" % ( config.translation.gc,)) + module = __import__("pypy.rpython.memory.gc." + modulename, + globals(), locals(), [classname]) + GCClass = getattr(module, classname) + return GCClass, GCClass.TRANSLATION_PARAMS Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Wed Apr 23 12:34:32 2008 @@ -33,6 +33,13 @@ prebuilt_gc_objects_are_static_roots = False first_unused_gcflag = SemiSpaceGC.first_unused_gcflag << 2 + # the following values override the default arguments of __init__ when + # translating to a real backend. + TRANSLATION_PARAMS = {'space_size': 8*1024*1024, # XXX adjust + 'nursery_size': 896*1024, + 'min_nursery_size': 48*1024, + 'auto_nursery_size': True} + def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, nursery_size=128, min_nursery_size=128, Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Wed Apr 23 12:34:32 2008 @@ -16,6 +16,12 @@ """ first_unused_gcflag = GenerationGC.first_unused_gcflag << 1 + # the following values override the default arguments of __init__ when + # translating to a real backend. + TRANSLATION_PARAMS = GenerationGC.TRANSLATION_PARAMS.copy() + TRANSLATION_PARAMS['large_object'] = 1024 # XXX adjust + TRANSLATION_PARAMS['large_object_gcptrs'] = 8192 # XXX adjust + def __init__(self, *args, **kwds): large_object = kwds.pop('large_object', 24) large_object_gcptrs = kwds.pop('large_object_gcptrs', 32) Modified: pypy/dist/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/dist/pypy/rpython/memory/gc/marksweep.py Wed Apr 23 12:34:32 2008 @@ -39,6 +39,10 @@ POOLNODE.become(lltype.Struct('gc_pool_node', ('linkedlist', HDRPTR), ('nextnode', POOLNODEPTR))) + # the following values override the default arguments of __init__ when + # translating to a real backend. + TRANSLATION_PARAMS = {'start_heap_size': 8*1024*1024} # XXX adjust + def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096): self.heap_usage = 0 # at the end of the latest collection self.bytes_malloced = 0 # since the latest collection Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/dist/pypy/rpython/memory/gc/semispace.py Wed Apr 23 12:34:32 2008 @@ -38,6 +38,10 @@ ('forw', llmemory.Address)) FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) + # the following values override the default arguments of __init__ when + # translating to a real backend. + TRANSLATION_PARAMS = {'space_size': 8*1024*1024} # XXX adjust + def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, space_size=4096, max_space_size=sys.maxint//2+1): MovingGCBase.__init__(self) From arigo at codespeak.net Wed Apr 23 12:35:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 12:35:53 +0200 (CEST) Subject: [pypy-svn] r54039 - in pypy/dist/pypy: interpreter module/cStringIO objspace/std Message-ID: <20080423103553.F3CD216A3E4@codespeak.net> Author: arigo Date: Wed Apr 23 12:35:52 2008 New Revision: 54039 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/cStringIO/interp_stringio.py pypy/dist/pypy/objspace/std/intobject.py Log: Silence some of the innocent "demoting method to base class" warnings. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Wed Apr 23 12:35:52 2008 @@ -65,6 +65,9 @@ raise OperationError(space.w_TypeError, space.wrap("__class__ assignment: only for heap types")) + def user_setup(self, space, w_subtype): + assert False, "only for interp-level user subclasses from typedef.py" + def getname(self, space, default): try: return space.str_w(space.getattr(self, space.wrap('__name__'))) Modified: pypy/dist/pypy/module/cStringIO/interp_stringio.py ============================================================================== --- pypy/dist/pypy/module/cStringIO/interp_stringio.py (original) +++ pypy/dist/pypy/module/cStringIO/interp_stringio.py Wed Apr 23 12:35:52 2008 @@ -86,6 +86,15 @@ return self.space.wrap(self.tell()) descr_tell.unwrap_spec = ['self'] + # abstract methods + def close(self): assert False, "abstract" + def is_closed(self): assert False, "abstract" + def getvalue(self): assert False, "abstract" + def read(self, n=-1): assert False, "abstract" + def readline(self, size=-1): assert False, "abstract" + def seek(self, position, mode=0): assert False, "abstract" + def tell(self): assert False, "abstract" + # ____________________________________________________________ class W_InputType(W_InputOutputType): @@ -143,7 +152,7 @@ # ____________________________________________________________ -class W_OutputType(W_InputOutputType, RStringIO): +class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): RStringIO.__init__(self) self.space = space Modified: pypy/dist/pypy/objspace/std/intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/intobject.py (original) +++ pypy/dist/pypy/objspace/std/intobject.py Wed Apr 23 12:35:52 2008 @@ -12,6 +12,7 @@ """ class W_IntObject(W_Object): + __slots__ = 'intval' from pypy.objspace.std.inttype import int_typedef as typedef def __init__(w_self, intval): From fijal at codespeak.net Wed Apr 23 12:39:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 12:39:05 +0200 (CEST) Subject: [pypy-svn] r54040 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080423103905.B94EB16A3E4@codespeak.net> Author: fijal Date: Wed Apr 23 12:39:05 2008 New Revision: 54040 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Log: Primitive operations for implementing string builder, not working. Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Wed Apr 23 12:39:05 2008 @@ -232,3 +232,39 @@ hop.exception_cannot_occur() return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) + +def raw_array_of_shape(T, init_size): + """ Allocates a raw array of given shape. This array is suitable + for resizing by resize_raw_array or finalizing calling + cast_raw_array_to_shape + """ + from pypy.rpython.lltypesystem import lltype + return lltype.malloc(lltype.Array(lltype.Char, hints={'nolength':True}), + init_size, flavor='raw') + +class RawArrayOfShapeEntry(ExtRegistryEntry): + _about_ = raw_array_of_shape + +def resize_raw_array(arr, old_size, new_size): + """ Resize raw array returned by raw_array_of_shape from old_size + to new_size. Returns pointer to new array (in case resizing copied + contents of old array to new place + """ + from pypy.rpython.lltypesystem import lltype + # we don't have any realloc on top of cpython + new_ar = lltype.malloc(lltype.Array(lltype.Char, hints={'nolength':True}), + new_size, flavor='raw') + for i in range(old_size): + new_ar[i] = arr[i] + lltype.free(arr, flavor='raw') + return new_ar + +class ResizeRawArrayEntry(ExtRegistryEntry): + _about_ = resize_raw_array + +def cast_raw_array_to_shape(T, arr): + """ Cast raw array returned by raw_array_of_shape to type T. + """ + from pypy.rpython.lltypesystem import rffi, lltype + return rffi.cast(lltype.Ptr(T), arr) + Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Wed Apr 23 12:39:05 2008 @@ -2,6 +2,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rlib import rgc # Force registration of gc.collect import gc +import py def test_collect(): def f(): @@ -36,3 +37,19 @@ assert res == True +def test_raw_array(): + py.test.skip("Not working") + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + + def f(): + arr = rgc.raw_array_of_shape(STR, 1) + arr[0] = 'a' + arr = rgc.resize_raw_array(arr, 1, 2) + arr[1] = 'b' + return hlstr(rgc.cast_raw_array_to_shape(STR, arr)) + + assert f() == 'ab' +# from pypy.translator.c.test.test_genc import compile +# fn = compile(f, []) +# assert fn() == 'ab' From fijal at codespeak.net Wed Apr 23 12:48:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 12:48:39 +0200 (CEST) Subject: [pypy-svn] r54041 - pypy/branch/io-improvements/pypy/translator/goal Message-ID: <20080423104839.55EF016A3E3@codespeak.net> Author: fijal Date: Wed Apr 23 12:48:39 2008 New Revision: 54041 Added: pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py (contents, props changed) Modified: pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py Log: a target showcasing how bad is our readline implementation (after translation it's roughly 2x slower than run directly cpy version) Modified: pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py (original) +++ pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py Wed Apr 23 12:48:39 2008 @@ -8,14 +8,26 @@ """ import os, sys +from pypy.rpython.lltypesystem import lltype, llmemory + +def fib(n): + if n == 0 or n == 1: + return n + else: + return fib(n-1) + fib(n-2) def debug(msg): - os.write(2, "debug: " + msg + '\n') + for i in range(36): + print "n=%d => %d" % (i, fib(i)) + # __________ Entry point __________ def entry_point(argv): debug("hello world") + print llmemory.sizeof(lltype.UniChar) + if len(argv) > 3: + raise ValueError return 0 # _____ Define and setup target ___ Added: pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py Wed Apr 23 12:48:39 2008 @@ -0,0 +1,26 @@ + +from pypy.rlib.streamio import fdopen_as_stream + +def target(*args): + return main, None + +def main(args): + search = args[0] + FD = 0 + s = fdopen_as_stream(FD, 'r', 1024) + while True: + next_line = s.readline() + if not next_line: + break + if search in next_line: + print next_line + return 0 + +def cpy_main(s): + for x in sys.stdin.readlines(): + if s in x: + print x + +if __name__ == '__main__': + import sys + cpy_main(sys.argv[1]) From fijal at codespeak.net Wed Apr 23 12:56:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 12:56:04 +0200 (CEST) Subject: [pypy-svn] r54042 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080423105604.C7FDD16A3E3@codespeak.net> Author: fijal Date: Wed Apr 23 12:56:04 2008 New Revision: 54042 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Log: Make this working without using rffi.cast (thanks armin :) Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Wed Apr 23 12:56:04 2008 @@ -262,9 +262,18 @@ class ResizeRawArrayEntry(ExtRegistryEntry): _about_ = resize_raw_array -def cast_raw_array_to_shape(T, arr): +def cast_raw_array_to_shape(T, arr, size): """ Cast raw array returned by raw_array_of_shape to type T. """ - from pypy.rpython.lltypesystem import rffi, lltype - return rffi.cast(lltype.Ptr(T), arr) + from pypy.rpython.lltypesystem import lltype + res = lltype.malloc(T, size) + if isinstance(T, lltype.Array): + array_elem = res + elif isinstance(T, lltype.Struct): + array_elem = getattr(res, T._arrayfld) + else: + raise TypeError("Cannot cast %s" % T) + for num in range(size): + array_elem[num] = arr[num] + return res Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Wed Apr 23 12:56:04 2008 @@ -38,7 +38,6 @@ assert res == True def test_raw_array(): - py.test.skip("Not working") from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr @@ -47,7 +46,7 @@ arr[0] = 'a' arr = rgc.resize_raw_array(arr, 1, 2) arr[1] = 'b' - return hlstr(rgc.cast_raw_array_to_shape(STR, arr)) + return hlstr(rgc.cast_raw_array_to_shape(STR, arr, 2)) assert f() == 'ab' # from pypy.translator.c.test.test_genc import compile From fijal at codespeak.net Wed Apr 23 12:59:16 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 12:59:16 +0200 (CEST) Subject: [pypy-svn] r54043 - pypy/branch/io-improvements/pypy/rlib/test Message-ID: <20080423105916.A619816A272@codespeak.net> Author: fijal Date: Wed Apr 23 12:59:16 2008 New Revision: 54043 Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Log: remove commented out code, will go somewhere else. Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Wed Apr 23 12:59:16 2008 @@ -49,6 +49,3 @@ return hlstr(rgc.cast_raw_array_to_shape(STR, arr, 2)) assert f() == 'ab' -# from pypy.translator.c.test.test_genc import compile -# fn = compile(f, []) -# assert fn() == 'ab' From fijal at codespeak.net Wed Apr 23 13:20:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 13:20:07 +0200 (CEST) Subject: [pypy-svn] r54044 - pypy/branch/io-improvements/pypy/translator/goal Message-ID: <20080423112007.1537C2A018D@codespeak.net> Author: fijal Date: Wed Apr 23 13:20:07 2008 New Revision: 54044 Modified: pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py Log: Sorry, revert changes to targetnopstandalone Modified: pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py (original) +++ pypy/branch/io-improvements/pypy/translator/goal/targetnopstandalone.py Wed Apr 23 13:20:07 2008 @@ -8,26 +8,14 @@ """ import os, sys -from pypy.rpython.lltypesystem import lltype, llmemory - -def fib(n): - if n == 0 or n == 1: - return n - else: - return fib(n-1) + fib(n-2) def debug(msg): - for i in range(36): - print "n=%d => %d" % (i, fib(i)) - + os.write(2, "debug: " + msg + '\n') # __________ Entry point __________ def entry_point(argv): debug("hello world") - print llmemory.sizeof(lltype.UniChar) - if len(argv) > 3: - raise ValueError return 0 # _____ Define and setup target ___ From fijal at codespeak.net Wed Apr 23 13:27:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 13:27:04 +0200 (CEST) Subject: [pypy-svn] r54045 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080423112704.C6D572D800C@codespeak.net> Author: fijal Date: Wed Apr 23 13:27:04 2008 New Revision: 54045 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py Log: a bit of test fixing Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Wed Apr 23 13:27:04 2008 @@ -686,10 +686,10 @@ self.make_llexception() def op_malloc_nonmovable(self, obj, flags, size): - raise NotImplementedError + return self.op_malloc(obj, flags, size) def op_malloc_nonmovable_varsize(self, obj, flags, size): - raise NotImplementedError + return self.op_malloc_varsize(obj, flags, size) def op_free(self, obj, flavor): assert isinstance(flavor, str) From arigo at codespeak.net Wed Apr 23 13:34:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 13:34:51 +0200 (CEST) Subject: [pypy-svn] r54049 - pypy/dist/pypy/translator/microbench Message-ID: <20080423113451.B5C7B2A018D@codespeak.net> Author: arigo Date: Wed Apr 23 13:34:49 2008 New Revision: 54049 Modified: pypy/dist/pypy/translator/microbench/test_formatting.py Log: Remove the constant-folding that made these benchmarks completely bogus. Modified: pypy/dist/pypy/translator/microbench/test_formatting.py ============================================================================== --- pypy/dist/pypy/translator/microbench/test_formatting.py (original) +++ pypy/dist/pypy/translator/microbench/test_formatting.py Wed Apr 23 13:34:49 2008 @@ -2,8 +2,9 @@ def test_simple_formatting(): i = 0 + tup = ('foo', 'bar', 'baz') while i < iterations: - '%s - %s - %s' % ('foo', 'bar', 'baz') + '%s - %s - %s' % tup i += 1 def test_dict_formatting(): @@ -15,8 +16,9 @@ def test_number_formatting(): i = 0 + tup = (10, 10.1234, 10.1234) while i < iterations: - '%04d %g %2f' % (10, 10.1234, 10.1234) + '%04d %g %2f' % tup i += 1 def test_repr_formatting(): @@ -28,12 +30,14 @@ def test_format_unicode(): i = 0 + tup = (u'foo', u'bar') while i < iterations: - '%s %s' % (u'foo', u'bar') + '%s %s' % tup i += 1 def test_format_long(): i = 0 + tup = (100000000000L,) while i < iterations: - '%d' % (100000000000L,) + '%d' % tup i += 1 From arigo at codespeak.net Wed Apr 23 13:51:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 13:51:07 +0200 (CEST) Subject: [pypy-svn] r54050 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080423115107.172452A018D@codespeak.net> Author: arigo Date: Wed Apr 23 13:51:07 2008 New Revision: 54050 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py Log: A comment. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Wed Apr 23 13:51:07 2008 @@ -263,6 +263,12 @@ # the next usage. def reset_young_gcflags(self): + # This empties self.old_objects_pointing_to_young, and puts the + # GCFLAG_NO_YOUNG_PTRS back on all these objects. Note that + # trace_and_copy() above would also put the GCFLAG_NO_YOUNG_PTRS + # back on the same objects (unless they die, and then it doesn't + # matter) -- except that trace_and_copy() doesn't see the prebuilt + # objects. oldlist = self.old_objects_pointing_to_young while oldlist.non_empty(): obj = oldlist.pop() From arigo at codespeak.net Wed Apr 23 14:00:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 14:00:51 +0200 (CEST) Subject: [pypy-svn] r54051 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080423120051.C92C72A025E@codespeak.net> Author: arigo Date: Wed Apr 23 14:00:50 2008 New Revision: 54051 Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py Log: An XXX comment. Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Wed Apr 23 14:00:50 2008 @@ -143,6 +143,10 @@ # In order to free the large objects from time to time, we # arbitrarily force a full collect() if none occurs when we have # allocated 'self.space_size' bytes of large objects. + # XXX we should probably track the total raw_malloc'ed size + # XXX and adjust sizes based on it; otherwise we risk doing + # XXX many many collections if the program allocates a lot + # XXX more than the current self.space_size. self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) if self.large_objects_collect_trigger < 0: self.semispace_collect() From arigo at codespeak.net Wed Apr 23 14:52:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 14:52:05 +0200 (CEST) Subject: [pypy-svn] r54052 - pypy/branch/gc-improvements Message-ID: <20080423125205.2573C16A19F@codespeak.net> Author: arigo Date: Wed Apr 23 14:52:04 2008 New Revision: 54052 Added: pypy/branch/gc-improvements/ - copied from r54051, pypy/dist/ Log: A branch in which to play with the hybric GC. From arigo at codespeak.net Wed Apr 23 14:53:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 14:53:31 +0200 (CEST) Subject: [pypy-svn] r54053 - pypy/branch/gc-improvements/pypy/rpython/memory/gc Message-ID: <20080423125331.A5A6116A19F@codespeak.net> Author: arigo Date: Wed Apr 23 14:53:31 2008 New Revision: 54053 Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py Log: Mostly just moving code around. Preparation for supporting a hybrid GC that makes very old objects non-movable. Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py Wed Apr 23 14:53:31 2008 @@ -239,6 +239,8 @@ GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS = (GCFLAG_EXTERNAL | GCFLAG_FORWARDED | GCFLAG_NO_YOUNG_PTRS) + # ____________________________________________________________ + # Support code for full collections def semispace_collect(self, size_changing=False): self.reset_young_gcflags() # we are doing a full collection anyway @@ -249,13 +251,13 @@ SemiSpaceGC.semispace_collect(self, size_changing) if DEBUG_PRINT and not size_changing: llop.debug_print(lltype.Void, "percent survived", float(self.free - self.tospace) / self.space_size) - - def trace_and_copy(self, obj): - # during a full collect, all objects copied might come from the nursery and - # so must have this flag set: - self.header(obj).tid |= GCFLAG_NO_YOUNG_PTRS - SemiSpaceGC.trace_and_copy(self, obj) + def make_a_copy(self, obj, objsize): + newobj = SemiSpaceGC.make_a_copy(self, obj, objsize) + # During a full collect, all copied objects might implicitly come + # from the nursery. In case they do, we must add this flag: + self.header(newobj).tid |= GCFLAG_NO_YOUNG_PTRS + return newobj # history: this was missing and caused an object to become old but without the # flag set. Such an object is bogus in the sense that the write_barrier doesn't # work on it. So it can eventually contain a ptr to a young object but we didn't @@ -264,11 +266,11 @@ def reset_young_gcflags(self): # This empties self.old_objects_pointing_to_young, and puts the - # GCFLAG_NO_YOUNG_PTRS back on all these objects. Note that - # trace_and_copy() above would also put the GCFLAG_NO_YOUNG_PTRS - # back on the same objects (unless they die, and then it doesn't - # matter) -- except that trace_and_copy() doesn't see the prebuilt - # objects. + # GCFLAG_NO_YOUNG_PTRS back on all these objects. We could put + # the flag back more lazily but we expect this list to be short + # anyway, and it's much saner to stick to the invariant: + # non-young objects all have GCFLAG_NO_YOUNG_PTRS set unless + # they are listed in old_objects_pointing_to_young. oldlist = self.old_objects_pointing_to_young while oldlist.non_empty(): obj = oldlist.pop() @@ -280,6 +282,9 @@ obj = self.young_objects_with_weakrefs.pop() self.objects_with_weakrefs.append(obj) + # ____________________________________________________________ + # Implementation of nursery-only collections + def collect_nursery(self): if self.nursery_size > self.top_of_space - self.free: # the semispace is running out, do a full collect @@ -324,6 +329,8 @@ while oldlist.non_empty(): count += 1 obj = oldlist.pop() + hdr = self.header(obj) + hdr.tid |= GCFLAG_NO_YOUNG_PTRS self.trace_and_drag_out_of_nursery(obj) if DEBUG_PRINT: llop.debug_print(lltype.Void, "collect_oldrefs_to_nursery", count) @@ -354,7 +361,6 @@ """obj must not be in the nursery. This copies all the young objects it references out of the nursery. """ - self.header(obj).tid |= GCFLAG_NO_YOUNG_PTRS self.trace(obj, self._trace_drag_out, None) def _trace_drag_out(self, pointer, ignored): Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py Wed Apr 23 14:53:31 2008 @@ -318,19 +318,23 @@ #llop.debug_print(lltype.Void, obj, "already copied to", self.get_forwarding_address(obj)) return self.get_forwarding_address(obj) else: - newaddr = self.free objsize = self.get_size(obj) - totalsize = self.size_gc_header() + objsize - llarena.arena_reserve(newaddr, totalsize) - raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) - self.free += totalsize - newobj = newaddr + self.size_gc_header() + newobj = self.make_a_copy(obj, objsize) #llop.debug_print(lltype.Void, obj, "copied to", newobj, # "tid", self.header(obj).tid, # "size", totalsize) self.set_forwarding_address(obj, newobj, objsize) return newobj + def make_a_copy(self, obj, objsize): + totalsize = self.size_gc_header() + objsize + newaddr = self.free + self.free += totalsize + llarena.arena_reserve(newaddr, totalsize) + raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) + newobj = newaddr + self.size_gc_header() + return newobj + def trace_and_copy(self, obj): self.trace(obj, self._trace_copy, None) From fijal at codespeak.net Wed Apr 23 15:18:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 15:18:05 +0200 (CEST) Subject: [pypy-svn] r54054 - pypy/branch/io-improvements/pypy/rpython/memory/test Message-ID: <20080423131805.9D9BF2A018D@codespeak.net> Author: fijal Date: Wed Apr 23 15:18:05 2008 New Revision: 54054 Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Log: Dummy test_can_move for test_gc. It does not solve the issue of having static GC_CAN_MOVE flag though (not sure what to assert) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Wed Apr 23 15:18:05 2008 @@ -21,6 +21,7 @@ class GCTest(object): GC_PARAMS = {} + GC_CAN_MOVE = False def setup_class(cls): cls._saved_logstate = py.log._getstate() @@ -388,12 +389,19 @@ res = self.interpret(f, []) assert res == 42 + def test_can_move(self): + TP = lltype.GcArray(lltype.Float) + def func(): + from pypy.rlib import rgc + return rgc.can_move(lltype.malloc(TP, 1)) + assert self.interpret(func, []) == self.GC_CAN_MOVE class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass class TestSemiSpaceGC(GCTest, snippet.SemiSpaceGCTests): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass + GC_CAN_MOVE = True class TestGrowingSemiSpaceGC(TestSemiSpaceGC): GC_PARAMS = {'space_size': 64} From fijal at codespeak.net Wed Apr 23 16:51:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 16:51:50 +0200 (CEST) Subject: [pypy-svn] r54055 - in pypy/branch/io-improvements/pypy/rpython: . memory memory/test Message-ID: <20080423145150.C574F16A211@codespeak.net> Author: fijal Date: Wed Apr 23 16:51:48 2008 New Revision: 54055 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: * Add tests to test_gc * Simplify tests in test_tranformed_gc * support in llinterp for malloc_nonmoving (still, pretty basic) Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Wed Apr 23 16:51:48 2008 @@ -685,11 +685,17 @@ except MemoryError: self.make_llexception() - def op_malloc_nonmovable(self, obj, flags, size): - return self.op_malloc(obj, flags, size) + def op_malloc_nonmovable(self, obj, flags): + flavor = flags['flavor'] + assert flavor == 'gc' + zero = flags.get('zero', False) + return self.heap.malloc_nonmovable(obj, zero=zero) def op_malloc_nonmovable_varsize(self, obj, flags, size): - return self.op_malloc_varsize(obj, flags, size) + flavor = flags['flavor'] + assert flavor == 'gc' + zero = flags.get('zero', False) + return self.heap.malloc_nonmovable(obj, size, zero=zero) def op_free(self, obj, flavor): assert isinstance(flavor, str) Modified: pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py Wed Apr 23 16:51:48 2008 @@ -42,6 +42,16 @@ else: return lltype.malloc(TYPE, n, flavor=flavor, zero=zero) + def malloc_nonmovable(self, TYPE, n=None, zero=False): + typeid = self.get_type_id(TYPE) + if self.gc.moving_gc: + return lltype.nullptr(TYPE) + addr = self.gc.malloc(typeid, n, zero=zero) + result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + if not self.gc.malloc_zero_filled: + gctypelayout.zero_gc_pointers(result) + return result + def free(self, TYPE, flavor='gc'): assert flavor != 'gc' return lltype.free(TYPE, flavor=flavor) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Wed Apr 23 16:51:48 2008 @@ -396,6 +396,39 @@ return rgc.can_move(lltype.malloc(TP, 1)) assert self.interpret(func, []) == self.GC_CAN_MOVE + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + + def test_malloc_nonmovable_fixsize(self): + S = lltype.GcStruct('S', ('x', lltype.Float)) + TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Wed Apr 23 16:51:48 2008 @@ -457,12 +457,13 @@ res = run([]) assert res == self.GC_CAN_MOVE - def _test_malloc_nonmovable(self): + def test_malloc_nonmovable(self): TP = lltype.GcArray(lltype.Char) def func(): try: from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() if a: assert not rgc.can_move(a) return 0 @@ -470,12 +471,10 @@ except Exception, e: return 2 - # this test would have different outcome for different - # gcs, please assert differently run = self.runner(func) - return run([]) + assert int(self.GC_CAN_MOVE) == run([]) - def _test_malloc_nonmovable_fixsize(self): + def test_malloc_nonmovable_fixsize(self): S = lltype.GcStruct('S', ('x', lltype.Float)) TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) def func(): @@ -490,26 +489,23 @@ except Exception, e: return 2 - # this test would have different outcome for different - # gcs, please assert differently run = self.runner(func) - return run([]) + assert run([]) == int(self.GC_CAN_MOVE) - def test_malloc_nonmovable(self): - res = self._test_malloc_nonmovable() - if self.GC_CAN_MOVE: - expected = 1 - else: - expected = 0 - assert res == expected + def test_raw_array(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc - def test_malloc_nonmovable_fixsize(self): - res = self._test_malloc_nonmovable_fixsize() - if self.GC_CAN_MOVE: - expected = 1 - else: - expected = 0 - assert res == expected + def f(): + arr = rgc.raw_array_of_shape(STR, 1) + arr[0] = 'a' + arr = rgc.resize_raw_array(arr, 1, 2) + arr[1] = 'b' + return len(hlstr(rgc.cast_raw_array_to_shape(STR, arr, 2))) + + run = self.runner(f) + assert run([]) == 2 class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True From arigo at codespeak.net Wed Apr 23 17:54:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 17:54:08 +0200 (CEST) Subject: [pypy-svn] r54058 - pypy/branch/gc-improvements/pypy/rpython/memory/test Message-ID: <20080423155408.C6D2B16A3D5@codespeak.net> Author: arigo Date: Wed Apr 23 17:54:08 2008 New Revision: 54058 Modified: pypy/branch/gc-improvements/pypy/rpython/memory/test/snippet.py Log: Missing import. Modified: pypy/branch/gc-improvements/pypy/rpython/memory/test/snippet.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/test/snippet.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/test/snippet.py Wed Apr 23 17:54:08 2008 @@ -1,4 +1,4 @@ -import os +import os, py from pypy.tool.udir import udir from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop From arigo at codespeak.net Wed Apr 23 17:56:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 17:56:24 +0200 (CEST) Subject: [pypy-svn] r54059 - in pypy/branch/gc-improvements/pypy/rpython: lltypesystem lltypesystem/test memory/gc Message-ID: <20080423155624.6CC3C16A3D8@codespeak.net> Author: arigo Date: Wed Apr 23 17:56:23 2008 New Revision: 54059 Modified: pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llarena.py pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llmemory.py pypy/branch/gc-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/branch/gc-improvements/pypy/rpython/memory/gc/base.py Log: Not absolutely necessary for now, but allows cleaner code: if x is a symbolic offset from llmemory, and if it clearly cannot be negative, then "x >= 0" works (and returns True). Can be used to distinguish between such a symbolic offset and a special value like -1. Modified: pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llarena.py Wed Apr 23 17:56:23 2008 @@ -245,6 +245,9 @@ def __repr__(self): return '< RoundedUpForAllocation %r >' % (self.basesize,) + def known_nonneg(self): + return self.basesize.known_nonneg() + def ref(self, ptr): return self.basesize.ref(ptr) Modified: pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/lltypesystem/llmemory.py Wed Apr 23 17:56:23 2008 @@ -22,6 +22,23 @@ return NotImplemented return CompositeOffset(self, other) + # special-casing: only for '>= 0' and '< 0' and only when the + # symbolic offset is known to be non-negative + def __ge__(self, other): + if self is other: + return True + elif (isinstance(other, (int, long)) and other == 0 and + self.known_nonneg()): + return True + else: + raise TypeError("Symbolics can not be compared!") + + def __lt__(self, other): + return not self.__ge__(other) + + def known_nonneg(self): + return False + def _raw_malloc(self, rest, zero): raise NotImplementedError("_raw_malloc(%r, %r)" % (self, rest)) @@ -48,6 +65,9 @@ def __neg__(self): return ItemOffset(self.TYPE, -self.repeat) + def known_nonneg(self): + return self.repeat >= 0 + def ref(self, firstitemptr): A = lltype.typeOf(firstitemptr).TO if A == self.TYPE: @@ -138,6 +158,9 @@ def __repr__(self): return "" % (self.TYPE, self.fldname) + def known_nonneg(self): + return True + def ref(self, struct): if lltype.typeOf(struct).TO != self.TYPE: struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct) @@ -195,6 +218,12 @@ ofs.reverse() return CompositeOffset(*ofs) + def known_nonneg(self): + for item in self.offsets: + if not item.known_nonneg(): + return False + return True + def ref(self, ptr): for item in self.offsets: ptr = item.ref(ptr) @@ -220,6 +249,9 @@ def __repr__(self): return '< ArrayItemsOffset %r >' % (self.TYPE,) + def known_nonneg(self): + return True + def ref(self, arrayptr): assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE) if isinstance(self.TYPE.OF, lltype.ContainerType): @@ -255,6 +287,9 @@ def __repr__(self): return '< ArrayLengthOffset %r >' % (self.TYPE,) + def known_nonneg(self): + return True + def ref(self, arrayptr): assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE) return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid) @@ -270,6 +305,9 @@ def __neg__(self): return GCHeaderAntiOffset(self.gcheaderbuilder) + def known_nonneg(self): + return True + def ref(self, headerptr): gcptr = self.gcheaderbuilder.object_from_header(headerptr) return gcptr Modified: pypy/branch/gc-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py Wed Apr 23 17:56:23 2008 @@ -590,3 +590,15 @@ src = cast_ptr_to_adr(a) + itemoffsetof(A, 0) raw_memclear(src, sizeof(lltype.Signed) * 0) +def test_nonneg(): + S1 = lltype.GcStruct('S1', ('x', lltype.Float)) + A1 = lltype.GcArray(lltype.Float) + assert sizeof(S1) >= 0 + assert itemoffsetof(A1, 4) >= 0 + assert not (sizeof(S1) < 0) + assert not (itemoffsetof(A1, 4) < 0) + py.test.raises(TypeError, "sizeof(S1) > 0") + py.test.raises(TypeError, "sizeof(S1) > 1") + py.test.raises(TypeError, "sizeof(S1) <= 0") + py.test.raises(TypeError, "sizeof(S1) <= 4") + py.test.raises(TypeError, "(-sizeof(S1)) >= 0") Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/base.py Wed Apr 23 17:56:23 2008 @@ -59,14 +59,7 @@ size = self.fixed_size(typeid) needs_finalizer = bool(self.getfinalizer(typeid)) - weakptr_offset = self.weakpointer_offset(typeid) - #XXX cannot compare weakptr_offset with -1 - #contains_weakptr = weakpointer_offset. != -1 - if isinstance(weakptr_offset, int): - assert weakptr_offset == -1 - contains_weakptr = False - else: - contains_weakptr = True + contains_weakptr = self.weakpointer_offset(typeid) >= 0 assert not (needs_finalizer and contains_weakptr) if self.is_varsize(typeid): assert not contains_weakptr From arigo at codespeak.net Wed Apr 23 18:00:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 18:00:19 +0200 (CEST) Subject: [pypy-svn] r54060 - in pypy/branch/gc-improvements/pypy/rpython/memory: gc test Message-ID: <20080423160019.D74FA16A3CE@codespeak.net> Author: arigo Date: Wed Apr 23 18:00:18 2008 New Revision: 54060 Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-improvements/pypy/rpython/memory/test/test_gc.py Log: Probable improvement in the hybrid gc: the second time a non-young object is copied, move it to raw_malloc'ed memory so that further copies are not necessary. To do: check if it would be better to do this only after some more copies. Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/generation.py Wed Apr 23 18:00:18 2008 @@ -373,13 +373,13 @@ # weakref; otherwise invalidate the weakref while self.young_objects_with_weakrefs.non_empty(): obj = self.young_objects_with_weakrefs.pop() - if not self.is_forwarded(obj): + if not self.surviving(obj): continue # weakref itself dies obj = self.get_forwarding_address(obj) offset = self.weakpointer_offset(self.get_type_id(obj)) pointing_to = (obj + offset).address[0] if self.is_in_nursery(pointing_to): - if self.is_forwarded(pointing_to): + if self.surviving(pointing_to): (obj + offset).address[0] = self.get_forwarding_address( pointing_to) else: Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py Wed Apr 23 18:00:18 2008 @@ -1,12 +1,14 @@ import sys from pypy.rpython.memory.gc.semispace import SemiSpaceGC -from pypy.rpython.memory.gc.generation import GenerationGC +from pypy.rpython.memory.gc.generation import GenerationGC, GCFLAG_FORWARDED +from pypy.rpython.memory.gc.generation import GCFLAG_NO_YOUNG_PTRS from pypy.rpython.lltypesystem import llmemory, llarena from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0 +GCFLAG_AGING = GenerationGC.first_unused_gcflag << 1 class HybridGC(GenerationGC): @@ -14,7 +16,7 @@ except that objects above a certain size are handled separately: they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion. """ - first_unused_gcflag = GenerationGC.first_unused_gcflag << 1 + first_unused_gcflag = GenerationGC.first_unused_gcflag << 2 # the following values override the default arguments of __init__ when # translating to a real backend. @@ -150,8 +152,7 @@ self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) if self.large_objects_collect_trigger < 0: self.semispace_collect() - # XXX maybe we should use llarena.arena_malloc above a certain size? - result = llmemory.raw_malloc(totalsize) + result = self.allocate_external_object(totalsize) if not result: raise MemoryError() # The parent classes guarantee zero-filled allocations, so we @@ -161,6 +162,11 @@ self.large_objects_list.append(result + size_gc_header) return result + def allocate_external_object(self, totalsize): + # XXX maybe we should use arena_malloc() above a certain size? + # If so, we'd also use arena_reset() in malloc_varsize_marknsweep(). + return llmemory.raw_malloc(totalsize) + # ___________________________________________________________________ # the following methods are hook into SemiSpaceGC.semispace_collect() @@ -171,6 +177,14 @@ ll_assert(not self.pending_external_object_list.non_empty(), "pending_external_object_list should be empty at start") + def surviving(self, obj): + # To use during a collection. The objects that survive are the + # ones with GCFLAG_FORWARDED set and GCFLAG_UNVISITED not set. + # This is equivalent to self.is_forwarded() for all objects except + # the ones obtained by raw_malloc. + flags = self.header(obj).tid & (GCFLAG_FORWARDED|GCFLAG_UNVISITED) + return flags == GCFLAG_FORWARDED + def visit_external_object(self, obj): hdr = self.header(obj) if hdr.tid & GCFLAG_UNVISITED: @@ -178,6 +192,45 @@ hdr.tid -= GCFLAG_UNVISITED self.pending_external_object_list.append(obj) + def make_a_copy(self, obj, objsize): + # During a full collect, all copied objects might implicitly come + # from the nursery. If they do, we must add the GCFLAG_NO_YOUNG_PTRS. + # If they don't, we count how many times they are copied and when + # some threshold is reached we make the copy a non-movable "external" + # object. For now we use a single flag GCFLAG_AGING, so threshold==2. + tid = self.header(obj).tid + if not (tid & GCFLAG_NO_YOUNG_PTRS): + tid |= GCFLAG_NO_YOUNG_PTRS # object comes from the nursery + elif not (tid & GCFLAG_AGING): + tid |= GCFLAG_AGING + else: + newobj = self.make_a_nonmoving_copy(obj, objsize) + if newobj: + return newobj + tid &= ~GCFLAG_AGING + # skip GenerationGC.make_a_copy() as we already did the right + # thing about GCFLAG_NO_YOUNG_PTRS + newobj = SemiSpaceGC.make_a_copy(self, obj, objsize) + self.header(newobj).tid = tid + return newobj + + def make_a_nonmoving_copy(self, obj, objsize): + # NB. the object can have a finalizer or be a weakref, but + # it's not an issue. + totalsize = self.size_gc_header() + objsize + newaddr = self.allocate_external_object(totalsize) + if not newaddr: + return llmemory.NULL # can't raise MemoryError during a collect() + + llmemory.raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) + newobj = newaddr + self.size_gc_header() + hdr = self.header(newobj) + hdr.tid |= self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS + # GCFLAG_UNVISITED is not set + self.large_objects_list.append(newobj) + self.pending_external_object_list.append(newobj) + return newobj + def scan_copied(self, scan): # Alternate between scanning the regular objects we just moved # and scanning the raw_malloc'ed object we just visited. Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/semispace.py Wed Apr 23 18:00:18 2008 @@ -342,6 +342,14 @@ if pointer.address[0] != NULL: pointer.address[0] = self.copy(pointer.address[0]) + def surviving(self, obj): + # To use during a collection. Check if the object is currently + # marked as surviving the collection. This is equivalent to + # self.is_forwarded() for all objects except the nonmoving objects + # created by the HybridGC subclass. In all cases, if an object + # survives, self.get_forwarding_address() returns its new address. + return self.is_forwarded(obj) + def is_forwarded(self, obj): return self.header(obj).tid & GCFLAG_FORWARDED != 0 # note: all prebuilt objects also have this flag set @@ -427,7 +435,7 @@ x = self.objects_with_finalizers.popleft() ll_assert(self._finalization_state(x) != 1, "bad finalization state 1") - if self.is_forwarded(x): + if self.surviving(x): new_with_finalizer.append(self.get_forwarding_address(x)) continue marked.append(x) @@ -470,7 +478,7 @@ _append_if_nonnull = staticmethod(_append_if_nonnull) def _finalization_state(self, obj): - if self.is_forwarded(obj): + if self.surviving(obj): newobj = self.get_forwarding_address(obj) hdr = self.header(newobj) if hdr.tid & GCFLAG_FINALIZATION_ORDERING: @@ -520,14 +528,14 @@ new_with_weakref = self.AddressStack() while self.objects_with_weakrefs.non_empty(): obj = self.objects_with_weakrefs.pop() - if not self.is_forwarded(obj): + if not self.surviving(obj): continue # weakref itself dies obj = self.get_forwarding_address(obj) offset = self.weakpointer_offset(self.get_type_id(obj)) pointing_to = (obj + offset).address[0] # XXX I think that pointing_to cannot be NULL here if pointing_to: - if self.is_forwarded(pointing_to): + if self.surviving(pointing_to): (obj + offset).address[0] = self.get_forwarding_address( pointing_to) new_with_weakref.append(obj) Modified: pypy/branch/gc-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/test/test_gc.py Wed Apr 23 18:00:18 2008 @@ -428,3 +428,53 @@ return len("".join(lst)) res = self.interpret(concat, [100]) assert res == concat(100) + + def test_longliving_weakref(self): + # test for the case where a weakref points to a very old object + # that was made non-movable after several collections + import gc, weakref + class A: + pass + def step1(x): + a = A() + a.x = 42 + ref = weakref.ref(a) + i = 0 + while i < x: + gc.collect() + i += 1 + assert ref() is a + assert ref().x == 42 + return ref + def step2(ref): + gc.collect() # 'a' is freed here + assert ref() is None + def f(x): + ref = step1(x) + step2(ref) + self.interpret(f, [10]) + + def test_longliving_object_with_finalizer(self): + class B(object): + pass + b = B() + b.nextid = 0 + b.num_deleted = 0 + class A(object): + def __init__(self): + self.id = b.nextid + b.nextid += 1 + def __del__(self): + b.num_deleted += 1 + def f(x): + a = A() + i = 0 + while i < x: + i += 1 + a = A() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return b.num_deleted + res = self.interpret(f, [15]) + assert res == 16 From fijal at codespeak.net Wed Apr 23 19:02:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 19:02:04 +0200 (CEST) Subject: [pypy-svn] r54061 - pypy/branch/io-improvements/pypy Message-ID: <20080423170204.156D316A3CC@codespeak.net> Author: fijal Date: Wed Apr 23 19:02:02 2008 New Revision: 54061 Modified: pypy/branch/io-improvements/pypy/FAILURES Log: this test passes these days. Modified: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- pypy/branch/io-improvements/pypy/FAILURES (original) +++ pypy/branch/io-improvements/pypy/FAILURES Wed Apr 23 19:02:02 2008 @@ -1,4 +1,3 @@ -rpython/memory/test/test_transformed_gc.py -k test_tree_cloning rpython/test/test_rbuiltin.py rpython/module/test/test_posix.py rpython/lltypesystem/test/test_lloperation.py From fijal at codespeak.net Wed Apr 23 19:23:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 19:23:09 +0200 (CEST) Subject: [pypy-svn] r54062 - pypy/branch/io-improvements/pypy/translator Message-ID: <20080423172309.0E7E216A3D0@codespeak.net> Author: fijal Date: Wed Apr 23 19:23:08 2008 New Revision: 54062 Modified: pypy/branch/io-improvements/pypy/translator/exceptiontransform.py Log: This fixes test_transformed_gc, although I'm not sure exactly if this is a right fix. Modified: pypy/branch/io-improvements/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/exceptiontransform.py (original) +++ pypy/branch/io-improvements/pypy/translator/exceptiontransform.py Wed Apr 23 19:23:08 2008 @@ -346,7 +346,7 @@ block.recloseblock(l0, l) insert_zeroing_op = False - if spaceop.opname == 'malloc': + if spaceop.opname == 'malloc' or spaceop.opname == 'malloc_nonmovable': flavor = spaceop.args[1].value['flavor'] if flavor == 'gc': insert_zeroing_op = True From fijal at codespeak.net Wed Apr 23 19:27:14 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 19:27:14 +0200 (CEST) Subject: [pypy-svn] r54063 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080423172714.56BE416A3D3@codespeak.net> Author: fijal Date: Wed Apr 23 19:27:13 2008 New Revision: 54063 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py Log: malloc_nonmovable and malloc are essentially the same here Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py Wed Apr 23 19:27:13 2008 @@ -17,3 +17,5 @@ def weakref_create_getlazy(objgetter): return weakref_create(objgetter()) + +malloc_nonmovable = malloc From fijal at codespeak.net Wed Apr 23 19:33:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 19:33:41 +0200 (CEST) Subject: [pypy-svn] r54064 - pypy/branch/io-improvements/pypy/translator Message-ID: <20080423173341.40F1516A3DC@codespeak.net> Author: fijal Date: Wed Apr 23 19:33:39 2008 New Revision: 54064 Modified: pypy/branch/io-improvements/pypy/translator/exceptiontransform.py Log: Leave XXX Modified: pypy/branch/io-improvements/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/exceptiontransform.py (original) +++ pypy/branch/io-improvements/pypy/translator/exceptiontransform.py Wed Apr 23 19:33:39 2008 @@ -346,6 +346,9 @@ block.recloseblock(l0, l) insert_zeroing_op = False + # XXX this is not right. it also inserts zero_gc_pointers_inside + # XXX on a path that malloc_nonmovable returns null, but does not raise + # XXX which might end up with a segfault. But we don't have such gc now if spaceop.opname == 'malloc' or spaceop.opname == 'malloc_nonmovable': flavor = spaceop.args[1].value['flavor'] if flavor == 'gc': From fijal at codespeak.net Wed Apr 23 19:46:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 19:46:05 +0200 (CEST) Subject: [pypy-svn] r54065 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080423174605.B9F9816A3E1@codespeak.net> Author: fijal Date: Wed Apr 23 19:46:04 2008 New Revision: 54065 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Log: Fix a bit tests. use llmemory.sizeof instead of rffi.sizeof, which gives the same numeric value but it's something different. Still explodes on ll2ctypes varsized structs. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Wed Apr 23 19:46:04 2008 @@ -18,6 +18,7 @@ from pypy.rpython.annlowlevel import llhelper, llstr, hlstr from pypy.rpython.lltypesystem.rstr import STR from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import llmemory import os class UnhandledRPythonException(Exception): @@ -538,7 +539,8 @@ dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: This is bad, because dest could potentially move ## if there are threads involved. - raw_memcopy(cast_ptr_to_adr(raw_buf), dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(cast_ptr_to_adr(raw_buf), dest, + llmemory.sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) @@ -548,7 +550,8 @@ try: dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: see above - raw_memcopy(cast_ptr_to_adr(raw_buf), dest, sizeof(lltype.Char) * needed_size) + raw_memcopy(cast_ptr_to_adr(raw_buf), dest, + llmemory.sizeof(lltype.Char) * needed_size) return hlstr(new_buf) finally: keepalive_until_here(new_buf) From fijal at codespeak.net Wed Apr 23 19:48:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 19:48:06 +0200 (CEST) Subject: [pypy-svn] r54066 - pypy/branch/io-improvements/pypy Message-ID: <20080423174806.2797816A3E7@codespeak.net> Author: fijal Date: Wed Apr 23 19:48:05 2008 New Revision: 54066 Modified: pypy/branch/io-improvements/pypy/FAILURES Log: update the list. I fear those items will stay here for a while... Modified: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- pypy/branch/io-improvements/pypy/FAILURES (original) +++ pypy/branch/io-improvements/pypy/FAILURES Wed Apr 23 19:48:05 2008 @@ -1,4 +1,4 @@ rpython/test/test_rbuiltin.py rpython/module/test/test_posix.py -rpython/lltypesystem/test/test_lloperation.py -rpython/memory/test/test_transformed_gc.py -k test_malloc_nonmovable_fixsize + + From fijal at codespeak.net Wed Apr 23 20:02:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Apr 2008 20:02:12 +0200 (CEST) Subject: [pypy-svn] r54067 - in pypy/branch/io-improvements/pypy/rpython/lltypesystem: . test Message-ID: <20080423180212.6AAD016A3CF@codespeak.net> Author: fijal Date: Wed Apr 23 20:02:10 2008 New Revision: 54067 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Shady support for varsized structs. Just enough to get strings running Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/ll2ctypes.py Wed Apr 23 20:02:10 2008 @@ -241,9 +241,12 @@ carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): + # fish that we have enough space + ctypes_array = ctypes.cast(carray.items, + ctypes.POINTER(carray.items._type_)) for i in range(container.getlength()): item_value = container.items[i] # fish fish - carray.items[i] = lltype2ctypes(item_value) + ctypes_array[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) @@ -262,7 +265,10 @@ remove_regular_struct_content(container) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) - if isinstance(FIELDTYPE, lltype.ContainerType): + if isinstance(FIELDTYPE, lltype.Array): + convert_array(getattr(container, field_name), + getattr(ctypes_storage, field_name)) + elif isinstance(FIELDTYPE, lltype.ContainerType): struct_use_ctypes_storage(getattr(container, field_name), getattr(ctypes_storage, field_name)) @@ -498,8 +504,10 @@ return lltype.nullptr(T.TO) if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: - raise NotImplementedError("XXX var-sized structs") - container = lltype._struct(T.TO) + lgt = getattr(cobj.contents, T.TO._arrayfld).length + container = lltype._struct(T.TO, lgt) + else: + container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Wed Apr 23 20:02:10 2008 @@ -6,7 +6,7 @@ from pypy.rpython.lltypesystem.ll2ctypes import lltype2ctypes, ctypes2lltype from pypy.rpython.lltypesystem.ll2ctypes import standard_c_lib from pypy.rpython.lltypesystem.ll2ctypes import uninitialized2ctypes -from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED +from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED, force_cast from pypy.rpython.annlowlevel import llhelper from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -817,3 +817,13 @@ c1 = lltype2ctypes(a1) c2 = lltype2ctypes(a2) assert type(c1) is type(c2) + + def test_varsized_struct(self): + STR = lltype.Struct('rpy_string', ('hash', lltype.Signed), + ('chars', lltype.Array(lltype.Char, hints={'immutable': True}))) + s = lltype.malloc(STR, 3, flavor='raw') + one = force_cast(rffi.VOIDP, s) + # sanity check + #assert lltype2ctypes(one).contents.items._length_ > 0 + two = force_cast(lltype.Ptr(STR), one) + assert s == two From arigo at codespeak.net Wed Apr 23 21:42:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Apr 2008 21:42:11 +0200 (CEST) Subject: [pypy-svn] r54069 - pypy/branch/gc-improvements/pypy/translator/c/gcc Message-ID: <20080423194211.5967C2A025A@codespeak.net> Author: arigo Date: Wed Apr 23 21:42:09 2008 New Revision: 54069 Modified: pypy/branch/gc-improvements/pypy/translator/c/gcc/trackgcroot.py Log: More instructions that can show up with -march=pentium4. Modified: pypy/branch/gc-improvements/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/gc-improvements/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/gc-improvements/pypy/translator/c/gcc/trackgcroot.py Wed Apr 23 21:42:09 2008 @@ -429,9 +429,10 @@ IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([ 'cmp', 'test', 'set', 'sahf', 'cltd', 'cld', 'std', - 'rep', 'movs', 'lods', 'stos', 'scas', 'cwtl', + 'rep', 'movs', 'lods', 'stos', 'scas', 'cwtl', 'prefetch', # floating-point operations cannot produce GC pointers 'f', + 'cvt', # sse2 # arithmetic operations should not produce GC pointers 'inc', 'dec', 'not', 'neg', 'or', 'and', 'sbb', 'adc', 'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'mul', 'imul', 'div', 'idiv', From bgola at codespeak.net Thu Apr 24 07:32:20 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Thu, 24 Apr 2008 07:32:20 +0200 (CEST) Subject: [pypy-svn] r54078 - in pypy/branch/2.5-features/pypy: module/__builtin__ module/__builtin__/test objspace Message-ID: <20080424053220.3C5BF2A0187@codespeak.net> Author: bgola Date: Thu Apr 24 07:32:18 2008 New Revision: 54078 Modified: pypy/branch/2.5-features/pypy/module/__builtin__/interp_classobj.py pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py pypy/branch/2.5-features/pypy/objspace/descroperation.py Log: 2.5 __hash__ new behavior, can return either a long or an integer Modified: pypy/branch/2.5-features/pypy/module/__builtin__/interp_classobj.py ============================================================================== --- pypy/branch/2.5-features/pypy/module/__builtin__/interp_classobj.py (original) +++ pypy/branch/2.5-features/pypy/module/__builtin__/interp_classobj.py Thu Apr 24 07:32:18 2008 @@ -541,10 +541,11 @@ else: return space.wrap(hash(self)) w_ret = space.call_function(w_func) - if not space.is_true(space.isinstance(w_ret, space.w_int)): + if (not space.is_true(space.isinstance(w_ret, space.w_int)) and + not space.is_true(space.isinstance(w_ret, space.w_long))): raise OperationError( space.w_TypeError, - space.wrap("__hash__ must return int")) + space.wrap("__hash__ must return int or long")) return w_ret def descr_index(self, space): Modified: pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py Thu Apr 24 07:32:18 2008 @@ -484,6 +484,11 @@ return 1 a = A() raises(TypeError, hash, a) + class A: # can return long + def __hash__(self): + return long(1) + a = A() + assert hash(a) == long(1) def test_index(self): import sys Modified: pypy/branch/2.5-features/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/2.5-features/pypy/objspace/descroperation.py (original) +++ pypy/branch/2.5-features/pypy/objspace/descroperation.py Thu Apr 24 07:32:18 2008 @@ -287,11 +287,12 @@ space.wrap("unhashable type")) return default_identity_hash(space, w_obj) w_result = space.get_and_call_function(w_hash, w_obj) - if space.is_true(space.isinstance(w_result, space.w_int)): + if (space.is_true(space.isinstance(w_result, space.w_int)) or + space.is_true(space.isinstance(w_result, space.w_long))): return w_result else: raise OperationError(space.w_TypeError, - space.wrap("__hash__() should return an int")) + space.wrap("__hash__() should return an int or long")) def userdel(space, w_obj): w_del = space.lookup(w_obj, '__del__') From bgola at codespeak.net Thu Apr 24 08:10:36 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Thu, 24 Apr 2008 08:10:36 +0200 (CEST) Subject: [pypy-svn] r54079 - pypy/branch/2.5-features/pypy/objspace/test Message-ID: <20080424061036.6312D169EEA@codespeak.net> Author: bgola Date: Thu Apr 24 08:10:34 2008 New Revision: 54079 Modified: pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py Log: test for new hash() behavior Modified: pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py ============================================================================== --- pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py (original) +++ pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py Thu Apr 24 08:10:34 2008 @@ -71,3 +71,7 @@ def __hash__(self): return "something" raises(TypeError, hash, E()) + class F: # can return long + def __hash__(self): + return long(1) + assert hash(F()) == long(1) From antocuni at codespeak.net Thu Apr 24 14:31:05 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Apr 2008 14:31:05 +0200 (CEST) Subject: [pypy-svn] r54082 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080424123105.5045D16A40F@codespeak.net> Author: antocuni Date: Thu Apr 24 14:31:03 2008 New Revision: 54082 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Log: implement handle_green_oosend Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Thu Apr 24 14:31:03 2008 @@ -56,32 +56,28 @@ colororder = None return colororder -class CallDesc: +class BaseCallDesc(object): + __metaclass__ = cachedtype - def __init__(self, RGenOp, exceptiondesc, FUNCTYPE, colororder=None): - self.exceptiondesc = exceptiondesc - self.sigtoken = RGenOp.sigToken(get_functype(FUNCTYPE)) - self.result_kind = RGenOp.kindToken(get_functype(FUNCTYPE).RESULT) - self.colororder = colororder - # xxx what if the result is virtualizable? - self.redboxbuilder = rvalue.ll_redboxbuilder(get_functype(FUNCTYPE).RESULT) - whatever_return_value = get_functype(FUNCTYPE).RESULT._defl() - numargs = len(get_functype(FUNCTYPE).ARGS) - voidargcount = 0 - for ARG in get_functype(FUNCTYPE).ARGS: - if ARG == lltype.Void: - voidargcount += 1 - argiter = unrolling_iterable(get_functype(FUNCTYPE).ARGS) - RETURN = get_functype(FUNCTYPE).RESULT - if RETURN is lltype.Void: + def _define_return_value(self, RGenOp, FUNCTYPE): + RESULT = get_functype(FUNCTYPE).RESULT + if RESULT is lltype.Void: self.gv_whatever_return_value = None else: + whatever_return_value = RESULT._defl() self.gv_whatever_return_value = RGenOp.constPrebuiltGlobal( whatever_return_value) - def perform_call(rgenop, gv_fnptr, args_gv): - fnptr = gv_fnptr.revealconst(FUNCTYPE) + def _define_do_perform_call(self, ARGS, RESULT): + numargs = len(ARGS) + voidargcount = 0 + for ARG in ARGS: + if ARG == lltype.Void: + voidargcount += 1 + argiter = unrolling_iterable(ARGS) + + def do_perform_call(rgenop, fn_or_meth, args_gv): assert len(args_gv) + voidargcount == numargs args = () j = 0 @@ -93,13 +89,14 @@ arg = genconst.revealconst(ARG) args += (arg, ) j += 1 - result = maybe_on_top_of_llinterp(self.exceptiondesc, fnptr)(*args) - if RETURN is lltype.Void: + result = maybe_on_top_of_llinterp(self.exceptiondesc, fn_or_meth)(*args) + if RESULT is lltype.Void: return None else: return rgenop.genconst(result) - self.perform_call = perform_call + self.do_perform_call = do_perform_call + return do_perform_call def _freeze_(self): return True @@ -119,6 +116,26 @@ if gv_result is not None: interpreter.green_result(gv_result) + +class CallDesc(BaseCallDesc): + + def __init__(self, RGenOp, exceptiondesc, FUNCTYPE, colororder=None): + self.exceptiondesc = exceptiondesc + self.sigtoken = RGenOp.sigToken(get_functype(FUNCTYPE)) + self.result_kind = RGenOp.kindToken(get_functype(FUNCTYPE).RESULT) + self.colororder = colororder + # xxx what if the result is virtualizable? + self.redboxbuilder = rvalue.ll_redboxbuilder(get_functype(FUNCTYPE).RESULT) + + T = get_functype(FUNCTYPE) + do_perform_call = self._define_do_perform_call(T.ARGS, T.RESULT) + self._define_return_value(RGenOp, FUNCTYPE) + + def perform_call(rgenop, gv_fnptr, greenargs): + fnptr = gv_fnptr.revealconst(FUNCTYPE) + return do_perform_call(rgenop, fnptr, greenargs) + self.perform_call = perform_call + def perform_call_mixed(self, rgenop, gv_fnptr, greens_gv, reds_gv): if self.colororder is None: args_gv = greens_gv + reds_gv @@ -166,14 +183,26 @@ self.calldesc = CallDesc(codewriter.RGenOp, codewriter.exceptiondesc, lltype.typeOf(fnptr), colororder) -class MethodDesc(object): +class MethodDesc(BaseCallDesc): - def __init__(self, RGenOp, SELFTYPE, methname): + def __init__(self, RGenOp, exceptiondesc, SELFTYPE, methname): + self.exceptiondesc = exceptiondesc + self.SELFTYPE = SELFTYPE + self.methname = methname + _, meth = SELFTYPE._lookup(methname) METH = ootype.typeOf(meth) self.methtoken = RGenOp.methToken(SELFTYPE, methname) self.redboxbuilder = rvalue.ll_redboxbuilder(METH.RESULT) + self.colororder = None + ARGS = (SELFTYPE,) + METH.ARGS + do_perform_call = self._define_do_perform_call(ARGS, METH.RESULT) + self._define_return_value(RGenOp, METH) + def perform_call(rgenop, gv_fnptr, args_gv): + assert gv_fnptr is None + return do_perform_call(rgenop, meth, args_gv) + self.perform_call = perform_call class BytecodeWriter(object): @@ -852,7 +881,7 @@ if key in self.methdesc_positions: return self.methdesc_positions[tok] result = len(self.methdescs) - desc = MethodDesc(self.RGenOp, TYPE, name) + desc = MethodDesc(self.RGenOp, self.exceptiondesc, TYPE, name) self.methdescs.append(desc) self.methdesc_positions[key] = result return result @@ -1691,7 +1720,19 @@ return handler(op, withexc) def handle_green_oosend(self, op, withexc): - assert False, 'TODO' + SELFTYPE, name, opargs = self.decompose_oosend(op) + has_result = self.has_result(op) + pos = self.methdesc_position(SELFTYPE, name) + emitted_args = [] + for v in op.args[1:]: + if v.concretetype != lltype.Void: + emitted_args.append(self.serialize_oparg("green", v)) + self.emit("green_oosend") + self.emit(pos) + self.emit(len(emitted_args)) + self.emit(*emitted_args) + if op.result.concretetype != ootype.Void: + self.register_greenvar(op.result) def handle_oopspec_oosend(self, op, withexc): SELFTYPE, name, opargs = self.decompose_oosend(op) Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 24 14:31:03 2008 @@ -1093,6 +1093,11 @@ self.run(self.jitstate, bytecode, greenargs, redargs, start_bytecode_loop=False) + @arguments("methdesc", "green_varargs") + def opimpl_green_oosend(self, methdesc, greenargs): + # we pass None as fnptr, since it's not needed/used + methdesc.green_call(self, None, greenargs) + @arguments("red_varargs", "methdesc", "bool") def opimpl_builtin_oosend(self, redargs, methdesc, has_result): result = rtimeshift.gen_external_oosend(self.jitstate, redargs, Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 24 14:31:03 2008 @@ -1004,7 +1004,6 @@ self.check_insns({}) def test_green_deepfrozen_oosend(self): - py.test.skip('in progress') d = {1: 2, 2: 4, 3: 9} def f(k): d1 = hint(d, deepfreeze=True) From antocuni at codespeak.net Thu Apr 24 14:35:01 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Apr 2008 14:35:01 +0200 (CEST) Subject: [pypy-svn] r54083 - pypy/branch/jit-hotpath/pypy/jit/rainbow/test Message-ID: <20080424123501.EC93639B5BB@codespeak.net> Author: antocuni Date: Thu Apr 24 14:35:01 2008 New Revision: 54083 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Log: this test passes out of the box Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Thu Apr 24 14:35:01 2008 @@ -610,7 +610,6 @@ def _skip(self): py.test.skip('in progress') - test_dfa_compile2 = _skip test_dfa_compile3 = _skip test_method_call_nonpromote = _skip test_method_call_promote = _skip From antocuni at codespeak.net Thu Apr 24 15:31:17 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Apr 2008 15:31:17 +0200 (CEST) Subject: [pypy-svn] r54091 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test Message-ID: <20080424133117.AA80416A3FD@codespeak.net> Author: antocuni Date: Thu Apr 24 15:31:17 2008 New Revision: 54091 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Log: yet another kind of oosend, for the case in which the self is green and thus the bytecode is known at compile time Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Thu Apr 24 15:31:17 2008 @@ -1540,6 +1540,9 @@ return 'oopspec', self.can_raise(spaceop) if not SELFTYPE._lookup_graphs(methname): return 'builtin', self.can_raise(spaceop) + hs_self = self.hannotator.binding(spaceop.args[1]) + if hs_self.is_green(): + return 'direct', self.can_raise(spaceop) if self.hannotator.bookkeeper.is_green_call(spaceop): return 'green', None withexc = self.can_raise(spaceop) @@ -1787,6 +1790,23 @@ if has_result: self.register_redvar(op.result) + def handle_direct_oosend(self, op, withexc): + SELFTYPE, name, opargs = self.decompose_oosend(op) + has_result = self.has_result(op) + _, meth = SELFTYPE._lookup(name) + graph2tsgraph = dict(self.graphs_from(op)) + targetgraph = graph2tsgraph[meth.graph] + graphindex = self.graph_position(targetgraph) + bytecode = self.all_graphs[targetgraph] + args = targetgraph.getargs() + emitted_args = self.args_of_call(op.args[1:], args) + assert not self.hannotator.policy.hotpath, 'TODO' + self.emit('direct_oosend') + self.emit(*emitted_args) + self.emit(graphindex) + if has_result: + self.register_redvar(op.result) + def handle_yellow_oosend(self, op, withexc): self.handle_red_oosend(op, withexc) self.emit("yellow_retrieve_result_as_red") Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Thu Apr 24 15:31:17 2008 @@ -1093,6 +1093,11 @@ self.run(self.jitstate, bytecode, greenargs, redargs, start_bytecode_loop=False) + @arguments("green_varargs", "red_varargs", "bytecode") + def opimpl_direct_oosend(self, greenargs, redargs, targetbytecode): + self.run(self.jitstate, targetbytecode, greenargs, redargs, + start_bytecode_loop=False) + @arguments("methdesc", "green_varargs") def opimpl_green_oosend(self, methdesc, greenargs): # we pass None as fnptr, since it's not needed/used Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_interpreter.py Thu Apr 24 15:31:17 2008 @@ -1013,6 +1013,21 @@ assert res == 9 self.check_insns({}) + def test_direct_oosend_with_green_self(self): + class Foo: + def __init__(self, x): + self.data = [x] + def getitem(self, i): + return self.data[i] + + obj = Foo(42) + def fn(x): + obj1 = hint(obj, deepfreeze=True) + return obj1.getitem(0) + res = self.interpret(fn, [42], []) + assert res == 42 + self.check_insns({'direct_call': 1}) + def test_residual_red_call(self): def g(x): return x+1 Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_portal.py Thu Apr 24 15:31:17 2008 @@ -610,7 +610,6 @@ def _skip(self): py.test.skip('in progress') - test_dfa_compile3 = _skip test_method_call_nonpromote = _skip test_method_call_promote = _skip test_float_promote = _skip From docgok at codespeak.net Thu Apr 24 17:41:28 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 24 Apr 2008 17:41:28 +0200 (CEST) Subject: [pypy-svn] r54098 - in pypy/branch/io-improvements/pypy/rpython: lltypesystem test Message-ID: <20080424154128.7C27B16A300@codespeak.net> Author: docgok Date: Thu Apr 24 17:41:26 2008 New Revision: 54098 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py pypy/branch/io-improvements/pypy/rpython/test/test_rbuiltin.py Log: Correctly handle the "non-moving buffer is too big" case when using llinterp. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rffi.py Thu Apr 24 17:41:26 2008 @@ -531,30 +531,25 @@ The returned string will be truncated to needed_size. """ assert allocated_size >= needed_size - str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - if gc_buf: - if allocated_size != needed_size: - new_buf = lltype.malloc(STR, needed_size) - try: - dest = cast_ptr_to_adr(new_buf) + str_chars_offset - ## FIXME: This is bad, because dest could potentially move - ## if there are threads involved. - raw_memcopy(cast_ptr_to_adr(raw_buf), dest, - llmemory.sizeof(lltype.Char) * needed_size) - return hlstr(new_buf) - finally: - keepalive_until_here(new_buf) + + if gc_buf and (allocated_size == needed_size): return hlstr(gc_buf) - else: - new_buf = lltype.malloc(STR, needed_size) - try: - dest = cast_ptr_to_adr(new_buf) + str_chars_offset - ## FIXME: see above - raw_memcopy(cast_ptr_to_adr(raw_buf), dest, - llmemory.sizeof(lltype.Char) * needed_size) - return hlstr(new_buf) - finally: - keepalive_until_here(new_buf) + + new_buf = lltype.malloc(STR, needed_size) + try: + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + if gc_buf: + src = cast_ptr_to_adr(gc_buf) + str_chars_offset + else: + src = cast_ptr_to_adr(raw_buf) + dest = cast_ptr_to_adr(new_buf) + str_chars_offset + ## FIXME: This is bad, because dest could potentially move + ## if there are threads involved. + raw_memcopy(src, dest, + llmemory.sizeof(lltype.Char) * needed_size) + return hlstr(new_buf) + finally: + keepalive_until_here(new_buf) # (char*, str) -> None def keep_buffer_alive_until_here(raw_buf, gc_buf): Modified: pypy/branch/io-improvements/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_rbuiltin.py Thu Apr 24 17:41:26 2008 @@ -221,10 +221,10 @@ f = file(tmpfile, 'w') f.write('hello world') f.close() - def f(): + def fn(): fd = os.open(tmpfile, os.O_RDONLY, 0777) return os.read(fd, 4096) - res = self.interpret(f, []) + res = self.interpret(fn, []) assert self.ll_to_string(res) == 'hello world' def test_os_lseek(self): From docgok at codespeak.net Thu Apr 24 17:44:00 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 24 Apr 2008 17:44:00 +0200 (CEST) Subject: [pypy-svn] r54099 - pypy/branch/io-improvements/pypy Message-ID: <20080424154400.9C81A16A300@codespeak.net> Author: docgok Date: Thu Apr 24 17:43:59 2008 New Revision: 54099 Modified: pypy/branch/io-improvements/pypy/FAILURES Log: test_posix doesn't seem to fail any more. Modified: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- pypy/branch/io-improvements/pypy/FAILURES (original) +++ pypy/branch/io-improvements/pypy/FAILURES Thu Apr 24 17:43:59 2008 @@ -1,4 +1,2 @@ rpython/test/test_rbuiltin.py -rpython/module/test/test_posix.py - From antocuni at codespeak.net Fri Apr 25 10:42:02 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 25 Apr 2008 10:42:02 +0200 (CEST) Subject: [pypy-svn] r54124 - pypy/dist/pypy/translator/jvm Message-ID: <20080425084202.53CFE16A089@codespeak.net> Author: antocuni Date: Fri Apr 25 10:42:00 2008 New Revision: 54124 Modified: pypy/dist/pypy/translator/jvm/opcodes.py Log: "implement" these two new opcodes Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Fri Apr 25 10:42:00 2008 @@ -92,6 +92,8 @@ 'gc__collect': jvm.SYSTEMGC, 'gc_set_max_heap_size': Ignore, + 'gc__enable_finalizers': Ignore, + 'gc__disable_finalizers': Ignore, 'resume_point': Ignore, 'debug_assert': [], # TODO: implement? From arigo at codespeak.net Fri Apr 25 12:54:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 25 Apr 2008 12:54:52 +0200 (CEST) Subject: [pypy-svn] r54128 - pypy/dist/pypy/doc Message-ID: <20080425105452.A3B352A00E2@codespeak.net> Author: arigo Date: Fri Apr 25 12:54:51 2008 New Revision: 54128 Modified: pypy/dist/pypy/doc/faq.txt Log: I think that a link to D05.1 from here makes sense. Modified: pypy/dist/pypy/doc/faq.txt ============================================================================== --- pypy/dist/pypy/doc/faq.txt (original) +++ pypy/dist/pypy/doc/faq.txt Fri Apr 25 12:54:51 2008 @@ -242,10 +242,17 @@ interpreter. The resulting JIT works for the full Python language in a way that doesn't need type inference at all. +For more motivation and details about our approach see also [D05.1]_, +section 3. + .. [BRETT] Brett Cannon, Localized Type Inference of Atomic Types in Python, http://www.ocf.berkeley.edu/~bac/thesis.pdf +.. [D05.1] Compiling Dynamic Language Implementations, + Report from the PyPy project to the E.U., + http://codespeak.net/svn/pypy/extradoc/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf + ------------------------------ What is this RPython language? ------------------------------ From arigo at codespeak.net Fri Apr 25 14:32:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 25 Apr 2008 14:32:57 +0200 (CEST) Subject: [pypy-svn] r54130 - pypy/dist/pypy/doc/config Message-ID: <20080425123257.2867116A088@codespeak.net> Author: arigo Date: Fri Apr 25 14:32:56 2008 New Revision: 54130 Added: pypy/dist/pypy/doc/config/objspace.std.optimized_comparison_op.txt (contents, props changed) Log: Add missing file. Added: pypy/dist/pypy/doc/config/objspace.std.optimized_comparison_op.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/objspace.std.optimized_comparison_op.txt Fri Apr 25 14:32:56 2008 @@ -0,0 +1 @@ +Optimize the comparison of two integers a bit. From cfbolz at codespeak.net Fri Apr 25 14:38:50 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 25 Apr 2008 14:38:50 +0200 (CEST) Subject: [pypy-svn] r54131 - pypy/dist/pypy/translator/goal Message-ID: <20080425123850.E985E16A088@codespeak.net> Author: cfbolz Date: Fri Apr 25 14:38:47 2008 New Revision: 54131 Removed: pypy/dist/pypy/translator/goal/targetfibsmalltalk.py Log: kill this target, it was unmaintained and doesn't work From arigo at codespeak.net Fri Apr 25 15:24:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 25 Apr 2008 15:24:08 +0200 (CEST) Subject: [pypy-svn] r54133 - pypy/branch/gc-improvements/pypy/rpython/memory/gc Message-ID: <20080425132408.52F5C39B5BA@codespeak.net> Author: arigo Date: Fri Apr 25 15:24:07 2008 New Revision: 54133 Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py Log: This seems to be a small improvement (wyvern; tried pystone, richards, and some microbenches) Modified: pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-improvements/pypy/rpython/memory/gc/hybrid.py Fri Apr 25 15:24:07 2008 @@ -21,8 +21,10 @@ # the following values override the default arguments of __init__ when # translating to a real backend. TRANSLATION_PARAMS = GenerationGC.TRANSLATION_PARAMS.copy() - TRANSLATION_PARAMS['large_object'] = 1024 # XXX adjust - TRANSLATION_PARAMS['large_object_gcptrs'] = 8192 # XXX adjust + TRANSLATION_PARAMS['large_object'] = 6*1024 # XXX adjust + TRANSLATION_PARAMS['large_object_gcptrs'] = 31*1024 # XXX adjust + TRANSLATION_PARAMS['min_nursery_size'] = 128*1024 + # condition: large_object <= large_object_gcptrs < min_nursery_size/4 def __init__(self, *args, **kwds): large_object = kwds.pop('large_object', 24) From cami at codespeak.net Sun Apr 27 12:42:23 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 27 Apr 2008 12:42:23 +0200 (CEST) Subject: [pypy-svn] r54162 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080427104223.9A6EC2A00E0@codespeak.net> Author: cami Date: Sun Apr 27 12:42:21 2008 New Revision: 54162 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Log: added driverclasses to gameboy startes soudn cleanup Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sun Apr 27 12:42:21 2008 @@ -5,49 +5,61 @@ """ from pypy.lang.gameboy import constants +from pyp.lang.gameboy.cpu import * +from pyp.lang.gameboy.cartridge import * +from pyp.lang.gameboy.joypad import * +from pyp.lang.gameboy.ram import * +from pyp.lang.gameboy.serial import * +from pyp.lang.gameboy.sound import * +from pyp.lang.gameboy.video import * +from pyp.lang.gameboy.cartridge import * + class GameBoy(object): - def __init__(self, videoDriver, soundDriver, joypadDriver, storeDriver, clockDriver): + def __init__(self): + sel.createDriver() + self.createGamboyPieces() + + def createDrivers(self): + self.createDrivers() + self.clock = Clock() + self.videoDriver = VideoDriver() + self.soundDriver = SoundDriver() + self.joypadDriver = JoypadDriver() + + def createGameboyPieces(self): self.ram = RAM() - self.cartridge = Cartridge(storeDriver, clockDriver) + self.cartridge = Cartridge(storeDriver, self.clock) self.interrupt = Interrupt() self.cpu = CPU(self.interrupt, self) self.serial = Serial(self.interrupt) self.timer = Timer(self.interrupt) - self.joypad = Joypad(joypadDriver, self.interrupt) - self.video = Video(videoDriver, self.interrupt, self) - self.sound = Sound(soundDriver) - + self.joypad = Joypad(self.joypadDriver, self.interrupt) + self.video = Video(self.videoDriver, self.interrupt, self) + self.sound = Sound(self.soundDriver) def getCartridge(self): return self.cartridge - def getFrameSkip(self): return self.video.getFrameSkip() - def setFrameSkip(self, frameSkip): self.video.setFrameSkip(frameSkip) - def load(self, cartridgeName): self.cartridge.load(cartridgeName) - def save(self, cartridgeName): self.cartridge.save(cartridgeName) - def start(self): self.sound.start() - def stop(self): self.sound.stop() - def reset(self): self.ram.reset() self.cartridge.reset() @@ -61,26 +73,21 @@ self.cpu.setROM(self.cartridge.getROM()) self.drawLogo() - def cycles(self): return min( self.video.cycles(), self.serial.cycles(), self.timer.cycles(), self.sound.cycles(), self.joypad.cycles()) - def emulate(self, ticks): while (ticks > 0): count = self.cycles() - self.cpu.emulate(count) self.serial.emulate(count) self.timer.emulate(count) self.video.emulate(count) self.sound.emulate(count) self.joypad.emulate(count) - ticks -= count - def write(self, address, data): self.getreceiver(address).write(address, data) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sun Apr 27 12:42:21 2008 @@ -51,6 +51,8 @@ self.interrupt.raiseInterrupt(constants.JOYPAD) +# ------------------------------------------------------------------------------ + class JoypadDriver(object): """ @@ -158,7 +160,8 @@ self.b.toggleButton(pressed) self.raised = True - + +# ------------------------------------------------------------------------------ class Button(object): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sun Apr 27 12:42:21 2008 @@ -9,28 +9,56 @@ class Channel(object): # Audio Channel 1 int - nr10=0 - nr11=0 - nr12=0 - nr13=0 - nr14=0 - audio1Index=0 - audio1Length=0 - audio1Frequency=0 + nr0 = 0 + nr1 = 0 + nr2 = 0 + nr3 = 0 + nr4 = 0 + audioIndex = 0 + audioLength = 0 + audioFrequency = 0 def __init__(self): pass + def reset(self): + self.audioIndex = 0 + + +# ------------------------------------------------------------------------------ + + class SquareWaveGenerator(Channel): pass + + +# ------------------------------------------------------------------------------ + class VoluntaryWaveGenerator(Channel): pass + +# ------------------------------------------------------------------------------ + + class NoiseGenerator(Channel): pass + +# ------------------------------------------------------------------------------ + +class Sound(object): + + def __init__(self, soundDriver): + self.soundDriver = soundDriver + self.createAudioChannels() + def createAudioChannels(self): + self.channel1 = SquareWaveGenerator(self.sampleRate) + self.channel2 = SquareWaveGenerator(self.sampleRate) + self.channel3 = VoluntaryWaveGenerator(self.sampleRate) + self.channel4 = NoiseGenerator(self.sampleRate) class Sound(object): From cami at codespeak.net Sun Apr 27 13:39:02 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 27 Apr 2008 13:39:02 +0200 (CEST) Subject: [pypy-svn] r54163 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080427113902.57DE016852E@codespeak.net> Author: cami Date: Sun Apr 27 13:38:58 2008 New Revision: 54163 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Log: restructuring sound by splitting up into different channels Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sun Apr 27 13:38:58 2008 @@ -19,122 +19,524 @@ audioFrequency = 0 def __init__(self): - pass - + self.nr0 = 0 + self.nr1 = 0 + self.nr2 = 0 + self.nr3 = 0 + self.nr4 = 0 + self.audioIndex = 0 + self.audioLength = 0 + self.audioFrequency = 0 + def reset(self): self.audioIndex = 0 # ------------------------------------------------------------------------------ - -class SquareWaveGenerator(Channel): - pass - - -# ------------------------------------------------------------------------------ - +#SquareWaveGenerator +class Channel1(Channel): + # Audio Channel 1 int + audioSweep=0 + audioLength=0 + audioEnvelope=0 + audioFrequency=0 + audioPlayback=0 + audio1Index=0 + audio1Length=0 + audio1Volume=0 + audio1EnvelopeLength=0 + audio1SweepLength=0 + audio1Frequency=0 -class VoluntaryWaveGenerator(Channel): - pass + # Audio Channel 1 + def getAudioSweep(self): + return self.audioSweep + def getAudioLength(self): + return self.audioLength -# ------------------------------------------------------------------------------ + def getAudioEnvelope(self): + return self.audioEnvelope + def getAudioFrequency(self): + return self.audioFrequency -class NoiseGenerator(Channel): - pass + def getAudioPlayback(self): + return self.audioPlayback + def setAudioSweep(self, data): + self.audioSweep = data + self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) -# ------------------------------------------------------------------------------ + def setAudioLength(self, data): + self.audioLength = data + self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) -class Sound(object): - - def __init__(self, soundDriver): - self.soundDriver = soundDriver - self.createAudioChannels() - - def createAudioChannels(self): - self.channel1 = SquareWaveGenerator(self.sampleRate) - self.channel2 = SquareWaveGenerator(self.sampleRate) - self.channel3 = VoluntaryWaveGenerator(self.sampleRate) - self.channel4 = NoiseGenerator(self.sampleRate) - -class Sound(object): + def setAudioEnvelope(self, data): + self.audioEnvelope = data + if ((self.audioPlayback & 0x40) != 0): + return + if ((self.audioEnvelope >> 4) == 0): + self.audio1Volume = 0 + elif (self.audio1EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): + self.audio1Volume = (self.audio1Volume + 1) & 0x0F + else: + self.audio1Volume = (self.audio1Volume + 2) & 0x0F - # Audio Channel 1 int - nr10=0 - nr11=0 - nr12=0 - nr13=0 - nr14=0 - audio1Index=0 - audio1Length=0 - audio1Volume=0 - audio1EnvelopeLength=0 - audio1SweepLength=0 - audio1Frequency=0 + def setAudioFrequency(self, data): + self.audioFrequency = data + self.audio1Frequency = self.frequencyTable[self.audioFrequency + ((self.audioPlayback & 0x07) << 8)] + + def setAudioPlayback(self, data): + self.audioPlayback = data + self.audio1Frequency = self.frequencyTable[self.audioFrequency + + ((self.audioPlayback & 0x07) << 8)] + if ((self.audioPlayback & 0x80) != 0): + self.outputEnable |= 0x01 + if ((self.audioPlayback & 0x40) != 0 and self.audio1Length == 0): + self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audio1Volume = self.audioEnvelope >> 4 + self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + def updateAudio(self): + if (self.audioPlayback & 0x40) != 0 and self.audio1Length > 0: + self.audio1Length-=1 + if self.audio1Length <= 0: + self.outputEnable &= ~0x01 + if self.audio1EnvelopeLength > 0: + self.audio1EnvelopeLength-=1 + if (self.audio1EnvelopeLength <= 0): + if ((self.audioEnvelope & 0x08) != 0): + if (self.audio1Volume < 15): + self.audio1Volume+=1 + elif (self.audio1Volume > 0): + self.audio1Volume-=1 + self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + if (self.audio1SweepLength > 0): + self.audio1SweepLength-=1 + if (self.audio1SweepLength <= 0): + sweepSteps = (self.audioSweep & 0x07) + if (sweepSteps != 0): + frequency = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency + if ((self.audioSweep & 0x08) != 0): + frequency -= frequency >> sweepSteps + else: + frequency += frequency >> sweepSteps + if (frequency < 2048): + self.audio1Frequency = self.frequencyTable[frequency] + self.audioFrequency = frequency & 0xFF + self.audioPlayback = (self.audioPlayback & 0xF8) + ((frequency >> 8) & 0x07) + else: + self.audio1Frequency = 0 + self.outputEnable &= ~0x01 + + self.audio1SweepLength += (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) - # Audio Channel 2 int - nr21=0 - nr22=0 - nr23=0 - nr24=0 + def mixAudio(self, buffer, length): + wavePattern = 0x18 + if (self.audioLength & 0xC0) == 0x00: + wavePattern = 0x04 + elif (self.audioLength & 0xC0) == 0x40: + wavePattern = 0x08 + elif (self.audioLength & 0xC0) == 0x80: + wavePattern = 0x10 + wavePattern << 22 + for index in range(0, length, 3): + self.audio1Index += self.audio1Frequency + if ((self.audio1Index & (0x1F << 22)) >= wavePattern): + if ((self.outputTerminal & 0x10) != 0): + buffer[index + 0] -= self.audio1Volume + if ((self.outputTerminal & 0x01) != 0): + buffer[index + 1] -= self.audio1Volume + else: + if ((self.outputTerminal & 0x10) != 0): + buffer[index + 0] += self.audio1Volume + if ((self.outputTerminal & 0x01) != 0): + buffer[index + 1] += self.audio1Volume + + +#SquareWaveGenerator +class Channel2(Channel): + # Audio Channel 2 int + audioLength=0 + audioEnvelope=0 + audioFrequency=0 + audioPlayback=0 audio2Index=0 audio2Length=0 audio2Volume=0 audio2EnvelopeLength=0 audio2Frequency=0 + + + # Audio Channel 2 + def getAudioLength(self): + return self.audioLength + + def getAudioEnvelope(self): + return self.audioEnvelope + + def getAudioFrequency(self): + return self.audioFrequency + + def getAudioPlayback(self): + return self.audioPlayback + + def setAudioLength(self, data): + self.audioLength = data + self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + + def setAudioEnvelope(self, data): + self.audioEnvelope = data + if ((self.audioPlayback & 0x40) == 0): + if ((self.audioEnvelope >> 4) == 0): + self.audio2Volume = 0 + elif (self.audio2EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): + self.audio2Volume = (self.audio2Volume + 1) & 0x0F + else: + self.audio2Volume = (self.audio2Volume + 2) & 0x0F + + def setAudioFrequency(self, data): + self.audioFrequency = data + self.audio2Frequency = self.frequencyTable[self.audioFrequency\ + + ((self.audioPlayback & 0x07) << 8)] + + def setAudioPlayback(self, data): + self.audioPlayback = data + self.audio2Frequency = self.frequencyTable[self.audioFrequency\ + + ((self.audioPlayback & 0x07) << 8)] + if ((self.audioPlayback & 0x80) != 0): + self.outputEnable |= 0x02 + if ((self.audioPlayback & 0x40) != 0 and self.audio2Length == 0): + self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio2Volume = self.audioEnvelope >> 4 + self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + + def updateAudio(self): + if ((self.audioPlayback & 0x40) != 0 and self.audio2Length > 0): + self.audio2Length-=1 + if (self.audio2Length <= 0): + self.outputEnable &= ~0x02 + if (self.audio2EnvelopeLength > 0): + self.audio2EnvelopeLength-=1 + + if (self.audio2EnvelopeLength <= 0): + if ((self.audioEnvelope & 0x08) != 0): + if (self.audio2Volume < 15): + self.audio2Volume+=1 + elif (self.audio2Volume > 0): + self.audio2Volume-=1 + self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + + def mixAudio(self, buffer, length): + wavePattern = 0x18 + if (self.audioLength & 0xC0) == 0x00: + wavePattern = 0x04 + elif (self.audioLength & 0xC0) == 0x40: + wavePattern = 0x08 + elif (self.audioLength & 0xC0) == 0x80: + wavePattern = 0x10 + wavePattern << 22 + for index in range(0, length): + self.audio2Index += self.audio2Frequency + if ((self.audio2Index & (0x1F << 22)) >= wavePattern): + if ((self.outputTerminal & 0x20) != 0): + buffer[index + 0] -= self.audio2Volume + if ((self.outputTerminal & 0x02) != 0): + buffer[index + 1] -= self.audio2Volume + else: + if ((self.outputTerminal & 0x20) != 0): + buffer[index + 0] += self.audio2Volume + if ((self.outputTerminal & 0x02) != 0): + buffer[index + 1] += self.audio2Volume - # Audio Channel 3 int - nr30=0 - nr31=0 - nr32=0 - nr33=0 - nr34=0 + + + +#SquareWaveGenerator +class Channel3(Channel): + # Audio Channel 3 int + audioEnable=0 + audioLength=0 + audioLevel=0 + audioFrequency=0 + audioPlayback=0 audio3Index=0 audio3Length=0 audio3Frequency=0 audio3WavePattern = []# = new byte[16] + + + # Audio Channel 3 + def getAudioEnable(self): + return self.audioEnable + + def getAudioLength(self): + return self.audioLength + + def getAudioLevel(self): + return self.audioLevel + + #FIXME strange number here + def getAudio4Frequency(self): + return self.audioFrequency + + def getAudioPlayback(self): + return self.audioPlayback + + def setAudioEnable(self, data): + self.audioEnable = data & 0x80 + if ((self.audioEnable & 0x80) == 0): + self.outputEnable &= ~0x04 + + def setAudioLength(self, data): + self.audioLength = data + self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.audioLength) + + def setAudioLevel(self, data): + self.audioLevel = data + + def setAudioFrequency(self, data): + self.audioFrequency = data + self.audio3Frequency = self.frequencyTable[((self.audioPlayback & 0x07) << 8) + self.audioFrequency] >> 1 + + def setAudioPlayback(self, data): + self.audioPlayback = data + self.audio3Frequency = self.frequencyTable[((self.audioPlayback & 0x07) << 8) + self.audioFrequency] >> 1 + if ((self.audioPlayback & 0x80) != 0 and (self.audioEnable & 0x80) != 0): + self.outputEnable |= 0x04 + if ((self.audioPlayback & 0x40) != 0 and self.audio3Length == 0): + self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.audioLength) + + def setAudioWavePattern(self, address, data): + self.audio3WavePattern[address & 0x0F] = data + + def getAudioWavePattern(self, address): + return self.audio3WavePattern[address & 0x0F] & 0xFF - # Audio Channel 4 int - nr41=0 - nr42=0 - nr43=0 - nr44=0 + def updateAudio(self): + if ((self.audioPlayback & 0x40) != 0 and self.audio3Length > 0): + self.audio3Length-=1 + if (self.audio3Length <= 0): + self.outputEnable &= ~0x04 + + def mixAudio(self, buffer, length): + wavePattern = 2 + if (self.audioLevel & 0x60) == 0x00: + wavePattern = 8 + elif (self.audioLevel & 0x60) == 0x40: + wavePattern = 0 + elif (self.audioLevel & 0x60) == 0x80: + wavePattern = 1 + + for index in range(0, length, 2): + self.audio3Index += self.audio3Frequency + sample = self.audio3WavePattern[(self.audio3Index >> 23) & 0x0F] + if ((self.audio3Index & (1 << 22)) != 0): + sample = (sample >> 0) & 0x0F + else: + sample = (sample >> 4) & 0x0F + + sample = ((sample - 8) << 1) >> level + + if ((self.outputTerminal & 0x40) != 0): + buffer[index + 0] += sample + if ((self.outputTerminal & 0x04) != 0): + buffer[index + 1] += sample + + + + +class NoiseGenerator(Channel): + # Audio Channel 4 int + audioLength=0 + audioEnvelope=0 + audioPolynomial=0 + audioPlayback=0 audio4Index=0 audio4Length=0 audio4Volume=0 audio4EnvelopeLength=0 audio4Frequency=0 + + # Frequency Table + frequencyTable = [0]*2048#= new int[2048] + noiseFreqRatioTable = [0]*8 #= new int[8] + + # Noise Tables + noiseStep7Table = [0]*4 #= new int[128 / 32] + noiseStep15Table = [0]*1024 #= new int[32768 / 32] + + #Frequency Table Generation + def generateFrequencyTables(self): + sampleRate = self.driver.getSampleRate() + # frequency = (4194304 / 32) / (2048 - period) Hz + for period in range(0, 2048): + skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << (22 - 8)) / (2048 - period) + if (skip >= (32 << 22)): + self.frequencyTable[period] = 0 + else: + self.frequencyTable[period] = skip + # Polynomial Noise Frequency Ratios + # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 * + # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz * + # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7 + for ratio in range(0, 8): + divider = 1 + if ratio != 0: + divider = 2 * ratio + self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) * ((1 << 16) / sampleRate) + + # Noise Generation + def generateNoiseTables(self): + polynomial = 0x7F + # 7 steps + for index in range(0, 0x7F): + polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | (polynomial >> 1) + if ((index & 31) == 0): + self.noiseStep7Table[index >> 5] = 0 + self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31) + # 15 steps& + polynomial = 0x7FFF + for index in range(0, 0x7FFF): + polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1) + if ((index & 31) == 0): + self.noiseStep15Table[index >> 5] = 0 + self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31) + + # Audio Channel 4 + def getAudioLength(self): + return self.audioLength + + def getAudioEnvelope(self): + return self.audioEnvelope + + def getAudioPolynomial(self): + return self.audioPolynomial + + def getAudioPlayback(self): + return self.audioPlayback + + def setAudioLength(self, data): + self.audioLength = data + self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + + def setAudioEnvelope(self, data): + self.audioEnvelope = data + if ((self.audioPlayback & 0x40) == 0): + if ((self.audioEnvelope >> 4) == 0): + self.audio4Volume = 0 + elif (self.audio4EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): + self.audio4Volume = (self.audio4Volume + 1) & 0x0F + else: + self.audio4Volume = (self.audio4Volume + 2) & 0x0F + + def setAudioPolynomial(self, data): + self.audioPolynomial = data + if ((self.audioPolynomial >> 4) <= 12): + self.audio4Frequency = self.noiseFreqRatioTable[self.audioPolynomial & 0x07] >> ((self.audioPolynomial >> 4) + 1) + else: + self.audio4Frequency = 0 + + def setAudioPlayback(self, data): + self.audioPlayback = data + if ((self.audioPlayback & 0x80) != 0): + self.outputEnable |= 0x08 + if ((self.audioPlayback & 0x40) != 0 and self.audio4Length == 0): + self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio4Volume = self.audioEnvelope >> 4 + self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio4Index = 0 + + def updateAudio(self): + if ((self.audioPlayback & 0x40) != 0 and self.audio4Length > 0): + self.audio4Length-=1 + if (self.audio4Length <= 0): + self.outputEnable &= ~0x08 + if (self.audio4EnvelopeLength > 0): + self.audio4EnvelopeLength-=1 + if (self.audio4EnvelopeLength <= 0): + if ((self.audioEnvelope & 0x08) != 0): + if (self.audio4Volume < 15): + self.audio4Volume+=1 + elif (self.audio4Volume > 0): + self.audio4Volume-=1 + self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + + def mixAudio(self, buffer, length): + for index in range(0, length, 2): + self.audio4Index += self.audio4Frequency + polynomial + if ((self.audioPolynomial & 0x08) != 0): + # 7 steps + self.audio4Index &= 0x7FFFFF + polynomial = self.noiseStep7Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) + else: + # 15 steps + self.audio4Index &= 0x7FFFFFFF + polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) + if ((polynomial & 1) != 0): + if ((self.outputTerminal & 0x80) != 0): + buffer[index + 0] -= self.audio4Volume + if ((self.outputTerminal & 0x08) != 0): + buffer[index + 1] -= self.audio4Volume + else: + if ((self.outputTerminal & 0x80) != 0): + buffer[index + 0] += self.audio4Volume + if ((self.outputTerminal & 0x08) != 0): + buffer[index + 1] += self.audio4Volume + + + + +# ------------------------------------------------------------------------------ + + +class VoluntaryWaveGenerator(Channel): + + def __init__(self): + Channel.__init__(self) + self.createWavePatterns() + + def createWavePatterns(self): + self.audioWavePattern = [0]*16 + + +# ------------------------------------------------------------------------------ + + +class Sound(object): # Output Control int - nr50=0 - nr51=0 - nr52=0 + outputLevel=0 + outputTerminal=0 + outputEnable=0 # Sound DriverSoundDriver #driver - buffer = []# = new byte[512] + buffer = [0]*512# = new byte[512] #int #frames #cycles - # Frequency Table - frequencyTable = []#= new int[2048] - noiseFreqRatioTable = [] #= new int[8] - - # Noise Tables - noiseStep7Table = [] #= new int[128 / 32] - noiseStep15Table = [] #= new int[32768 / 32] def __init__(self, soundDriver): self.driver = soundDriver + self.createAudioChannels() + self.generateFrequencyTables() self.generateNoiseTables() self.reset() + + def createAudioChannels(self): + self.channel1 = SquareWaveGenerator(self.sampleRate) + self.channel2 = SquareWaveGenerator(self.sampleRate) + self.channel3 = VoluntaryWaveGenerator(self.sampleRate) + self.channel4 = NoiseGenerator(self.sampleRate) + def reset(self): self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK @@ -162,9 +564,9 @@ self.write(constants.NR43, 0x00) self.write(constants.NR44, 0xBF) - self.write(constants.NR50, 0x00) # 0x77 - self.write(constants.NR51, 0xF0) - self.write(constants.NR52, 0xFF) # 0xF0 + self.write(constants.outputLevel, 0x00) # 0x77 + self.write(constants.outputTerminal, 0xF0) + self.write(constants.outputEnable, 0xFF) # 0xF0 for address in range(0xFF30, 0xFF3F): write = 0xFF @@ -199,535 +601,156 @@ def read(self, address): if address==constants.NR10: - return self.getAudio1Sweep() + return self.channel1.getAudioSweep() elif address == constants.NR11: - return self.getAudio1Length() + return self.channel1.getAudioLength() elif address == constants.NR12: - return self.getAudio1Envelope() + return self.channel1.getAudioEnvelope() elif address == constants.NR13: - return self.getAudio1Frequency() + return self.channel1.getAudioFrequency() elif address == constants.NR14: - return self.getAudio1Playback() + return self.channel1.getAudioPlayback() elif address == constants.NR21: - return self.getAudio2Length() + return self.channel2.getAudioLength() elif address == constants.NR22: - return self.getAudio2Envelope() + return self.channel2.getAudioEnvelope() elif address==constants.NR23: - return self.getAudio2Frequency() + return self.channel2.getAudioFrequency() elif address==constants.NR24: - return self.getAudio2Playback() + return self.channel2.getAudioPlayback() elif address==constants.NR30: - return self.getAudio3Enable() + return self.channel3.getAudioEnable() elif address==constants.NR31: - return self.getAudio3Length() + return self.channel3.getAudioLength() elif address==constants.NR32: - return self.getAudio3Level() + return self.channel3.getAudioLevel() elif address==constants.NR33: - return self.getAudio4Frequency() + return self.channel4.getAudioFrequency() elif address==constants.NR34: - return self.getAudio3Playback() + return self.channel3.getAudioPlayback() elif address==constants.NR41: - return self.getAudio4Length() + return self.channel4.getAudioLength() elif address==constants.NR42: - return self.getAudio4Envelope() + return self.channel4.getAudioEnvelope() elif address==constants.NR43: - return self.getAudio4Polynomial() + return self.channel4.getAudioPolynomial() elif address==constants.NR44: - return self.getAudio4Playback() + return self.channel4.getAudioPlayback() - elif address==constants.NR50: + elif address==constants.outputLevel: return self.getOutputLevel() - elif address==constants.NR51: + elif address==constants.outputTerminal: return self.getOutputTerminal() - elif address==constants.NR52: + elif address==constants.outputEnable: return self.getOutputEnable() elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): - return self.getAudio3WavePattern(address) + return self.channel3.getAudioWavePattern(address) return 0xFF def write(self, address, data): if address==constants.NR10: - self.setAudio1Sweep(data) + self.channel1.setAudioSweep(data) elif address == constants.NR11: - self.setAudio1Length(data) + self.channel1.setAudioLength(data) elif address == constants.NR12: - self.setAudio1Envelope(data) + self.channel1.setAudioEnvelope(data) elif address == constants.NR13: - self.setAudio1Frequency(data) + self.channel1.setAudi1Frequency(data) elif address == constants.NR14: - self.setAudio1Playback(data) + self.channel1.setAudioPlayback(data) elif address == constants.NR21: - self.setAudio2Length(data) + self.channel2.setAudioLength(data) elif address == constants.NR22: - self.setAudio2Envelope(data) + self.channel2.setAudioEnvelope(data) elif address == constants.NR23: - self.setAudio2Frequency(data) + self.channel2.setAudioFrequency(data) elif address == constants.NR24: - self.setAudio2Playback(data) + self.channel2.setAudioPlayback(data) elif address == constants.NR30: - self.setAudio3Enable(data) + self.channel3.setAudioEnable(data) elif address == constants.NR31: - self.setAudio3Length(data) + self.channel3.setAudioLength(data) elif address == constants.NR32: - self.setAudio3Level(data) + self.channel3.setAudioLevel(data) elif address == constants.NR33: - self.setAudio3Frequency(data) + self.channel3.setAudioFrequency(data) elif address == constants.NR34: - self.setAudio3Playback(data) + self.channel3.setAudioPlayback(data) elif address == constants.NR41: - self.setAudio4Length(data) + self.channel4.setAudioLength(data) elif address == constants.NR42: - self.setAudio4Envelope(data) + self.channel4.setAudioEnvelope(data) elif address == constants.NR43: - self.setAudio4Polynomial(data) + self.channel4.setAudioPolynomial(data) elif address == constants.NR44: - self.setAudio4Playback(data) + self.channel4.setAudioPlayback(data) - elif address == constants.NR50: + elif address == constants.outputLevel: self.setOutputLevel(data) - elif address == constants.NR51: + elif address == constants.outputTerminal: self.setOutputTerminal(data) - elif address == constants.NR52: + elif address == constants.outputEnable: self.setOutputEnable(data) elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): self.setAudio3WavePattern(address, data) def updateAudio(self): - if (self.nr52 & 0x80) == 0: + if (self.outputEnable & 0x80) == 0: return - if (self.nr52 & 0x01) != 0: - self.updateAudio1() - if (self.nr52 & 0x02) != 0: - self.updateAudio2() - if (self.nr52 & 0x04) != 0: - self.updateAudio3() - if (self.nr52 & 0x08) != 0: - self.updateAudio4() + if (self.outputEnable & 0x01) != 0: + self.channel1.updateAudio() + if (self.outputEnable & 0x02) != 0: + self.channel2.updateAudio() + if (self.outputEnable & 0x04) != 0: + self.channel3.updateAudio() + if (self.outputEnable & 0x08) != 0: + self.channel4.updateAudio() def mixAudio(self,buffer, length): buffer = [0]*length - if (self.nr52 & 0x80) == 0: - return - if (self.nr52 & 0x01) != 0: - self.mixAudio1(buffer, length) - if (self.nr52 & 0x02) != 0: - self.mixAudio2(buffer, length) - if (self.nr52 & 0x04) != 0: - self.mixAudio3(buffer, length) - if (self.nr52 & 0x08) != 0: - self.mixAudio4(buffer, length) - - # Audio Channel 1 - def getAudio1Sweep(self): - return self.nr10 - - def getAudio1Length(self): - return self.nr11 - - def getAudio1Envelope(self): - return self.nr12 - - def getAudio1Frequency(self): - return self.nr13 - - def getAudio1Playback(self): - return self.nr14 - - def setAudio1Sweep(self, data): - self.nr10 = data - self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07) - - def setAudio1Length(self, data): - self.nr11 = data - self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F)) - - def setAudio1Envelope(self, data): - self.nr12 = data - if ((self.nr14 & 0x40) != 0): + if (self.outputEnable & 0x80) == 0: return - if ((self.nr12 >> 4) == 0): - self.audio1Volume = 0 - elif (self.audio1EnvelopeLength == 0 and (self.nr12 & 0x07) == 0): - self.audio1Volume = (self.audio1Volume + 1) & 0x0F - else: - self.audio1Volume = (self.audio1Volume + 2) & 0x0F - - def setAudio1Frequency(self, data): - self.nr13 = data - self.audio1Frequency = self.frequencyTable[self.nr13 + ((self.nr14 & 0x07) << 8)] - - def setAudio1Playback(self, data): - self.nr14 = data - self.audio1Frequency = self.frequencyTable[self.nr13 - + ((self.nr14 & 0x07) << 8)] - if ((self.nr14 & 0x80) != 0): - self.nr52 |= 0x01 - if ((self.nr14 & 0x40) != 0 and self.audio1Length == 0): - self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F)) - self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07) - self.audio1Volume = self.nr12 >> 4 - self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07) - - def updateAudio1(self): - if (self.nr14 & 0x40) != 0 and self.audio1Length > 0: - self.audio1Length-=1 - if self.audio1Length <= 0: - self.nr52 &= ~0x01 - if self.audio1EnvelopeLength > 0: - self.audio1EnvelopeLength-=1 - if (self.audio1EnvelopeLength <= 0): - if ((self.nr12 & 0x08) != 0): - if (self.audio1Volume < 15): - self.audio1Volume+=1 - elif (self.audio1Volume > 0): - self.audio1Volume-=1 - self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07) - if (self.audio1SweepLength > 0): - self.audio1SweepLength-=1 - if (self.audio1SweepLength <= 0): - sweepSteps = (self.nr10 & 0x07) - if (sweepSteps != 0): - frequency = ((self.nr14 & 0x07) << 8) + self.nr13 - if ((self.nr10 & 0x08) != 0): - frequency -= frequency >> sweepSteps - else: - frequency += frequency >> sweepSteps - if (frequency < 2048): - self.audio1Frequency = self.frequencyTable[frequency] - self.nr13 = frequency & 0xFF - self.nr14 = (self.nr14 & 0xF8) + ((frequency >> 8) & 0x07) - else: - self.audio1Frequency = 0 - self.nr52 &= ~0x01 - - self.audio1SweepLength += (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07) - - def mixAudio1(self, buffer, length): - wavePattern = 0x18 - if (self.nr11 & 0xC0) == 0x00: - wavePattern = 0x04 - elif (self.nr11 & 0xC0) == 0x40: - wavePattern = 0x08 - elif (self.nr11 & 0xC0) == 0x80: - wavePattern = 0x10 - wavePattern << 22 - for index in range(0, length, 3): - self.audio1Index += self.audio1Frequency - if ((self.audio1Index & (0x1F << 22)) >= wavePattern): - if ((self.nr51 & 0x10) != 0): - buffer[index + 0] -= self.audio1Volume - if ((self.nr51 & 0x01) != 0): - buffer[index + 1] -= self.audio1Volume - else: - if ((self.nr51 & 0x10) != 0): - buffer[index + 0] += self.audio1Volume - if ((self.nr51 & 0x01) != 0): - buffer[index + 1] += self.audio1Volume - - # Audio Channel 2 - def getAudio2Length(self): - return self.nr21 - - def getAudio2Envelope(self): - return self.nr22 - - def getAudio2Frequency(self): - return self.nr23 - - def getAudio2Playback(self): - return self.nr24 - - def setAudio2Length(self, data): - self.nr21 = data - self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F)) - - def setAudio2Envelope(self, data): - self.nr22 = data - if ((self.nr24 & 0x40) == 0): - if ((self.nr22 >> 4) == 0): - self.audio2Volume = 0 - elif (self.audio2EnvelopeLength == 0 and (self.nr22 & 0x07) == 0): - self.audio2Volume = (self.audio2Volume + 1) & 0x0F - else: - self.audio2Volume = (self.audio2Volume + 2) & 0x0F - - def setAudio2Frequency(self, data): - self.nr23 = data - self.audio2Frequency = self.frequencyTable[self.nr23\ - + ((self.nr24 & 0x07) << 8)] - - def setAudio2Playback(self, data): - self.nr24 = data - self.audio2Frequency = self.frequencyTable[self.nr23\ - + ((self.nr24 & 0x07) << 8)] - if ((self.nr24 & 0x80) != 0): - self.nr52 |= 0x02 - if ((self.nr24 & 0x40) != 0 and self.audio2Length == 0): - self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F)) - self.audio2Volume = self.nr22 >> 4 - self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07) - - def updateAudio2(self): - if ((self.nr24 & 0x40) != 0 and self.audio2Length > 0): - self.audio2Length-=1 - if (self.audio2Length <= 0): - self.nr52 &= ~0x02 - if (self.audio2EnvelopeLength > 0): - self.audio2EnvelopeLength-=1 - - if (self.audio2EnvelopeLength <= 0): - if ((self.nr22 & 0x08) != 0): - if (self.audio2Volume < 15): - self.audio2Volume+=1 - elif (self.audio2Volume > 0): - self.audio2Volume-=1 - self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07) - - def mixAudio2(self, buffer, length): - wavePattern = 0x18 - if (self.nr21 & 0xC0) == 0x00: - wavePattern = 0x04 - elif (self.nr21 & 0xC0) == 0x40: - wavePattern = 0x08 - elif (self.nr21 & 0xC0) == 0x80: - wavePattern = 0x10 - wavePattern << 22 - for index in range(0, length): - self.audio2Index += self.audio2Frequency - if ((self.audio2Index & (0x1F << 22)) >= wavePattern): - if ((self.nr51 & 0x20) != 0): - buffer[index + 0] -= self.audio2Volume - if ((self.nr51 & 0x02) != 0): - buffer[index + 1] -= self.audio2Volume - else: - if ((self.nr51 & 0x20) != 0): - buffer[index + 0] += self.audio2Volume - if ((self.nr51 & 0x02) != 0): - buffer[index + 1] += self.audio2Volume - - # Audio Channel 3 - def getAudio3Enable(self): - return self.nr30 - - def getAudio3Length(self): - return self.nr31 - - def getAudio3Level(self): - return self.nr32 - - def getAudio4Frequency(self): - return self.nr33 - - def getAudio3Playback(self): - return self.nr34 + if (self.outputEnable & 0x01) != 0: + self.channel1.mixAudio(buffer, length) + if (self.outputEnable & 0x02) != 0: + self.channel2.mixAudio(buffer, length) + if (self.outputEnable & 0x04) != 0: + self.channel3.mixAudio(buffer, length) + if (self.outputEnable & 0x08) != 0: + self.channel4.mixAudio(buffer, length) - def setAudio3Enable(self, data): - self.nr30 = data & 0x80 - if ((self.nr30 & 0x80) == 0): - self.nr52 &= ~0x04 - - def setAudio3Length(self, data): - self.nr31 = data - self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31) - - def setAudio3Level(self, data): - self.nr32 = data - - def setAudio3Frequency(self, data): - self.nr33 = data - self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1 - - def setAudio3Playback(self, data): - self.nr34 = data - self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1 - if ((self.nr34 & 0x80) != 0 and (self.nr30 & 0x80) != 0): - self.nr52 |= 0x04 - if ((self.nr34 & 0x40) != 0 and self.audio3Length == 0): - self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31) - - def setAudio3WavePattern(self, address, data): - self.audio3WavePattern[address & 0x0F] = data - - def getAudio3WavePattern(self, address): - return self.audio3WavePattern[address & 0x0F] & 0xFF - - def updateAudio3(self): - if ((self.nr34 & 0x40) != 0 and self.audio3Length > 0): - self.audio3Length-=1 - if (self.audio3Length <= 0): - self.nr52 &= ~0x04 - - def mixAudio3(self, buffer, length): - wavePattern = 2 - if (self.nr32 & 0x60) == 0x00: - wavePattern = 8 - elif (self.nr32 & 0x60) == 0x40: - wavePattern = 0 - elif (self.nr32 & 0x60) == 0x80: - wavePattern = 1 - - for index in range(0, length, 2): - self.audio3Index += self.audio3Frequency - sample = self.audio3WavePattern[(self.audio3Index >> 23) & 0x0F] - if ((self.audio3Index & (1 << 22)) != 0): - sample = (sample >> 0) & 0x0F - else: - sample = (sample >> 4) & 0x0F - - sample = ((sample - 8) << 1) >> level - - if ((self.nr51 & 0x40) != 0): - buffer[index + 0] += sample - if ((self.nr51 & 0x04) != 0): - buffer[index + 1] += sample - - # Audio Channel 4 - def getAudio4Length(self): - return self.nr41 - - def getAudio4Envelope(self): - return self.nr42 - - def getAudio4Polynomial(self): - return self.nr43 - - def getAudio4Playback(self): - return self.nr44 - - def setAudio4Length(self, data): - self.nr41 = data - self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F)) - - def setAudio4Envelope(self, data): - self.nr42 = data - if ((self.nr44 & 0x40) == 0): - if ((self.nr42 >> 4) == 0): - self.audio4Volume = 0 - elif (self.audio4EnvelopeLength == 0 and (self.nr42 & 0x07) == 0): - self.audio4Volume = (self.audio4Volume + 1) & 0x0F - else: - self.audio4Volume = (self.audio4Volume + 2) & 0x0F - - def setAudio4Polynomial(self, data): - self.nr43 = data - if ((self.nr43 >> 4) <= 12): - self.audio4Frequency = self.noiseFreqRatioTable[self.nr43 & 0x07] >> ((self.nr43 >> 4) + 1) - else: - self.audio4Frequency = 0 - - def setAudio4Playback(self, data): - self.nr44 = data - if ((self.nr44 & 0x80) != 0): - self.nr52 |= 0x08 - if ((self.nr44 & 0x40) != 0 and self.audio4Length == 0): - self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F)) - self.audio4Volume = self.nr42 >> 4 - self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07) - self.audio4Index = 0 - - def updateAudio4(self): - if ((self.nr44 & 0x40) != 0 and self.audio4Length > 0): - self.audio4Length-=1 - if (self.audio4Length <= 0): - self.nr52 &= ~0x08 - if (self.audio4EnvelopeLength > 0): - self.audio4EnvelopeLength-=1 - if (self.audio4EnvelopeLength <= 0): - if ((self.nr42 & 0x08) != 0): - if (self.audio4Volume < 15): - self.audio4Volume+=1 - elif (self.audio4Volume > 0): - self.audio4Volume-=1 - self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07) - def mixAudio4(self, buffer, length): - for index in range(0, length, 2): - self.audio4Index += self.audio4Frequency - polynomial - if ((self.nr43 & 0x08) != 0): - # 7 steps - self.audio4Index &= 0x7FFFFF - polynomial = self.noiseStep7Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) - else: - # 15 steps - self.audio4Index &= 0x7FFFFFFF - polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) - if ((polynomial & 1) != 0): - if ((self.nr51 & 0x80) != 0): - buffer[index + 0] -= self.audio4Volume - if ((self.nr51 & 0x08) != 0): - buffer[index + 1] -= self.audio4Volume - else: - if ((self.nr51 & 0x80) != 0): - buffer[index + 0] += self.audio4Volume - if ((self.nr51 & 0x08) != 0): - buffer[index + 1] += self.audio4Volume - # Output Control def getOutputLevel(self): - return self.nr50 + return self.outputLevel def getOutputTerminal(self): - return self.nr51 + return self.outputTerminal def getOutputEnable(self): - return self.nr52 + return self.outputEnable def setOutputLevel(self, data): - self.nr50 = data + self.outputLevel = data def setOutputTerminal(self, data): - self.nr51 = data + self.outputTerminal = data def setOutputEnable(self, data): - self.nr52 = (self.nr52 & 0x7F) | (data & 0x80) - if ((self.nr52 & 0x80) == 0x00): - self.nr52 &= 0xF0 + self.outputEnable = (self.outputEnable & 0x7F) | (data & 0x80) + if ((self.outputEnable & 0x80) == 0x00): + self.outputEnable &= 0xF0 - # Frequency Table Generation - def generateFrequencyTables(self): - sampleRate = self.driver.getSampleRate() - # frequency = (4194304 / 32) / (2048 - period) Hz - for period in range(0, 2048): - skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << (22 - 8)) / (2048 - period) - if (skip >= (32 << 22)): - self.frequencyTable[period] = 0 - else: - self.frequencyTable[period] = skip - # Polynomial Noise Frequency Ratios - # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 * - # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz * - # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7 - for ratio in range(0, 8): - divider = 1 - if ratio != 0: - divider = 2 * ratio - self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) * ((1 << 16) / sampleRate) - # Noise Generation - def generateNoiseTables(self): - polynomial = 0x7F - # 7 steps - for index in range(0, 0x7F): - polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | (polynomial >> 1) - if ((index & 31) == 0): - self.noiseStep7Table[index >> 5] = 0 - self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31) - # 15 steps& - polynomial = 0x7FFF - for index in range(0, 0x7FFF): - polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1) - if ((index & 31) == 0): - self.noiseStep15Table[index >> 5] = 0 - self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31) + # SOUND DRIVER ----------------------------------------------------------------- From cami at codespeak.net Sun Apr 27 14:20:45 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 27 Apr 2008 14:20:45 +0200 (CEST) Subject: [pypy-svn] r54164 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080427122045.0DF6516A079@codespeak.net> Author: cami Date: Sun Apr 27 14:20:44 2008 New Revision: 54164 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Log: more restructuring Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sun Apr 27 14:20:44 2008 @@ -510,20 +510,12 @@ class Sound(object): - # Output Control int - outputLevel=0 - outputTerminal=0 - outputEnable=0 - - # Sound DriverSoundDriver - #driver - buffer = [0]*512# = new byte[512] - #int - #frames - #cycles - - def __init__(self, soundDriver): + self.buffer = [0]*512 + self.outputLevel=0 + self.outputTerminal=0 + self.outputEnable=0 + self.driver = soundDriver self.createAudioChannels() @@ -541,7 +533,16 @@ def reset(self): self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK self.frames = 0 - self.audio1Index = self.audio2Index = self.audio3Index = self.audio4Index = 0 + self.channel1.reset() + self.channel2.reset() + self.channel3.reset() + self.channel4.reset() + + self.channel1.audioIndex = 0 + self.channel2.audioIndex = 0 + self.channel3.audioIndex = 0 + self.channel4.audioIndex = 0 + self.write(constants.NR10, 0x80) self.write(constants.NR11, 0x3F) # 0xBF self.write(constants.NR12, 0x00) # 0xF3 @@ -700,7 +701,7 @@ self.setOutputEnable(data) elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): - self.setAudio3WavePattern(address, data) + self.channel3.setAudioWavePattern(address, data) def updateAudio(self): if (self.outputEnable & 0x80) == 0: @@ -714,8 +715,7 @@ if (self.outputEnable & 0x08) != 0: self.channel4.updateAudio() - def mixAudio(self,buffer, length): - buffer = [0]*length + def mixAudio(self, buffer, length): if (self.outputEnable & 0x80) == 0: return if (self.outputEnable & 0x01) != 0: @@ -727,7 +727,6 @@ if (self.outputEnable & 0x08) != 0: self.channel4.mixAudio(buffer, length) - # Output Control def getOutputLevel(self): return self.outputLevel From fijal at codespeak.net Mon Apr 28 12:18:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 28 Apr 2008 12:18:22 +0200 (CEST) Subject: [pypy-svn] r54171 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080428101822.ECC5D168069@codespeak.net> Author: fijal Date: Mon Apr 28 12:18:20 2008 New Revision: 54171 Modified: pypy/dist/pypy/objspace/std/floatobject.py pypy/dist/pypy/objspace/std/intobject.py pypy/dist/pypy/objspace/std/test/test_floatobject.py Log: * Shorten a bit comparison function implementation (by metaprogramming) * Implement comparisons between floats and ints, both way, not sure what to do with int -> float comparison where we loose precision. This speeds up pybench quite a bit (there is a benchmark for that). (from 3.5x times slower than cpython on int/float comparison to roughly equal) Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Mon Apr 28 12:18:20 2008 @@ -87,35 +87,47 @@ s = formatd("%.12g", x) return space.wrap(should_not_look_like_an_int(s)) -def lt__Float_Float(space, w_float1, w_float2): - i = w_float1.floatval - j = w_float2.floatval - return space.newbool( i < j ) - -def le__Float_Float(space, w_float1, w_float2): - i = w_float1.floatval - j = w_float2.floatval - return space.newbool( i <= j ) - -def eq__Float_Float(space, w_float1, w_float2): - i = w_float1.floatval - j = w_float2.floatval - return space.newbool( i == j ) - -def ne__Float_Float(space, w_float1, w_float2): - i = w_float1.floatval - j = w_float2.floatval - return space.newbool( i != j ) - -def gt__Float_Float(space, w_float1, w_float2): - i = w_float1.floatval - j = w_float2.floatval - return space.newbool( i > j ) - -def ge__Float_Float(space, w_float1, w_float2): - i = w_float1.floatval - j = w_float2.floatval - return space.newbool( i >= j ) + +def declare_new_float_comparison(opname): + import operator + from pypy.tool.sourcetools import func_with_new_name + op = getattr(operator, opname) + def f(space, w_int1, w_int2): + i = w_int1.floatval + j = w_int2.floatval + return space.newbool(op(i, j)) + name = opname + "__Float_Float" + return func_with_new_name(f, name), name + +def declare_new_int_float_comparison(opname): + import operator + from pypy.tool.sourcetools import func_with_new_name + op = getattr(operator, opname) + def f(space, w_int1, w_float2): + i = w_int1.intval + j = w_float2.floatval + return space.newbool(op(float(i), j)) + name = opname + "__Int_Float" + return func_with_new_name(f, name), name + +def declare_new_float_int_comparison(opname): + import operator + from pypy.tool.sourcetools import func_with_new_name + op = getattr(operator, opname) + def f(space, w_float1, w_int2): + i = w_float1.floatval + j = w_int2.intval + return space.newbool(op(i, float(j))) + name = opname + "__Float_Int" + return func_with_new_name(f, name), name + +for op in ['lt', 'le', 'eq', 'ne', 'gt', 'ge']: + func, name = declare_new_float_comparison(op) + globals()[name] = func + func, name = declare_new_int_float_comparison(op) + globals()[name] = func + func, name = declare_new_float_int_comparison(op) + globals()[name] = func # for overflowing comparisons between longs and floats # XXX we might have to worry (later) about eq__Float_Int, for the case Modified: pypy/dist/pypy/objspace/std/intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/intobject.py (original) +++ pypy/dist/pypy/objspace/std/intobject.py Mon Apr 28 12:18:20 2008 @@ -50,35 +50,20 @@ str__Int = repr__Int -def lt__Int_Int(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i < j ) - -def le__Int_Int(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i <= j ) - -def eq__Int_Int(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i == j ) - -def ne__Int_Int(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i != j ) - -def gt__Int_Int(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i > j ) - -def ge__Int_Int(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i >= j ) +def declare_new_int_comparison(opname): + import operator + from pypy.tool.sourcetools import func_with_new_name + op = getattr(operator, opname) + def f(space, w_int1, w_int2): + i = w_int1.intval + j = w_int2.intval + return space.newbool(op(i, j)) + name = opname + "__Int_Int" + return func_with_new_name(f, name), name + +for op in ['lt', 'le', 'eq', 'ne', 'gt', 'ge']: + func, name = declare_new_int_comparison(op) + globals()[name] = func def hash__Int(space, w_int1): # unlike CPython, we don't special-case the value -1 in most of our Modified: pypy/dist/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_floatobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_floatobject.py Mon Apr 28 12:18:20 2008 @@ -157,6 +157,16 @@ assert 13.01 > 13L assert 13.0 >= 13L assert 13.01 >= 13L + assert 12.0 == 12 + assert 12.1 != 12 + assert infinite != 123456789 + assert 12.9 < 13 + assert -infinite < -13 + assert 12.9 <= 13 + assert 13.0 <= 13 + assert 13.01 > 13 + assert 13.0 >= 13 + assert 13.01 >= 13 assert infinite > verylonglong assert infinite >= verylonglong assert 1234.56 < verylonglong @@ -177,3 +187,8 @@ assert verylonglong <= infinite assert verylonglong > 1234.56 assert verylonglong >= 1234.56 + assert 13 >= 12.9 + assert 13 >= 13.0 + assert 13 < 13.01 + assert 13 <= 13.0 + assert 13 <= 13.01 From cami at codespeak.net Mon Apr 28 16:02:52 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 28 Apr 2008 16:02:52 +0200 (CEST) Subject: [pypy-svn] r54174 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080428140252.3590116805A@codespeak.net> Author: cami Date: Mon Apr 28 16:02:50 2008 New Revision: 54174 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: more refactoring Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Mon Apr 28 16:02:50 2008 @@ -8,17 +8,16 @@ class Channel(object): - # Audio Channel 1 int - nr0 = 0 - nr1 = 0 - nr2 = 0 - nr3 = 0 - nr4 = 0 audioIndex = 0 audioLength = 0 audioFrequency = 0 def __init__(self): + + self.audioLength=0 + self.audioEnvelope=0 + self.audioFrequency=0 + self.audioPlayback=0 self.nr0 = 0 self.nr1 = 0 self.nr2 = 0 @@ -32,42 +31,40 @@ self.audioIndex = 0 + def getAudioLength(self): + return self.audioLength + + def getAudioEnvelope(self): + return self.audioEnvelope + + def getAudioFrequency(self): + return self.audioFrequency + + def getAudioPlayback(self): + return self.audioPlayback + + + # ------------------------------------------------------------------------------ #SquareWaveGenerator class Channel1(Channel): # Audio Channel 1 int audioSweep=0 - audioLength=0 - audioEnvelope=0 - audioFrequency=0 - audioPlayback=0 audio1Index=0 audio1Length=0 - audio1Volume=0 + audioVolume=0 audio1EnvelopeLength=0 - audio1SweepLength=0 + audioSweepLength=0 audio1Frequency=0 # Audio Channel 1 def getAudioSweep(self): return self.audioSweep - def getAudioLength(self): - return self.audioLength - - def getAudioEnvelope(self): - return self.audioEnvelope - - def getAudioFrequency(self): - return self.audioFrequency - - def getAudioPlayback(self): - return self.audioPlayback - def setAudioSweep(self, data): self.audioSweep = data - self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audioSweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) def setAudioLength(self, data): self.audioLength = data @@ -78,11 +75,11 @@ if ((self.audioPlayback & 0x40) != 0): return if ((self.audioEnvelope >> 4) == 0): - self.audio1Volume = 0 + self.audioVolume = 0 elif (self.audio1EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): - self.audio1Volume = (self.audio1Volume + 1) & 0x0F + self.audioVolume = (self.audioVolume + 1) & 0x0F else: - self.audio1Volume = (self.audio1Volume + 2) & 0x0F + self.audioVolume = (self.audioVolume + 2) & 0x0F def setAudioFrequency(self, data): self.audioFrequency = data @@ -96,8 +93,8 @@ self.outputEnable |= 0x01 if ((self.audioPlayback & 0x40) != 0 and self.audio1Length == 0): self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) - self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) - self.audio1Volume = self.audioEnvelope >> 4 + self.audioSweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audioVolume = self.audioEnvelope >> 4 self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) def updateAudio(self): @@ -109,14 +106,14 @@ self.audio1EnvelopeLength-=1 if (self.audio1EnvelopeLength <= 0): if ((self.audioEnvelope & 0x08) != 0): - if (self.audio1Volume < 15): - self.audio1Volume+=1 - elif (self.audio1Volume > 0): - self.audio1Volume-=1 + if (self.audioVolume < 15): + self.audioVolume+=1 + elif (self.audioVolume > 0): + self.audioVolume-=1 self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) - if (self.audio1SweepLength > 0): - self.audio1SweepLength-=1 - if (self.audio1SweepLength <= 0): + if (self.audioSweepLength > 0): + self.audioSweepLength-=1 + if (self.audioSweepLength <= 0): sweepSteps = (self.audioSweep & 0x07) if (sweepSteps != 0): frequency = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency @@ -132,9 +129,10 @@ self.audio1Frequency = 0 self.outputEnable &= ~0x01 - self.audio1SweepLength += (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audioSweepLength += (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) def mixAudio(self, buffer, length): + wavePattern = 0x18 if (self.audioLength & 0xC0) == 0x00: wavePattern = 0x04 @@ -147,42 +145,28 @@ self.audio1Index += self.audio1Frequency if ((self.audio1Index & (0x1F << 22)) >= wavePattern): if ((self.outputTerminal & 0x10) != 0): - buffer[index + 0] -= self.audio1Volume + buffer[index + 0] -= self.audioVolume if ((self.outputTerminal & 0x01) != 0): - buffer[index + 1] -= self.audio1Volume + buffer[index + 1] -= self.audioVolume else: if ((self.outputTerminal & 0x10) != 0): - buffer[index + 0] += self.audio1Volume + buffer[index + 0] += self.audioVolume if ((self.outputTerminal & 0x01) != 0): - buffer[index + 1] += self.audio1Volume - + buffer[index + 1] += self.audioVolume + + #SquareWaveGenerator class Channel2(Channel): # Audio Channel 2 int - audioLength=0 - audioEnvelope=0 - audioFrequency=0 - audioPlayback=0 audio2Index=0 audio2Length=0 - audio2Volume=0 + audioVolume=0 audio2EnvelopeLength=0 audio2Frequency=0 # Audio Channel 2 - def getAudioLength(self): - return self.audioLength - - def getAudioEnvelope(self): - return self.audioEnvelope - - def getAudioFrequency(self): - return self.audioFrequency - - def getAudioPlayback(self): - return self.audioPlayback def setAudioLength(self, data): self.audioLength = data @@ -192,11 +176,11 @@ self.audioEnvelope = data if ((self.audioPlayback & 0x40) == 0): if ((self.audioEnvelope >> 4) == 0): - self.audio2Volume = 0 + self.audioVolume = 0 elif (self.audio2EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): - self.audio2Volume = (self.audio2Volume + 1) & 0x0F + self.audioVolume = (self.audioVolume + 1) & 0x0F else: - self.audio2Volume = (self.audio2Volume + 2) & 0x0F + self.audioVolume = (self.audioVolume + 2) & 0x0F def setAudioFrequency(self, data): self.audioFrequency = data @@ -211,7 +195,7 @@ self.outputEnable |= 0x02 if ((self.audioPlayback & 0x40) != 0 and self.audio2Length == 0): self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) - self.audio2Volume = self.audioEnvelope >> 4 + self.audioVolume = self.audioEnvelope >> 4 self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) def updateAudio(self): @@ -224,10 +208,10 @@ if (self.audio2EnvelopeLength <= 0): if ((self.audioEnvelope & 0x08) != 0): - if (self.audio2Volume < 15): - self.audio2Volume+=1 - elif (self.audio2Volume > 0): - self.audio2Volume-=1 + if (self.audioVolume < 15): + self.audioVolume+=1 + elif (self.audioVolume > 0): + self.audioVolume-=1 self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) def mixAudio(self, buffer, length): @@ -243,14 +227,14 @@ self.audio2Index += self.audio2Frequency if ((self.audio2Index & (0x1F << 22)) >= wavePattern): if ((self.outputTerminal & 0x20) != 0): - buffer[index + 0] -= self.audio2Volume + buffer[index + 0] -= self.audioVolume if ((self.outputTerminal & 0x02) != 0): - buffer[index + 1] -= self.audio2Volume + buffer[index + 1] -= self.audioVolume else: if ((self.outputTerminal & 0x20) != 0): - buffer[index + 0] += self.audio2Volume + buffer[index + 0] += self.audioVolume if ((self.outputTerminal & 0x02) != 0): - buffer[index + 1] += self.audio2Volume + buffer[index + 1] += self.audioVolume @@ -260,10 +244,7 @@ class Channel3(Channel): # Audio Channel 3 int audioEnable=0 - audioLength=0 audioLevel=0 - audioFrequency=0 - audioPlayback=0 audio3Index=0 audio3Length=0 audio3Frequency=0 @@ -274,9 +255,6 @@ def getAudioEnable(self): return self.audioEnable - def getAudioLength(self): - return self.audioLength - def getAudioLevel(self): return self.audioLevel @@ -284,9 +262,6 @@ def getAudio4Frequency(self): return self.audioFrequency - def getAudioPlayback(self): - return self.audioPlayback - def setAudioEnable(self, data): self.audioEnable = data & 0x80 if ((self.audioEnable & 0x80) == 0): @@ -331,7 +306,6 @@ wavePattern = 0 elif (self.audioLevel & 0x60) == 0x80: wavePattern = 1 - for index in range(0, length, 2): self.audio3Index += self.audio3Frequency sample = self.audio3WavePattern[(self.audio3Index >> 23) & 0x0F] @@ -342,23 +316,20 @@ sample = ((sample - 8) << 1) >> level - if ((self.outputTerminal & 0x40) != 0): + if (self.outputTerminal & 0x40) != 0: buffer[index + 0] += sample - if ((self.outputTerminal & 0x04) != 0): + if (self.outputTerminal & 0x04) != 0: buffer[index + 1] += sample - class NoiseGenerator(Channel): # Audio Channel 4 int audioLength=0 - audioEnvelope=0 audioPolynomial=0 - audioPlayback=0 audio4Index=0 audio4Length=0 - audio4Volume=0 + audioVolume=0 audio4EnvelopeLength=0 audio4Frequency=0 @@ -375,8 +346,8 @@ sampleRate = self.driver.getSampleRate() # frequency = (4194304 / 32) / (2048 - period) Hz for period in range(0, 2048): - skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << (22 - 8)) / (2048 - period) - if (skip >= (32 << 22)): + skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << 16) / (2048 - period) + if skip >= (32 << 22): self.frequencyTable[period] = 0 else: self.frequencyTable[period] = skip @@ -396,14 +367,14 @@ # 7 steps for index in range(0, 0x7F): polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | (polynomial >> 1) - if ((index & 31) == 0): + if (index & 31) == 0: self.noiseStep7Table[index >> 5] = 0 self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31) # 15 steps& polynomial = 0x7FFF for index in range(0, 0x7FFF): polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1) - if ((index & 31) == 0): + if (index & 31) == 0: self.noiseStep15Table[index >> 5] = 0 self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31) @@ -411,9 +382,6 @@ def getAudioLength(self): return self.audioLength - def getAudioEnvelope(self): - return self.audioEnvelope - def getAudioPolynomial(self): return self.audioPolynomial @@ -426,51 +394,51 @@ def setAudioEnvelope(self, data): self.audioEnvelope = data - if ((self.audioPlayback & 0x40) == 0): - if ((self.audioEnvelope >> 4) == 0): - self.audio4Volume = 0 - elif (self.audio4EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): - self.audio4Volume = (self.audio4Volume + 1) & 0x0F + if (self.audioPlayback & 0x40) == 0: + if (self.audioEnvelope >> 4) == 0: + self.audioVolume = 0 + elif self.audio4EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0: + self.audioVolume = (self.audioVolume + 1) & 0x0F else: - self.audio4Volume = (self.audio4Volume + 2) & 0x0F + self.audioVolume = (self.audioVolume + 2) & 0x0F def setAudioPolynomial(self, data): self.audioPolynomial = data - if ((self.audioPolynomial >> 4) <= 12): + if (self.audioPolynomial >> 4) <= 12: self.audio4Frequency = self.noiseFreqRatioTable[self.audioPolynomial & 0x07] >> ((self.audioPolynomial >> 4) + 1) else: self.audio4Frequency = 0 def setAudioPlayback(self, data): self.audioPlayback = data - if ((self.audioPlayback & 0x80) != 0): + if (self.audioPlayback & 0x80) != 0: self.outputEnable |= 0x08 - if ((self.audioPlayback & 0x40) != 0 and self.audio4Length == 0): + if (self.audioPlayback & 0x40) != 0 and self.audio4Length == 0: self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) - self.audio4Volume = self.audioEnvelope >> 4 + self.audioVolume = self.audioEnvelope >> 4 self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) self.audio4Index = 0 def updateAudio(self): - if ((self.audioPlayback & 0x40) != 0 and self.audio4Length > 0): + if (self.audioPlayback & 0x40) != 0 and self.audio4Length > 0: self.audio4Length-=1 - if (self.audio4Length <= 0): + if self.audio4Length <= 0: self.outputEnable &= ~0x08 - if (self.audio4EnvelopeLength > 0): + if self.audio4EnvelopeLength > 0: self.audio4EnvelopeLength-=1 - if (self.audio4EnvelopeLength <= 0): - if ((self.audioEnvelope & 0x08) != 0): - if (self.audio4Volume < 15): - self.audio4Volume+=1 - elif (self.audio4Volume > 0): - self.audio4Volume-=1 + if self.audio4EnvelopeLength <= 0: + if (self.audioEnvelope & 0x08) != 0: + if self.audioVolume < 15: + self.audioVolume+=1 + elif self.audioVolume > 0: + self.audioVolume-=1 self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) def mixAudio(self, buffer, length): for index in range(0, length, 2): self.audio4Index += self.audio4Frequency polynomial - if ((self.audioPolynomial & 0x08) != 0): + if (self.audioPolynomial & 0x08) != 0: # 7 steps self.audio4Index &= 0x7FFFFF polynomial = self.noiseStep7Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) @@ -478,16 +446,16 @@ # 15 steps self.audio4Index &= 0x7FFFFFFF polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) - if ((polynomial & 1) != 0): - if ((self.outputTerminal & 0x80) != 0): - buffer[index + 0] -= self.audio4Volume - if ((self.outputTerminal & 0x08) != 0): - buffer[index + 1] -= self.audio4Volume + if (polynomial & 1) != 0: + if (self.outputTerminal & 0x80) != 0: + buffer[index + 0] -= self.audioVolume + if (self.outputTerminal & 0x08) != 0: + buffer[index + 1] -= self.audioVolume else: - if ((self.outputTerminal & 0x80) != 0): - buffer[index + 0] += self.audio4Volume - if ((self.outputTerminal & 0x08) != 0): - buffer[index + 1] += self.audio4Volume + if (self.outputTerminal & 0x80) != 0: + buffer[index + 0] += self.audioVolume + if (self.outputTerminal & 0x08) != 0: + buffer[index + 1] += self.audioVolume Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Mon Apr 28 16:02:50 2008 @@ -102,7 +102,7 @@ # CLOCK DRIVER ----------------------------------------------------------------- -class ClockDriver(object): +class Clock(object): def __init__(self): pass Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Mon Apr 28 16:02:50 2008 @@ -202,16 +202,17 @@ def setLYCompare(self, data): self.lineYCompare = data - if ((self.control & 0x80) != 0): - if (self.lineY == self.lineYCompare): - # NOTE: raise interrupt once per line (Prehistorik Man, The Jetsons, Muhammad Ali) - if ((self.stat & 0x04) == 0): - # constants.LYC=LY interrupt - self.stat |= 0x04 - if ((self.stat & 0x40) != 0): - self.interrupt.raiseInterrupt(constants.LCD) - else: - self.stat &= 0xFB + if (self.control & 0x80) == 0: + return + if (self.lineY == self.lineYCompare): + # NOTE: raise interrupt once per line + if (self.stat & 0x04) == 0: + # constants.LYC=LY interrupt + self.stat |= 0x04 +# if (self.stat & 0x40) != 0: + self.interrupt.raiseInterrupt(constants.LCD) + else: + self.stat &= 0xFB def getDMA(self): return self.dma @@ -279,70 +280,88 @@ def emulateHBlank(self): self.lineY+=1 - if (self.lineY == self.lineYCompare): + self.emulateHBlankLineYCompare() + if self.lineY < 144: + self.emulateHBlankPart1() + else: + self.emulateHBlankPart2() + + def emulateHBlankLineYCompare(self): + if self.lineY == self.lineYCompare: # constants.LYC=LY interrupt self.stat |= 0x04 - if ((self.stat & 0x40) != 0): + if (self.stat & 0x40) != 0: self.interrupt.raiseInterrupt(constants.LCD) else: self.stat &= 0xFB - if (self.lineY < 144): - self.stat = (self.stat & 0xFC) | 0x02 - self.cycles += constants.MODE_2_TICKS - # constants.OAM interrupt - if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44): - self.interrupt.raiseInterrupt(constants.LCD) + def emulateHBlankPart1(self): + self.stat = (self.stat & 0xFC) | 0x02 + self.cycles += constants.MODE_2_TICKS + # constants.OAM interrupt + if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44): + self.interrupt.raiseInterrupt(constants.LCD) + + def emulateHBlankPart2(self): + if self.display: + self.drawFrame() + self.frames += 1 + if self.frames >= self.frameSkip: + self.display = True + self.frames = 0 else: - if (self.display): - self.drawFrame() - self.frames += 1 - if (self.frames >= self.frameSkip): - self.display = True - self.frames = 0 - else: - self.display = False - - self.stat = (self.stat & 0xFC) | 0x01 - self.cycles += constants.MODE_1_BEGIN_TICKS - self.vblank = True + self.display = False + self.stat = (self.stat & 0xFC) | 0x01 + self.cycles += constants.MODE_1_BEGIN_TICKS + self.vblank = True + + def emulateVBlank(self): - if (self.vblank): - self.vblank = False + if self.vblank: + self.emulateVBlankVBlank() + elif self.lineY == 0: + self.emulateVBlankFirstYLine() + else: + self.emulateVBlankOther() + + def emulateVBlankVBlank(self): + self.vblank = False + self.stat = (self.stat & 0xFC) | 0x01 + self.cycles += constants.MODE_1_TICKS - constants.MODE_1_BEGIN_TICKS + # V-Blank interrupt + if ((self.stat & 0x10) != 0): + self.interrupt.raiseInterrupt(constants.LCD) + # V-Blank interrupt + self.interrupt.raiseInterrupt(constants.VBLANK) + + def emulateVBlankFirstYLine(self): + self.stat = (self.stat & 0xFC) | 0x02 + self.cycles += constants.MODE_2_TICKS + # constants.OAM interrupt + if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44): + self.interrupt.raiseInterrupt(constants.LCD) + + def emulateVBlankOther(self): + if (self.lineY < 153): + self.lineY+=1 self.stat = (self.stat & 0xFC) | 0x01 - self.cycles += constants.MODE_1_TICKS - constants.MODE_1_BEGIN_TICKS - # V-Blank interrupt - if ((self.stat & 0x10) != 0): - self.interrupt.raiseInterrupt(constants.LCD) - # V-Blank interrupt - self.interrupt.raiseInterrupt(constants.VBLANK) - elif (self.lineY == 0): - self.stat = (self.stat & 0xFC) | 0x02 - self.cycles += constants.MODE_2_TICKS - # constants.OAM interrupt - if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44): + if (self.lineY == 153): + self.cycles += constants.MODE_1_END_TICKS + else: + self.cycles += constants.MODE_1_TICKS + else: + self.lineY = self.wlineY = 0 + self.stat = (self.stat & 0xFC) | 0x01 + self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS + if (self.lineY == self.lineYCompare): + # constants.LYC=LY interrupt + self.stat |= 0x04 + if ((self.stat & 0x40) != 0): self.interrupt.raiseInterrupt(constants.LCD) else: - if (self.lineY < 153): - self.lineY+=1 - self.stat = (self.stat & 0xFC) | 0x01 - if (self.lineY == 153): - self.cycles += constants.MODE_1_END_TICKS - else: - self.cycles += constants.MODE_1_TICKS - else: - self.lineY = self.wlineY = 0 - self.stat = (self.stat & 0xFC) | 0x01 - self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS - if (self.lineY == self.lineYCompare): - # constants.LYC=LY interrupt - self.stat |= 0x04 - if ((self.stat & 0x40) != 0): - self.interrupt.raiseInterrupt(constants.LCD) - else: - self.stat &= 0xFB - + self.stat &= 0xFB + def drawFrame(self): self.driver.updateDisplay() @@ -351,13 +370,13 @@ self.driver.updateDisplay() def drawLine(self): - if ((self.control & 0x01) != 0): + if (self.control & 0x01) != 0: self.drawBackground() else: self.drawCleanBackground() - if ((self.control & 0x20) != 0): + if (self.control & 0x20) != 0: self.drawWindow() - if ((self.control & 0x02) != 0): + if (self.control & 0x02) != 0: self.drawObjects() self.drawPixels() @@ -374,22 +393,23 @@ tileData = constants.VRAM_DATA_B if (self.control & 0x10) != 0: tileData = constants.VRAM_DATA_A - tileMap += ((y >> 3) << 5) + (x >> 3) + tileMap += ((y >> 3) << 5) + (x >> 3) tileData += (y & 7) << 1 self.drawTiles(8 - (x & 7), tileMap, tileData) def drawWindow(self): - if (self.lineY >= self.windowY and self.windowX < 167 and self.wlineY < 144): - tileMap = constants.VRAM_MAP_A - if (self.control & 0x40) != 0: - tileMap = constants.VRAM_MAP_B - tileData = constants.VRAM_DATA_B - if (self.control & 0x10) != 0: - tileData = constants.VRAM_DATA_A - tileMap += (self.wlineY >> 3) << 5 - tileData += (self.wlineY & 7) << 1 - self.drawTiles(self.windowX + 1, tileMap, tileData) - self.wlineY+=1 + if (self.lineY < self.windowY or self.windowX >= 167 or self.wlineY >= 144): + return + tileMap = constants.VRAM_MAP_A + if (self.control & 0x40) != 0: + tileMap = constants.VRAM_MAP_B + tileData = constants.VRAM_DATA_B + if (self.control & 0x10) != 0: + tileData = constants.VRAM_DATA_A + tileMap += (self.wlineY >> 3) << 5 + tileData += (self.wlineY & 7) << 1 + self.drawTiles(self.windowX + 1, tileMap, tileData) + self.wlineY+=1 def drawObjects(self): count = self.scanObjects() @@ -445,9 +465,9 @@ for index in range(0, count): rightmost = index for number in range(index+1, count): - if ((self.objects[number] >> 20) > (self.objects[rightmost] >> 20)): + if (self.objects[number] >> 20) > (self.objects[rightmost] >> 20): rightmost = number - if (rightmost != index): + if rightmost != index: data = self.objects[index] self.objects[index] = self.objects[rightmost] self.objects[rightmost] = data @@ -461,79 +481,62 @@ self.drawTile(x, tileData + (tile << 4)) tileMap = (tileMap & 0x1FE0) + ((tileMap + 1) & 0x001F) x += 8 - - def drawTile(self, x, address): - pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8) - for i in range(0, 8): - self.line[x + i] = (pattern >> (7-i)) & 0x0101 - - def drawObjectTile(self, x, address, flags): - pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8) - mask = 0 + + def getPattern(self, address): + pattern = self.vram[address] & 0xFF + pattern +=(self.vram[address + 1] & 0xFF) << 8 + return pattern + + def drawObject(self, setter): + pattern = self.getPattern(address) + self.mask = 0 # priority if (flags & 0x80) != 0: - mask |= 0x0008 + self.mask |= 0x0008 # palette if (flags & 0x10) != 0: - mask |= 0x0004 - # X flip + self.mask |= 0x0004 if (flags & 0x20) != 0: - self.drawObjectTileXFlipped(x, pattern, mask) + self.drawObjectNormal(x, pattern, mask, setter) else: - self.drawObjectTileNormal(x, pattern, mask) - - def drawObjectTileNormal(self, x, pattern, mask): - for i in range(0, 7): - color = (pattern >> (6-i)) - if ((color & 0x0202) != 0): - self.line[x + i] |= color | mask - color = (pattern << 1) - if ((color & 0x0202) != 0): - self.line[x + 7] |= color | mask + self.drawObjectFlipped(x, pattern, mask, setter) - def drawObjectTileXFlipped(self, x, pattern, mask): - color = (pattern << 1) - if ((color & 0x0202) != 0): - self.line[x + 0] |= color | mask - for i in range(0, 7): - color = (pattern >> i) - if ((color & 0x0202) != 0): - self.line[x + i + 1] |= color | mask + def drawObjectNormal(self, x, pattern, mask, setter): + for i in range(0, 7): + color = pattern >> (6-i) + if (color & 0x0202) != 0: + setter(self, x+1, color, mask) + color = pattern << 1 + if (color & 0x0202) != 0: + setter(self, x+7, color, mask) + + def drawObjectFlipped(self, x, pattern, mask, setter): + color = pattern << 1 + if (color & 0x0202) != 0: + setter(self, x, color | mask) + for i in range(0, 7): + color = pattern >> i + if (color & 0x0202) != 0: + setter(self, x + i + 1, color | mask) + + def drawTile(self, x, address): + pattern = self.getPattern(address) + for i in range(0, 8): + self.line[x + i] = (pattern >> (7-i)) & 0x0101 + def drawObjectTile(self, x, address, flags): + pattern = self.getPattern(address) + self.drawObject(self.setTileLine) + + def setTileLine(self, pos, color, mask): + self.line[pos] |= color | mask def drawOverlappedObjectTile(self, x, address, flags): - pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8) - mask = 0 - # priority - if ((flags & 0x80) != 0): - mask |= 0x0008 - # palette - if ((flags & 0x10) != 0): - mask |= 0x0004 - # X flip - if ((flags & 0x20) != 0): - self.drawOverlappedObjectTileXFlipped(x, pattern, mask) - else: - self.drawOverlappedObjectTileNormal(x, pattern, mask) + self.drawObject(self.setOverlappedObjectLine) + + def setOverlappedObjectLine(self, pos, color, mask): + self.line[pos] = (self.line[pos] & 0x0101) | color | mask - def drawOverlappedObjectTileNormal(self, x, pattern, mask): - for i in range(0,7): - color = (pattern >> (6-i)) - if ((color & 0x0202) != 0): - self.line[x + i] = (self.line[x + i] & 0x0101) | color | mask - color = (pattern << 1) - if ((color & 0x0202) != 0): - self.line[x + 7] = (self.line[x + 7] & 0x0101) | color | mask - - def drawOverlappedObjectTileXFlipped(self, x, pattern, mask): - color = (pattern << 1) - if ((color & 0x0202) != 0): - self.line[x + 0] = (self.line[x + 0] & 0x0101) | color | mask - #TODO maybe a bug in the java implementetation [0,1,2,3,4,6,5] - for i in range(0,7): - color = (pattern >> i) - if ((color & 0x0202) != 0): - self.line[x + i + 1] = (self.line[x + i +1] & 0x0101) | color | mask def drawPixels(self): self.updatePalette() @@ -546,9 +549,7 @@ offset += 4 def clearPixels(self): - pixels = self.driver.getPixels() - for offset in range(0, len(pixels)): - pixels[offset] = constants.COLOR_MAP[0] + self.driver.clearPixels() def updatePalette(self): if not self.dirty: @@ -576,8 +577,11 @@ def __init__(self, width, height): self.width = width self.height = height - self.pixels = [0]*width*height + self.clearPixels() + def clearPixels(): + self.pixels = [0] * self.width * self.height + def getWidth(self): return self.width From cami at codespeak.net Mon Apr 28 18:00:29 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 28 Apr 2008 18:00:29 +0200 (CEST) Subject: [pypy-svn] r54175 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080428160029.C2E311680B8@codespeak.net> Author: cami Date: Mon Apr 28 18:00:26 2008 New Revision: 54175 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Log: added some more cpu tests fixed some minor bugs in cpu Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Mon Apr 28 18:00:26 2008 @@ -362,13 +362,13 @@ self.cycles -= 2 # Fetching 1 cycle - def fetch(self): + def fetch(self, useCycles=True): self.cycles += 1 - if (self.pc.get() <= 0x3FFF): - data = self.rom[self.pc.get()] + if self.pc.get(useCycles) <= 0x3FFF: + data = self.rom[self.pc.get(useCycles)] else: - data = self.memory.read(self.pc.get()) - self.pc.inc() # 2 cycles + data = self.memory.read(self.pc.get(useCycles)) + self.pc.inc(useCycles) # 2 cycles return data def fetchDoubleAddress(self): @@ -464,7 +464,7 @@ def carryFlagFinish(self, s, data): self.f.reset() - # set the hfalg if the 0x10 bit was affected + # set the hflag if the 0x10 bit was affected if ((s ^ self.a.get() ^ data) & 0x10) != 0: self.f.hFlag = True if s >= 0x100: @@ -473,10 +473,14 @@ self.a.set(s) # 1 cycle # 1 cycle - def subtract(self, getter, setter=None): + def subtractA(self, getter, setter=None): self.compareA(getter, setter) # 1 cycle self.a.sub(getter(useCycles=False), False) + def fetchSubtractA(self): + data = self.fetch() + self.subtractA(lambda useCycles=False: data) + # 1 cycle def compareA(self, getter, setter=None): s = (self.a.get() - getter()) & 0xFF @@ -798,8 +802,8 @@ self.call(self.fetchDoubleAddress()) # 4+2 cycles # CALL cc,nnnn, 3,6 cycles - def conditionalCall(self, getter): - if getter(): + def conditionalCall(self, cc): + if cc: self.unconditionalCall() # 6 cycles else: self.pc.add(2) # 3 cycles @@ -965,7 +969,7 @@ (0xCD, CPU.unconditionalCall), (0xC6, lambda s: CPU.addA(s, s.fetch)), (0xCE, lambda s: CPU.addWithCarry(s, s.fetch)), - (0xD6, lambda s: CPU.subtract(s, s.fetch)), + (0xD6, CPU.fetchSubtractA), (0xDE, lambda s: CPU.subtractWithCarry(s, s.fetch)), (0xE6, lambda s: CPU.AND(s, s.fetch)), (0xEE, lambda s: CPU.XOR(s, s.fetch)), @@ -987,7 +991,7 @@ (0x06, 0x08, CPU.loadFetchRegister), (0x80, 0x01, CPU.addA), (0x88, 0x01, CPU.addWithCarry), - (0x90, 0x01, CPU.subtract), + (0x90, 0x01, CPU.subtractA), (0x98, 0x01, CPU.subtractWithCarry), (0xA0, 0x01, CPU.AND), (0xA8, 0x01, CPU.XOR), Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Mon Apr 28 18:00:26 2008 @@ -1377,18 +1377,53 @@ assert cpu.pc.get() == cpu.interrupt.vBlank.callCode assert cpu.ime == False +def conditionalCallTest(cpu, opCode, flagSetter): + flagSetter(cpu, False) + cpu.pc.set(0) + f = cpu.f.get() + cycle_test(cpu, 0xC4, 3) + assert_default_registers(cpu, pc=2, f=f) + + cpu.reset() + fetchValue = 0x1234 + flagSetter(cpu, True) + cpu.sp.set(fetchValue) + prepare_for_fetch(cpu, fetchValue) + f = cpu.f.get() + cycle_test(cpu, 0xC4, 6) + assert_default_registers(cpu, pc=fetchValue, sp=fetchValue-2, f=f) + # call_NZ_nnnn def test_0xC4(): - pass + cpu = get_cpu() + conditionalCallTest(cpu, 0xC4, setFlag0xC4) + +def setFlag0xC4(cpu, value): + cpu.f.zFlag = not value + # call_Z_nnnn def test_0xCC(): - pass + cpu = get_cpu() + conditionalCallTest(cpu, 0xCC, setFlag0xC4) + +def setFlag0xCC(cpu, value): + cpu.f.cFlag = not value + # call_NC_nnnn def test_0xD4(): - pass + cpu = get_cpu() + conditionalCallTest(cpu, 0xD4, setFlag0xC4) + +def setFlag0xD4(cpu, value): + cpu.f.cFlag = value + # call_C_nnnn def test_0xDC(): - pass + cpu = get_cpu() + conditionalCallTest(cpu, 0xDC, setFlag0xC4) + +def setFlag0xDC(cpu, value): + cpu.f.zFlag = value # push_BC to push_AF def test_0xC5_to_0xF5(): @@ -1407,39 +1442,67 @@ # call_nnnn def test_0xCD(): - pass + cpu = get_cpu() + fetchValue = 0x1234 + cpu.sp.set(fetchValue) + prepare_for_fetch(cpu, fetchValue) + cycle_test(cpu, 0xCD, 6) + assert_default_registers(cpu, pc=fetchValue, sp=fetchValue-2) + +def a_nn_test(opCode, cycles, opCaller): + # flags tested already + cpu = get_cpu() + value = 0x12 + valueAdd = 0x12 + cpu.a.set(value) + prepare_for_fetch(cpu, valueAdd,) + pc = cpu.pc.get() + + cycle_test(cpu, opCode, cycles) + assert_default_registers(cpu, a=opCaller(value,valueAdd, cpu), pc=pc+1, f=cpu.f.get()) + return cpu # add_A_nn def test_0xC6(): - pass + a_nn_test(0xC6, 2, lambda a, b, cpu: a+b) # adc_A_nn def test_0xCE(): - pass + a_nn_test(0xCE, 2, lambda a, b, cpu: a+b) # sub_A_nn def test_0xD6(): - pass + a_nn_test(0xD6, 2, lambda a, b, cpu: a-b) # sbc_A_nn def test_0xDE(): - pass + a_nn_test(0xDE, 2, lambda a, b, cpu: a-b) # and_A_nn def test_0xE6(): - pass + a_nn_test(0xE6, 2, lambda a, b, cpu: a&b) # xor_A_nn def test_0xEE(): - pass + a_nn_test(0xEE, 2, lambda a, b, cpu: a^b) # or_A_nn def test_0xF6(): - pass + a_nn_test(0xF6, 2, lambda a, b, cpu: a|b) # cp_A_nn def test_0xFE(): - pass + # flags tested already + cpu = get_cpu() + value = 0x12 + valueA = 0x12 + cpu.a.set(valueA) + pc = cpu.pc.get() + + cycle_test(cpu, 0xFE, 2) + + assert_default_registers(cpu, a=valueA, pc=pc+1, f=cpu.f.get()) + assert cpu.f.zFlag == True # rst(0x00) to rst(0x38) def test_0xC7_to_0xFF(): From arigo at codespeak.net Mon Apr 28 19:17:00 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:17:00 +0200 (CEST) Subject: [pypy-svn] r54176 - pypy/branch/oo-jit Message-ID: <20080428171700.5F425168074@codespeak.net> Author: arigo Date: Mon Apr 28 19:16:58 2008 New Revision: 54176 Added: pypy/branch/oo-jit/ - copied from r54175, pypy/dist/ Log: (antocuni, arigo) A branch for the efforts towards an oo-typesystem JIT, and towards a CLI version. From arigo at codespeak.net Mon Apr 28 19:30:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:19 +0200 (CEST) Subject: [pypy-svn] r54177 - pypy/branch/oo-jit/pypy/config Message-ID: <20080428173019.E24461683D3@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:17 2008 New Revision: 54177 Added: pypy/branch/oo-jit/pypy/config/translationoption.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/config/translationoption.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/config/translationoption.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53562 | fijal | 2008-04-08 04:43:19 +0200 (Tue, 08 Apr 2008) | 2 lines add --jit-backend to force backend choice ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52122 | cfbolz | 2008-03-03 21:16:57 +0100 (Mon, 03 Mar 2008) | 2 lines add rainbow to the fork-before options ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:21 +0200 (CEST) Subject: [pypy-svn] r54178 - pypy/branch/oo-jit/pypy/interpreter Message-ID: <20080428173021.931E01683D3@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:20 2008 New Revision: 54178 Added: pypy/branch/oo-jit/pypy/interpreter/pyopcode.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/interpreter/pyopcode.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/interpreter/pyopcode.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53548 | fijal | 2008-04-07 23:44:54 +0200 (Mon, 07 Apr 2008) | 2 lines Don't try to handle NotImplementedError here ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:26 +0200 (CEST) Subject: [pypy-svn] r54179 - pypy/branch/oo-jit/pypy/annotation Message-ID: <20080428173026.E20E61683D7@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:25 2008 New Revision: 54179 Added: pypy/branch/oo-jit/pypy/annotation/binaryop.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/annotation/binaryop.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/annotation/binaryop.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52059 | arigo | 2008-03-02 18:28:35 +0100 (Sun, 02 Mar 2008) | 3 lines Experimental, to help in translating the rainbow interpreter: reading from empty lists is not fatal ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:31 +0200 (CEST) Subject: [pypy-svn] r54180 - pypy/branch/oo-jit/pypy/annotation Message-ID: <20080428173031.3B4C81683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:30 2008 New Revision: 54180 Added: pypy/branch/oo-jit/pypy/annotation/description.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/annotation/description.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/annotation/description.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52518 | arigo | 2008-03-14 17:37:51 +0100 (Fri, 14 Mar 2008) | 5 lines Obscure annotator bug: don't attach _annenforceargs_ back to the real function object! It explodes confusingly if the function object has many specialized version because _annenforceargs_ then shows up on the other versions as well... ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:34 +0200 (CEST) Subject: [pypy-svn] r54181 - pypy/branch/oo-jit/pypy/annotation Message-ID: <20080428173034.6D9871683DB@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:33 2008 New Revision: 54181 Added: pypy/branch/oo-jit/pypy/annotation/builtin.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/annotation/builtin.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/annotation/builtin.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53057 | antocuni | 2008-03-28 17:53:32 +0100 (Fri, 28 Mar 2008) | 4 lines annotation & rtyping of the new type ootype.Object and the two operations cast_to_object and cast_from_object. ------------------------------------------------------------------------ r52520 | arigo | 2008-03-14 18:00:44 +0100 (Fri, 14 Mar 2008) | 4 lines Test and a simple fix for calling list() on a list and then mutating the result to make the items more general (used to cause a badly-typed called to ll_copy()). ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:37 +0200 (CEST) Subject: [pypy-svn] r54182 - pypy/branch/oo-jit/pypy/annotation Message-ID: <20080428173037.AD6991683DC@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:36 2008 New Revision: 54182 Added: pypy/branch/oo-jit/pypy/annotation/model.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/annotation/model.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/annotation/model.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53057 | antocuni | 2008-03-28 17:53:32 +0100 (Fri, 28 Mar 2008) | 4 lines annotation & rtyping of the new type ootype.Object and the two operations cast_to_object and cast_from_object. ------------------------------------------------------------------------ r52507 | arigo | 2008-03-14 16:55:37 +0100 (Fri, 14 Mar 2008) | 3 lines A translation test for the hotpath support code. Some initial RPython fixes, in-progress. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:40 +0200 (CEST) Subject: [pypy-svn] r54183 - pypy/branch/oo-jit/pypy/translator Message-ID: <20080428173040.661DF1683D9@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:39 2008 New Revision: 54183 Added: pypy/branch/oo-jit/pypy/translator/driver.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/driver.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/driver.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53562 | fijal | 2008-04-08 04:43:19 +0200 (Tue, 08 Apr 2008) | 2 lines add --jit-backend to force backend choice ------------------------------------------------------------------------ r53375 | arigo | 2008-04-05 09:36:46 +0200 (Sat, 05 Apr 2008) | 2 lines Need to mention the ia32 backend here. ------------------------------------------------------------------------ r53096 | arigo | 2008-03-29 17:02:08 +0100 (Sat, 29 Mar 2008) | 8 lines Biggish refactoring of the way the JitDriver class is used. We're now supposed to create a (singleton) instance of it, and subclassing JitDriver is optional. This is somewhat a clean-up. It fixes the translation issues about the way JIT parameters are set (classmethods are not really supported in RPython). All tests (I think) ported to the new style -- keyboard macros rule :-) ------------------------------------------------------------------------ r52917 | arigo | 2008-03-25 16:20:59 +0100 (Tue, 25 Mar 2008) | 2 lines Be slightly less verbose by default in --jit translated interpreters. ------------------------------------------------------------------------ r52901 | arigo | 2008-03-25 13:15:12 +0100 (Tue, 25 Mar 2008) | 3 lines fwiw the tests still pass when applying graphopt.simplify_virtualizable_accesses(). ------------------------------------------------------------------------ r52880 | arigo | 2008-03-23 20:08:24 +0100 (Sun, 23 Mar 2008) | 3 lines Some minimal wacking until the threshold is configurable at run-time in a pypy-c-jit. ------------------------------------------------------------------------ r52789 | arigo | 2008-03-20 19:35:14 +0100 (Thu, 20 Mar 2008) | 2 lines Reduce the massive spamming of --jit translations. ------------------------------------------------------------------------ r52727 | cfbolz | 2008-03-19 16:50:52 +0100 (Wed, 19 Mar 2008) | 2 lines (cfbolz, arigo): use the low level type system bytecode writer ------------------------------------------------------------------------ r52721 | cfbolz | 2008-03-19 14:53:44 +0100 (Wed, 19 Mar 2008) | 2 lines (arigo, cfbolz): support the hotpath jit stuff in the driver too ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52240 | arigo | 2008-03-07 10:58:28 +0100 (Fri, 07 Mar 2008) | 5 lines Can't use constant_fold_graph() here because it doesn't preserve annotations. The original problem was that hannotator.simplify() was not done any more when using the translator driver. ------------------------------------------------------------------------ r52080 | cfbolz | 2008-03-03 00:32:19 +0100 (Mon, 03 Mar 2008) | 3 lines fix the driver and translate.py to use the rainbow interpreter instead of the timeshifter ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:45 +0200 (CEST) Subject: [pypy-svn] r54184 - pypy/branch/oo-jit/pypy/rlib Message-ID: <20080428173045.4BAC01683D9@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:44 2008 New Revision: 54184 Added: pypy/branch/oo-jit/pypy/rlib/objectmodel.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rlib/objectmodel.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rlib/objectmodel.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52516 | arigo | 2008-03-14 17:24:58 +0100 (Fri, 14 Mar 2008) | 2 lines Duh, a bug in the implementation of noop(). ------------------------------------------------------------------------ r52507 | arigo | 2008-03-14 16:55:37 +0100 (Fri, 14 Mar 2008) | 3 lines A translation test for the hotpath support code. Some initial RPython fixes, in-progress. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:49 +0200 (CEST) Subject: [pypy-svn] r54185 - pypy/branch/oo-jit/pypy/rpython Message-ID: <20080428173049.1D3051683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:48 2008 New Revision: 54185 Added: pypy/branch/oo-jit/pypy/rpython/rpbc.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/rpbc.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/rpbc.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52226 | arigo | 2008-03-06 19:03:29 +0100 (Thu, 06 Mar 2008) | 2 lines Give these Structs a better name than just 'pbc' if possible. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:54 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:54 +0200 (CEST) Subject: [pypy-svn] r54186 - pypy/branch/oo-jit/pypy/rpython Message-ID: <20080428173054.CFC881683E0@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:54 2008 New Revision: 54186 Added: pypy/branch/oo-jit/pypy/rpython/annlowlevel.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/annlowlevel.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/annlowlevel.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53076 | antocuni | 2008-03-29 10:46:18 +0100 (Sat, 29 Mar 2008) | 3 lines make llhelper() working also with ootype ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52215 | arigo | 2008-03-06 15:58:49 +0100 (Thu, 06 Mar 2008) | 2 lines Typo ------------------------------------------------------------------------ r52214 | arigo | 2008-03-06 15:28:48 +0100 (Thu, 06 Mar 2008) | 2 lines Oh well. Very ad hoc function to support the JIT... ------------------------------------------------------------------------ r52213 | arigo | 2008-03-06 13:32:33 +0100 (Thu, 06 Mar 2008) | 2 lines A skipped test documenting what doesn't work with llhelper(). ------------------------------------------------------------------------ r52092 | arigo | 2008-03-03 15:52:30 +0100 (Mon, 03 Mar 2008) | 4 lines Whack until exceptions within ll_continue_compilation() no longer give obscure infinite loops when stdout is captured by py.test. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:30:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:30:59 +0200 (CEST) Subject: [pypy-svn] r54187 - pypy/branch/oo-jit/pypy/rpython Message-ID: <20080428173059.0EA051683D8@codespeak.net> Author: arigo Date: Mon Apr 28 19:30:59 2008 New Revision: 54187 Added: pypy/branch/oo-jit/pypy/rpython/llinterp.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/llinterp.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/llinterp.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53058 | arigo | 2008-03-28 17:55:59 +0100 (Fri, 28 Mar 2008) | 2 lines Use a single "jit_marker" operation for all jit-oriented markers. ------------------------------------------------------------------------ r52784 | arigo | 2008-03-20 18:34:24 +0100 (Thu, 20 Mar 2008) | 6 lines (cfbolz, arigo) Make all the 'tryfold' operations directly runnable too, for example all ovf-checking arithmetic. (done by moving their implementation from llinterp.py to opimpl.py) ------------------------------------------------------------------------ r52499 | arigo | 2008-03-14 14:57:29 +0100 (Fri, 14 Mar 2008) | 2 lines test_hp_tlr passes :-) ------------------------------------------------------------------------ r52426 | arigo | 2008-03-12 18:23:39 +0100 (Wed, 12 Mar 2008) | 7 lines A second test and the code to make it pass. It introduces green vars and it's a real interpreter over a bytecode with loop support. Quiz: in this bytecode, what is the following function doing? 'ISRDD{ISR%?SDD*}S' ------------------------------------------------------------------------ r52401 | arigo | 2008-03-11 22:29:33 +0100 (Tue, 11 Mar 2008) | 7 lines An oversight in the jit-refactoring.txt: after the fallback interpreter finishes we need to pass new values for the red=(..) and green=(..) variables of jit_merge_point(). Solved by splitting the portal graph in three graphs, the middle one being a wrapper that catches a ContinueRunningNormally exception carrying the new values. ------------------------------------------------------------------------ r52362 | arigo | 2008-03-10 18:56:38 +0100 (Mon, 10 Mar 2008) | 2 lines In-progress. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52212 | arigo | 2008-03-06 13:05:13 +0100 (Thu, 06 Mar 2008) | 2 lines Avoids an obscure way to hide bugs. ------------------------------------------------------------------------ r52083 | arigo | 2008-03-03 11:18:23 +0100 (Mon, 03 Mar 2008) | 3 lines Move the special-casing of ComputedIntSymbolic into opimpl.py. Allows the llop.int_xxx() operations to operate on them. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:04 +0200 (CEST) Subject: [pypy-svn] r54188 - pypy/branch/oo-jit/pypy/objspace/std Message-ID: <20080428173104.609E31683D7@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:03 2008 New Revision: 54188 Added: pypy/branch/oo-jit/pypy/objspace/std/intobject.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/objspace/std/intobject.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/objspace/std/intobject.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52935 | arigo | 2008-03-25 19:13:59 +0100 (Tue, 25 Mar 2008) | 2 lines Sprinkle some _immutable_ hints in the stdobjspace. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:07 +0200 (CEST) Subject: [pypy-svn] r54189 - pypy/branch/oo-jit/pypy/objspace/std Message-ID: <20080428173107.61C9A1683DC@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:06 2008 New Revision: 54189 Added: pypy/branch/oo-jit/pypy/objspace/std/floatobject.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/objspace/std/floatobject.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/objspace/std/floatobject.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52935 | arigo | 2008-03-25 19:13:59 +0100 (Tue, 25 Mar 2008) | 2 lines Sprinkle some _immutable_ hints in the stdobjspace. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:11 +0200 (CEST) Subject: [pypy-svn] r54190 - pypy/branch/oo-jit/pypy/objspace/std Message-ID: <20080428173111.A288C1683DB@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:10 2008 New Revision: 54190 Added: pypy/branch/oo-jit/pypy/objspace/std/stringobject.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/objspace/std/stringobject.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/objspace/std/stringobject.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52935 | arigo | 2008-03-25 19:13:59 +0100 (Tue, 25 Mar 2008) | 2 lines Sprinkle some _immutable_ hints in the stdobjspace. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:15 +0200 (CEST) Subject: [pypy-svn] r54191 - pypy/branch/oo-jit/pypy/objspace/std Message-ID: <20080428173115.A70FF1683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:14 2008 New Revision: 54191 Added: pypy/branch/oo-jit/pypy/objspace/std/unicodeobject.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/objspace/std/unicodeobject.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/objspace/std/unicodeobject.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52935 | arigo | 2008-03-25 19:13:59 +0100 (Tue, 25 Mar 2008) | 2 lines Sprinkle some _immutable_ hints in the stdobjspace. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:19 +0200 (CEST) Subject: [pypy-svn] r54192 - pypy/branch/oo-jit/pypy/objspace/flow Message-ID: <20080428173119.94C611683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:17 2008 New Revision: 54192 Added: pypy/branch/oo-jit/pypy/objspace/flow/objspace.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/objspace/flow/objspace.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/objspace/flow/objspace.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52524 | arigo | 2008-03-14 18:56:27 +0100 (Fri, 14 Mar 2008) | 3 lines Experimental: this removes the unexpected difference the flow object space makes for constant-folding between 'i += 1' and 'i = i + 1'. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:23 +0200 (CEST) Subject: [pypy-svn] r54193 - pypy/branch/oo-jit/pypy/jit/timeshifter Message-ID: <20080428173123.332301683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:22 2008 New Revision: 54193 Added: pypy/branch/oo-jit/pypy/jit/timeshifter/exception.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/jit/timeshifter/exception.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/jit/timeshifter/exception.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53193 | arigo | 2008-03-31 10:33:07 +0200 (Mon, 31 Mar 2008) | 4 lines Now that we removed the 'ptrkind' argument to the genop_ptr_*() methods, we don't need them any more at all: they can be handled by genop1() and genop2(), as they originally were. Kill kill! ------------------------------------------------------------------------ r53111 | cfbolz | 2008-03-29 21:25:14 +0100 (Sat, 29 Mar 2008) | 2 lines another loose end ------------------------------------------------------------------------ r53109 | cfbolz | 2008-03-29 20:53:43 +0100 (Sat, 29 Mar 2008) | 3 lines remove most uses of kind tokens in the codegen interface, since it didn't really help the backend. Probably small amounts of breakage left. ------------------------------------------------------------------------ r53077 | antocuni | 2008-03-29 10:58:05 +0100 (Sat, 29 Mar 2008) | 3 lines test_known_nonzero pass for ootype ------------------------------------------------------------------------ r52895 | antocuni | 2008-03-25 10:57:25 +0100 (Tue, 25 Mar 2008) | 3 lines finish porting of exception.py to ootype. Three more tests pass ------------------------------------------------------------------------ r52778 | antocuni | 2008-03-20 16:09:28 +0100 (Thu, 20 Mar 2008) | 3 lines more refactoring towards a working rainbow for ootype ------------------------------------------------------------------------ r52409 | arigo | 2008-03-12 12:11:54 +0100 (Wed, 12 Mar 2008) | 3 lines Enough of the fallback interpreter to support the current test (which does not pass yet for other reasons). ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51237 | cfbolz | 2008-02-04 10:31:20 +0100 (Mon, 04 Feb 2008) | 2 lines clean up the Pseudo* stuff ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:27 +0200 (CEST) Subject: [pypy-svn] r54194 - pypy/branch/oo-jit/pypy/jit/hintannotator Message-ID: <20080428173127.61BE71683DC@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:26 2008 New Revision: 54194 Added: pypy/branch/oo-jit/pypy/jit/hintannotator/bookkeeper.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/jit/hintannotator/bookkeeper.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/jit/hintannotator/bookkeeper.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52779 | arigo | 2008-03-20 16:25:56 +0100 (Thu, 20 Mar 2008) | 4 lines Record the causes for SomeLLAbstractVariables and print them in the common error message "hint %s makes no sense on %s". ------------------------------------------------------------------------ r52735 | cfbolz | 2008-03-19 19:52:38 +0100 (Wed, 19 Mar 2008) | 5 lines (cfbolz, arigo): move the impurity analyzer to translator/backendopt. add tests for it. fix a bug. Note to Antonio: needs a bit more work before it can be useful on ootype :-) ------------------------------------------------------------------------ r52609 | arigo | 2008-03-16 17:13:43 +0100 (Sun, 16 Mar 2008) | 2 lines Metacall stubs. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:32 +0200 (CEST) Subject: [pypy-svn] r54195 - pypy/branch/oo-jit/pypy/translator/js Message-ID: <20080428173132.E05C81683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:30 2008 New Revision: 54195 Added: pypy/branch/oo-jit/pypy/translator/js/opcodes.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/js/opcodes.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/js/opcodes.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52955 | antocuni | 2008-03-26 11:28:16 +0100 (Wed, 26 Mar 2008) | 6 lines introduce a new opcode ooisnull, in addition to oononnull. This is needed by the rainbow interpreter to correctly emit learn_nonzeroness; moreover, the CLI backend can translate it a bit faster than oononnull+negation ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:36 +0200 (CEST) Subject: [pypy-svn] r54196 - pypy/branch/oo-jit/pypy/translator/cli Message-ID: <20080428173136.13C731683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:35 2008 New Revision: 54196 Added: pypy/branch/oo-jit/pypy/translator/cli/opcodes.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/cli/opcodes.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52955 | antocuni | 2008-03-26 11:28:16 +0100 (Wed, 26 Mar 2008) | 6 lines introduce a new opcode ooisnull, in addition to oononnull. This is needed by the rainbow interpreter to correctly emit learn_nonzeroness; moreover, the CLI backend can translate it a bit faster than oononnull+negation ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:40 +0200 (CEST) Subject: [pypy-svn] r54197 - pypy/branch/oo-jit/pypy/translator/c Message-ID: <20080428173140.33E9C1683DC@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:38 2008 New Revision: 54197 Added: pypy/branch/oo-jit/pypy/translator/c/funcgen.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/c/funcgen.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/c/funcgen.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53058 | arigo | 2008-03-28 17:55:59 +0100 (Fri, 28 Mar 2008) | 2 lines Use a single "jit_marker" operation for all jit-oriented markers. ------------------------------------------------------------------------ r52792 | arigo | 2008-03-20 21:54:07 +0100 (Thu, 20 Mar 2008) | 3 lines Support more types in debug_print and don't crash on the remaining unsupported types. ------------------------------------------------------------------------ r52728 | cfbolz | 2008-03-19 16:51:29 +0100 (Wed, 19 Mar 2008) | 2 lines (cfbolz, arigo): Ignore the jit merge_point hint in normal code ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:44 +0200 (CEST) Subject: [pypy-svn] r54198 - pypy/branch/oo-jit/pypy/translator/jvm Message-ID: <20080428173144.9B50E1683DB@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:43 2008 New Revision: 54198 Added: pypy/branch/oo-jit/pypy/translator/jvm/opcodes.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/jvm/opcodes.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/jvm/opcodes.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52955 | antocuni | 2008-03-26 11:28:16 +0100 (Wed, 26 Mar 2008) | 6 lines introduce a new opcode ooisnull, in addition to oononnull. This is needed by the rainbow interpreter to correctly emit learn_nonzeroness; moreover, the CLI backend can translate it a bit faster than oononnull+negation ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:48 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:48 +0200 (CEST) Subject: [pypy-svn] r54199 - pypy/branch/oo-jit/pypy/translator/goal Message-ID: <20080428173148.EF2F41683DB@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:48 2008 New Revision: 54199 Added: pypy/branch/oo-jit/pypy/translator/goal/translate.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/goal/translate.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/goal/translate.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r52080 | cfbolz | 2008-03-03 00:32:19 +0100 (Mon, 03 Mar 2008) | 3 lines fix the driver and translate.py to use the rainbow interpreter instead of the timeshifter ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:52 +0200 (CEST) Subject: [pypy-svn] r54200 - pypy/branch/oo-jit/pypy/translator/goal Message-ID: <20080428173152.77FC01683DA@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:51 2008 New Revision: 54200 Added: pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/goal/targetpypystandalone.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53100 | arigo | 2008-03-29 17:59:40 +0100 (Sat, 29 Mar 2008) | 2 lines Translation fixes and typos. ------------------------------------------------------------------------ r53098 | arigo | 2008-03-29 17:15:09 +0100 (Sat, 29 Mar 2008) | 3 lines Try to give a --jit option to tune the jit when pypy-c starts up. A bit ad-hoc and undocumented for now. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:56 +0200 (CEST) Subject: [pypy-svn] r54201 - pypy/branch/oo-jit/pypy/translator/backendopt Message-ID: <20080428173156.3FE6D1683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:55 2008 New Revision: 54201 Added: pypy/branch/oo-jit/pypy/translator/backendopt/malloc.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/translator/backendopt/malloc.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/translator/backendopt/malloc.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52955 | antocuni | 2008-03-26 11:28:16 +0100 (Wed, 26 Mar 2008) | 6 lines introduce a new opcode ooisnull, in addition to oononnull. This is needed by the rainbow interpreter to correctly emit learn_nonzeroness; moreover, the CLI backend can translate it a bit faster than oononnull+negation ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:31:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:31:59 +0200 (CEST) Subject: [pypy-svn] r54202 - pypy/branch/oo-jit/pypy/rpython/lltypesystem Message-ID: <20080428173159.AB99E1683DA@codespeak.net> Author: arigo Date: Mon Apr 28 19:31:58 2008 New Revision: 54202 Added: pypy/branch/oo-jit/pypy/rpython/lltypesystem/llmemory.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/lltypesystem/llmemory.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/llmemory.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53490 | fijal | 2008-04-07 02:28:07 +0200 (Mon, 07 Apr 2008) | 2 lines Port address.float[] change from trunk ------------------------------------------------------------------------ r52499 | arigo | 2008-03-14 14:57:29 +0100 (Fri, 14 Mar 2008) | 2 lines test_hp_tlr passes :-) ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:04 +0200 (CEST) Subject: [pypy-svn] r54203 - pypy/branch/oo-jit/pypy/rpython/lltypesystem Message-ID: <20080428173204.46CE81683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:03 2008 New Revision: 54203 Added: pypy/branch/oo-jit/pypy/rpython/lltypesystem/lltype.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/lltypesystem/lltype.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lltype.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53280 | antocuni | 2008-04-03 15:09:01 +0200 (Thu, 03 Apr 2008) | 10 lines - teach ImpurityAnalizer how to check if calls to external methods are pure - mark all methods of ootype.String and ootype.Unicode as pure - rewrite test_plus_minus to use an RPython string instead of a lowlevel string, so that it can work also with ootype - after all of this, test_plus_minus passes :-) ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:08 +0200 (CEST) Subject: [pypy-svn] r54204 - pypy/branch/oo-jit/pypy/rpython/lltypesystem Message-ID: <20080428173208.9F7F71683D9@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:07 2008 New Revision: 54204 Added: pypy/branch/oo-jit/pypy/rpython/lltypesystem/lloperation.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/lltypesystem/lloperation.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/lloperation.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53655 | antocuni | 2008-04-10 15:03:22 +0200 (Thu, 10 Apr 2008) | 3 lines teach backendopt how to constfold oogetfield ------------------------------------------------------------------------ r53538 | arigo | 2008-04-07 20:07:39 +0200 (Mon, 07 Apr 2008) | 2 lines Drop the exception path if the operation cannot raise. ------------------------------------------------------------------------ r53058 | arigo | 2008-03-28 17:55:59 +0100 (Fri, 28 Mar 2008) | 2 lines Use a single "jit_marker" operation for all jit-oriented markers. ------------------------------------------------------------------------ r53057 | antocuni | 2008-03-28 17:53:32 +0100 (Fri, 28 Mar 2008) | 4 lines annotation & rtyping of the new type ootype.Object and the two operations cast_to_object and cast_from_object. ------------------------------------------------------------------------ r52955 | antocuni | 2008-03-26 11:28:16 +0100 (Wed, 26 Mar 2008) | 6 lines introduce a new opcode ooisnull, in addition to oononnull. This is needed by the rainbow interpreter to correctly emit learn_nonzeroness; moreover, the CLI backend can translate it a bit faster than oononnull+negation ------------------------------------------------------------------------ r52784 | arigo | 2008-03-20 18:34:24 +0100 (Thu, 20 Mar 2008) | 6 lines (cfbolz, arigo) Make all the 'tryfold' operations directly runnable too, for example all ovf-checking arithmetic. (done by moving their implementation from llinterp.py to opimpl.py) ------------------------------------------------------------------------ r52735 | cfbolz | 2008-03-19 19:52:38 +0100 (Wed, 19 Mar 2008) | 5 lines (cfbolz, arigo): move the impurity analyzer to translator/backendopt. add tests for it. fix a bug. Note to Antonio: needs a bit more work before it can be useful on ootype :-) ------------------------------------------------------------------------ r52407 | arigo | 2008-03-12 10:56:57 +0100 (Wed, 12 Mar 2008) | 3 lines Start the fallback interpreter. Also share more code between dump.py and interpreter.py. ------------------------------------------------------------------------ r52362 | arigo | 2008-03-10 18:56:38 +0100 (Mon, 10 Mar 2008) | 2 lines In-progress. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:12 +0200 (CEST) Subject: [pypy-svn] r54205 - pypy/branch/oo-jit/pypy/rpython/test Message-ID: <20080428173212.3A5E51683DC@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:10 2008 New Revision: 54205 Added: pypy/branch/oo-jit/pypy/rpython/test/test_rlist.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/test/test_rlist.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/test/test_rlist.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53099 | arigo | 2008-03-29 17:59:29 +0100 (Sat, 29 Mar 2008) | 2 lines Quick workaround for an rtyper crash in valid code. ------------------------------------------------------------------------ r52520 | arigo | 2008-03-14 18:00:44 +0100 (Fri, 14 Mar 2008) | 4 lines Test and a simple fix for calling list() on a list and then mutating the result to make the items more general (used to cause a badly-typed called to ll_copy()). ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:16 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:16 +0200 (CEST) Subject: [pypy-svn] r54206 - pypy/branch/oo-jit/pypy/rpython/ootypesystem Message-ID: <20080428173216.439D91683D9@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:15 2008 New Revision: 54206 Added: pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rootype.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53076 | antocuni | 2008-03-29 10:46:18 +0100 (Sat, 29 Mar 2008) | 3 lines make llhelper() working also with ootype ------------------------------------------------------------------------ r53057 | antocuni | 2008-03-28 17:53:32 +0100 (Fri, 28 Mar 2008) | 4 lines annotation & rtyping of the new type ootype.Object and the two operations cast_to_object and cast_from_object. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:19 +0200 (CEST) Subject: [pypy-svn] r54207 - pypy/branch/oo-jit/pypy/rpython/ootypesystem Message-ID: <20080428173219.E54B21683DF@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:19 2008 New Revision: 54207 Added: pypy/branch/oo-jit/pypy/rpython/ootypesystem/rclass.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rclass.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rclass.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53655 | antocuni | 2008-04-10 15:03:22 +0200 (Thu, 10 Apr 2008) | 3 lines teach backendopt how to constfold oogetfield ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:23 +0200 (CEST) Subject: [pypy-svn] r54208 - pypy/branch/oo-jit/pypy/rpython/ootypesystem Message-ID: <20080428173223.B56E91683E2@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:23 2008 New Revision: 54208 Added: pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rbuiltin.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53057 | antocuni | 2008-03-28 17:53:32 +0100 (Fri, 28 Mar 2008) | 4 lines annotation & rtyping of the new type ootype.Object and the two operations cast_to_object and cast_from_object. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:27 +0200 (CEST) Subject: [pypy-svn] r54209 - pypy/branch/oo-jit/pypy/rpython/ootypesystem Message-ID: <20080428173227.B881A1683D9@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:27 2008 New Revision: 54209 Added: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ootype.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53870 | antocuni | 2008-04-19 15:43:06 +0200 (Sat, 19 Apr 2008) | 3 lines add support for vdicts to ootype. test_vdict passes ------------------------------------------------------------------------ r53650 | antocuni | 2008-04-10 11:14:36 +0200 (Thu, 10 Apr 2008) | 3 lines add support to call ooidentityhash on ootype.Object values ------------------------------------------------------------------------ r53626 | antocuni | 2008-04-09 20:43:13 +0200 (Wed, 09 Apr 2008) | 3 lines a failing test and the corresponding fix ------------------------------------------------------------------------ r53329 | antocuni | 2008-04-04 14:52:46 +0200 (Fri, 04 Apr 2008) | 3 lines more passing tests ------------------------------------------------------------------------ r53280 | antocuni | 2008-04-03 15:09:01 +0200 (Thu, 03 Apr 2008) | 10 lines - teach ImpurityAnalizer how to check if calls to external methods are pure - mark all methods of ootype.String and ootype.Unicode as pure - rewrite test_plus_minus to use an RPython string instead of a lowlevel string, so that it can work also with ootype - after all of this, test_plus_minus passes :-) ------------------------------------------------------------------------ r53232 | antocuni | 2008-04-01 16:38:05 +0200 (Tue, 01 Apr 2008) | 3 lines port oopspec and vlist to ootype. First test passes ------------------------------------------------------------------------ r53226 | antocuni | 2008-04-01 10:15:23 +0200 (Tue, 01 Apr 2008) | 4 lines attach the name of the method to the _bound_meth object (only for builtin types so far) ------------------------------------------------------------------------ r53209 | antocuni | 2008-03-31 21:05:44 +0200 (Mon, 31 Mar 2008) | 5 lines add a way to fish the class of a method given an ootype.Meth type (only works for BuiltinADTType so far) ------------------------------------------------------------------------ r53035 | antocuni | 2008-03-28 10:06:14 +0100 (Fri, 28 Mar 2008) | 5 lines introduce a new type ootype.Object, which every non-primitive type can be converted to. Backends can be easily map it to System.Object or java.lang.Object etc. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:31 +0200 (CEST) Subject: [pypy-svn] r54210 - pypy/branch/oo-jit/pypy/rpython/ootypesystem Message-ID: <20080428173231.C052F1683E3@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:31 2008 New Revision: 54210 Added: pypy/branch/oo-jit/pypy/rpython/ootypesystem/rtuple.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rtuple.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtuple.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53969 | antocuni | 2008-04-21 12:40:01 +0200 (Mon, 21 Apr 2008) | 7 lines - implement materialize() for InstanceTypeDesc - add the relevant hints to ootypesystem.tupletype - test_compile_time_const_tuple passes! ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:38 +0200 (CEST) Subject: [pypy-svn] r54211 - pypy/branch/oo-jit/pypy/objspace/flow/test Message-ID: <20080428173238.1FF471683D3@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:37 2008 New Revision: 54211 Added: pypy/branch/oo-jit/pypy/objspace/flow/test/test_objspace.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/objspace/flow/test/test_objspace.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/objspace/flow/test/test_objspace.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52525 | arigo | 2008-03-14 19:06:12 +0100 (Fri, 14 Mar 2008) | 2 lines Report this minor problem as a skipped test. ------------------------------------------------------------------------ r52524 | arigo | 2008-03-14 18:56:27 +0100 (Fri, 14 Mar 2008) | 3 lines Experimental: this removes the unexpected difference the flow object space makes for constant-folding between 'i += 1' and 'i = i + 1'. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:44 +0200 (CEST) Subject: [pypy-svn] r54212 - pypy/branch/oo-jit/pypy/jit/codegen/test Message-ID: <20080428173244.CF09C1683DA@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:44 2008 New Revision: 54212 Added: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/jit/codegen/test/rgenop_tests.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53589 | arigo | 2008-04-08 17:57:58 +0200 (Tue, 08 Apr 2008) | 4 lines Don't return the input list directly as a result of get_frame_info(), in case the caller continues to mutate the list. ------------------------------------------------------------------------ r53542 | fijal | 2008-04-07 21:24:23 +0200 (Mon, 07 Apr 2008) | 2 lines cast_float_to_int (raising) + check ------------------------------------------------------------------------ r53505 | fijal | 2008-04-07 08:15:30 +0200 (Mon, 07 Apr 2008) | 2 lines Adapt a test. ------------------------------------------------------------------------ r53488 | fijal | 2008-04-07 02:24:20 +0200 (Mon, 07 Apr 2008) | 2 lines Test for read_frame_place for floats ------------------------------------------------------------------------ r53487 | fijal | 2008-04-07 02:14:36 +0200 (Mon, 07 Apr 2008) | 3 lines * in-progress test for frame_place_read and floats * isolate does not like printing at all :( ------------------------------------------------------------------------ r53482 | fijal | 2008-04-06 21:42:07 +0200 (Sun, 06 Apr 2008) | 2 lines Simplify the test ------------------------------------------------------------------------ r53481 | fijal | 2008-04-06 21:40:20 +0200 (Sun, 06 Apr 2008) | 2 lines A test pointing out that there is something wrong with genop_call for floats. ------------------------------------------------------------------------ r53477 | fijal | 2008-04-06 20:24:01 +0200 (Sun, 06 Apr 2008) | 2 lines A test that might showcase lack of address.float[0] ------------------------------------------------------------------------ r53414 | fijal | 2008-04-06 03:20:20 +0200 (Sun, 06 Apr 2008) | 2 lines A test for float frame_place_write ------------------------------------------------------------------------ r53395 | fijal | 2008-04-05 18:48:55 +0200 (Sat, 05 Apr 2008) | 3 lines Grrrr, didn't check that in yesterday. support for frame reading + tests ------------------------------------------------------------------------ r53374 | fijal | 2008-04-05 05:36:06 +0200 (Sat, 05 Apr 2008) | 2 lines add a new test for interior access of float stuff ------------------------------------------------------------------------ r53369 | fijal | 2008-04-05 04:30:41 +0200 (Sat, 05 Apr 2008) | 2 lines Add a test for field access ------------------------------------------------------------------------ r53356 | fijal | 2008-04-04 21:14:26 +0200 (Fri, 04 Apr 2008) | 2 lines make tests more verbose - setarrayitem with constant ------------------------------------------------------------------------ r53352 | fijal | 2008-04-04 20:33:04 +0200 (Fri, 04 Apr 2008) | 2 lines test for array of floats (passes on llgraph backend) ------------------------------------------------------------------------ r53274 | fijal | 2008-04-03 08:33:41 +0200 (Thu, 03 Apr 2008) | 2 lines test same_as, just because (passes) ------------------------------------------------------------------------ r53211 | fijal | 2008-03-31 21:57:02 +0200 (Mon, 31 Mar 2008) | 2 lines add a simple float loop ------------------------------------------------------------------------ r53193 | arigo | 2008-03-31 10:33:07 +0200 (Mon, 31 Mar 2008) | 4 lines Now that we removed the 'ptrkind' argument to the genop_ptr_*() methods, we don't need them any more at all: they can be handled by genop1() and genop2(), as they originally were. Kill kill! ------------------------------------------------------------------------ r53176 | fijal | 2008-03-31 03:22:18 +0200 (Mon, 31 Mar 2008) | 2 lines Yay! First test for float passes. ------------------------------------------------------------------------ r53154 | fijal | 2008-03-30 19:57:21 +0200 (Sun, 30 Mar 2008) | 2 lines Split direct and compile tests (rest of backend will follow) ------------------------------------------------------------------------ r53119 | cfbolz | 2008-03-30 00:56:48 +0100 (Sun, 30 Mar 2008) | 2 lines fix more tests ------------------------------------------------------------------------ r53109 | cfbolz | 2008-03-29 20:53:43 +0100 (Sat, 29 Mar 2008) | 3 lines remove most uses of kind tokens in the codegen interface, since it didn't really help the backend. Probably small amounts of breakage left. ------------------------------------------------------------------------ r53023 | fijal | 2008-03-27 21:18:25 +0100 (Thu, 27 Mar 2008) | 2 lines cpython2.5 tends to return unsigned 32 bit long. ------------------------------------------------------------------------ r52959 | arigo | 2008-03-26 17:08:56 +0100 (Wed, 26 Mar 2008) | 4 lines Add a test that tries to reproduce the calls issued by pypy-c-jit in a simple example. Look at this before attempting to improve the backends :-) ------------------------------------------------------------------------ r52724 | arigo | 2008-03-19 16:24:40 +0100 (Wed, 19 Mar 2008) | 2 lines Support writing the machine code of function with Void return type. ------------------------------------------------------------------------ r52722 | cfbolz | 2008-03-19 15:25:15 +0100 (Wed, 19 Mar 2008) | 3 lines (cfbolz, arigo) Tests and easy implementation of genconst_from_frame_var() in the 386 backend. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:49 +0200 (CEST) Subject: [pypy-svn] r54213 - pypy/branch/oo-jit/pypy/jit/codegen/llgraph Message-ID: <20080428173249.5B1EB1683DB@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:48 2008 New Revision: 54213 Added: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/llimpl.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53978 | antocuni | 2008-04-21 19:26:23 +0200 (Mon, 21 Apr 2008) | 3 lines port test_portal to ootype, first tests pass ------------------------------------------------------------------------ r53651 | antocuni | 2008-04-10 11:22:27 +0200 (Thu, 10 Apr 2008) | 4 lines test_simple_indirect_call & co. pass. To compute the greenkey for static methods, we use their ooidentityhash ------------------------------------------------------------------------ r53588 | arigo | 2008-04-08 17:39:42 +0200 (Tue, 08 Apr 2008) | 2 lines Check index against negative values. ------------------------------------------------------------------------ r53257 | antocuni | 2008-04-02 19:03:36 +0200 (Wed, 02 Apr 2008) | 8 lines move the various test_degenerated_* to TestLLType, and write the equivalents for ootype. To make test_degenerated_at_return passing we need to erase the type of all instances to the most general superclass (ROOT excluded); I'm not sure this is 100% correct, but tests seem to pass. ------------------------------------------------------------------------ r53159 | antocuni | 2008-03-30 20:35:17 +0200 (Sun, 30 Mar 2008) | 3 lines fix test_graph2rgenop ------------------------------------------------------------------------ r53109 | cfbolz | 2008-03-29 20:53:43 +0100 (Sat, 29 Mar 2008) | 3 lines remove most uses of kind tokens in the codegen interface, since it didn't really help the backend. Probably small amounts of breakage left. ------------------------------------------------------------------------ r53068 | antocuni | 2008-03-28 21:09:18 +0100 (Fri, 28 Mar 2008) | 4 lines erase all non primitive types to ootype.Object instead of ootype.ROOT. Surprinsingly enough, all tests passes out of the box :-) ------------------------------------------------------------------------ r52940 | antocuni | 2008-03-25 20:58:44 +0100 (Tue, 25 Mar 2008) | 6 lines Implement InstanceTypeDesc & co., which share a lof of code with StructTypeDesc & co. test_struct_simple passes for ootype too. ------------------------------------------------------------------------ r52895 | antocuni | 2008-03-25 10:57:25 +0100 (Tue, 25 Mar 2008) | 3 lines finish porting of exception.py to ootype. Three more tests pass ------------------------------------------------------------------------ r52778 | antocuni | 2008-03-20 16:09:28 +0100 (Thu, 20 Mar 2008) | 3 lines more refactoring towards a working rainbow for ootype ------------------------------------------------------------------------ r52407 | arigo | 2008-03-12 10:56:57 +0100 (Wed, 12 Mar 2008) | 3 lines Start the fallback interpreter. Also share more code between dump.py and interpreter.py. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51917 | cfbolz | 2008-02-28 16:03:13 +0100 (Thu, 28 Feb 2008) | 2 lines oops. of course graphs can have no returnblock at all ------------------------------------------------------------------------ r51914 | cfbolz | 2008-02-28 14:55:59 +0100 (Thu, 28 Feb 2008) | 2 lines fix a problem with sharing blocks between flow graphs ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:53 +0200 (CEST) Subject: [pypy-svn] r54214 - pypy/branch/oo-jit/pypy/rpython/lltypesystem/test Message-ID: <20080428173253.BF4FC1683E3@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:53 2008 New Revision: 54214 Added: pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_lloperation.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_lloperation.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/test/test_lloperation.py revisions 51111 to 54176: ------------------------------------------------------------------------ r52784 | arigo | 2008-03-20 18:34:24 +0100 (Thu, 20 Mar 2008) | 6 lines (cfbolz, arigo) Make all the 'tryfold' operations directly runnable too, for example all ovf-checking arithmetic. (done by moving their implementation from llinterp.py to opimpl.py) ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:32:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:32:59 +0200 (CEST) Subject: [pypy-svn] r54215 - pypy/branch/oo-jit/pypy/jit/codegen/i386/test Message-ID: <20080428173259.911781683DA@codespeak.net> Author: arigo Date: Mon Apr 28 19:32:59 2008 New Revision: 54215 Added: pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_ts.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_ts.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_ts.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53108 | cfbolz | 2008-03-29 20:29:42 +0100 (Sat, 29 Mar 2008) | 2 lines skip non-ported tests ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:33:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:33:03 +0200 (CEST) Subject: [pypy-svn] r54216 - pypy/branch/oo-jit/pypy/jit/codegen/dump/test Message-ID: <20080428173303.6F7C31683DD@codespeak.net> Author: arigo Date: Mon Apr 28 19:33:02 2008 New Revision: 54216 Added: pypy/branch/oo-jit/pypy/jit/codegen/dump/test/test_rgenop.py.merge.tmp - copied, changed from r54176, pypy/branch/oo-jit/pypy/jit/codegen/dump/test/test_rgenop.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/jit-hotpath/pypy/jit/codegen/dump/test/test_rgenop.py revisions 51111 to 54176: ------------------------------------------------------------------------ r53108 | cfbolz | 2008-03-29 20:29:42 +0100 (Sat, 29 Mar 2008) | 2 lines skip non-ported tests ------------------------------------------------------------------------ r52724 | arigo | 2008-03-19 16:24:40 +0100 (Wed, 19 Mar 2008) | 2 lines Support writing the machine code of function with Void return type. ------------------------------------------------------------------------ r52360 | arigo | 2008-03-10 17:26:12 +0100 (Mon, 10 Mar 2008) | 8 lines A branch off the jit-refactoring branch to start playing with the hotpath approach described in jit-refactoring-plan.txt. This is all experimental. Some of the changes in this branch might be easy to merge back if the approach seems to work, but some not. Anyway for now I will just go ahead and whack at code just to try things out without worrying about merging. ------------------------------------------------------------------------ r51125 | cfbolz | 2008-01-30 14:07:44 +0100 (Wed, 30 Jan 2008) | 2 lines a branch for the rainbow interpreter refactoring ------------------------------------------------------------------------ From arigo at codespeak.net Mon Apr 28 19:34:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 28 Apr 2008 19:34:50 +0200 (CEST) Subject: [pypy-svn] r54217 - in pypy/branch/oo-jit: demo/jit pypy/annotation pypy/annotation/test pypy/config pypy/interpreter pypy/jit pypy/jit/codegen pypy/jit/codegen/demo pypy/jit/codegen/dump pypy/jit/codegen/dump/test pypy/jit/codegen/i386 pypy/jit/codegen/i386/test pypy/jit/codegen/ia32 pypy/jit/codegen/llgraph pypy/jit/codegen/llgraph/test pypy/jit/codegen/llvm pypy/jit/codegen/ppc pypy/jit/codegen/test pypy/jit/hintannotator pypy/jit/hintannotator/test pypy/jit/rainbow pypy/jit/timeshifter pypy/jit/timeshifter/test pypy/jit/tl pypy/lang/prolog pypy/module/pypyjit pypy/objspace/flow pypy/objspace/flow/test pypy/objspace/std pypy/rlib pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/ootypesystem pypy/rpython/ootypesystem/test pypy/rpython/test pypy/tool pypy/translator pypy/translator/backendopt pypy/translator/backendopt/test pypy/translator/c pypy/translator/cli pypy/translator/goal pypy/translator/js pypy/translator/jvm Message-ID: <20080428173450.278CA1683D8@codespeak.net> Author: arigo Date: Mon Apr 28 19:34:48 2008 New Revision: 54217 Added: pypy/branch/oo-jit/demo/jit/ - copied from r54216, pypy/branch/jit-hotpath/demo/jit/ pypy/branch/oo-jit/pypy/annotation/binaryop.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/annotation/binaryop.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/builtin.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/annotation/builtin.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/description.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/annotation/description.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/model.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/annotation/model.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/test/ - copied from r54216, pypy/branch/jit-hotpath/pypy/annotation/test/ pypy/branch/oo-jit/pypy/config/translationoption.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/config/translationoption.py.merge.tmp pypy/branch/oo-jit/pypy/interpreter/pyopcode.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/interpreter/pyopcode.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/demo/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/demo/ pypy/branch/oo-jit/pypy/jit/codegen/detect_cpu.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/detect_cpu.py pypy/branch/oo-jit/pypy/jit/codegen/dump/rgenop.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/dump/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/dump/test/test_dump.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/dump/test/test_dump.py pypy/branch/oo-jit/pypy/jit/codegen/dump/test/test_rgenop.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/jit/codegen/dump/test/test_rgenop.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/emit_moves.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/emit_moves.py pypy/branch/oo-jit/pypy/jit/codegen/graph2rgenop.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/graph2rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/i386/operation.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/operation.py pypy/branch/oo-jit/pypy/jit/codegen/i386/regalloc.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/regalloc.py pypy/branch/oo-jit/pypy/jit/codegen/i386/rgenop.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/ri386.py pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386setup.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/ri386setup.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_auto_encoding.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_auto_encoding.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_exception.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_exception.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_portal.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_portal.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_promotion.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_promotion.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_tl.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_tl.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_tlc.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_tlc.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_tlr.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_tlr.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_ts.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_ts.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_virtualizable.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_virtualizable.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_vlist.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_genc_vlist.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_interp_ts.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_interp_ts.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_operation.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_operation.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_rgenop.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/i386/test/test_rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/ia32/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/ia32/ pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/llgraph/test/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/llgraph/test/ pypy/branch/oo-jit/pypy/jit/codegen/llvm/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/llvm/ pypy/branch/oo-jit/pypy/jit/codegen/model.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/model.py pypy/branch/oo-jit/pypy/jit/codegen/ppc/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/ppc/ pypy/branch/oo-jit/pypy/jit/codegen/support.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/support.py pypy/branch/oo-jit/pypy/jit/codegen/test/operation_tests.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/test/operation_tests.py pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/test/test_emit_moves.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/codegen/test/test_emit_moves.py pypy/branch/oo-jit/pypy/jit/conftest.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/conftest.py pypy/branch/oo-jit/pypy/jit/hintannotator/bookkeeper.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/jit/hintannotator/bookkeeper.py.merge.tmp pypy/branch/oo-jit/pypy/jit/hintannotator/hotpath.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/hintannotator/hotpath.py pypy/branch/oo-jit/pypy/jit/hintannotator/model.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/hintannotator/model.py pypy/branch/oo-jit/pypy/jit/hintannotator/policy.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/hintannotator/policy.py pypy/branch/oo-jit/pypy/jit/hintannotator/test/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/hintannotator/test/ pypy/branch/oo-jit/pypy/jit/rainbow/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/rainbow/ pypy/branch/oo-jit/pypy/jit/timeshifter/booleffect.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/booleffect.py pypy/branch/oo-jit/pypy/jit/timeshifter/exception.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/jit/timeshifter/exception.py.merge.tmp pypy/branch/oo-jit/pypy/jit/timeshifter/greenkey.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/greenkey.py pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/oop.py pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/rcontainer.py pypy/branch/oo-jit/pypy/jit/timeshifter/rdump.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/rdump.py pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py pypy/branch/oo-jit/pypy/jit/timeshifter/rvalue.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvalue.py pypy/branch/oo-jit/pypy/jit/timeshifter/rvirtualizable.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/rvirtualizable.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/support.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/support.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_greenkey.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_greenkey.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_rcontainer.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_rcontainer.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_rvalue.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/test/test_rvalue.py pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/vdict.py pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/jit/timeshifter/vlist.py pypy/branch/oo-jit/pypy/jit/tl/ - copied from r54216, pypy/branch/jit-hotpath/pypy/jit/tl/ pypy/branch/oo-jit/pypy/lang/prolog/ - copied from r54216, pypy/branch/jit-hotpath/pypy/lang/prolog/ pypy/branch/oo-jit/pypy/module/pypyjit/ - copied from r54216, pypy/branch/jit-hotpath/pypy/module/pypyjit/ pypy/branch/oo-jit/pypy/objspace/flow/objspace.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/objspace/flow/objspace.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/flow/test/test_objspace.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/objspace/flow/test/test_objspace.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/boolobject.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/objspace/std/boolobject.py pypy/branch/oo-jit/pypy/objspace/std/complexobject.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/objspace/std/complexobject.py pypy/branch/oo-jit/pypy/objspace/std/floatobject.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/objspace/std/floatobject.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/intobject.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/objspace/std/intobject.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/longobject.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/objspace/std/longobject.py pypy/branch/oo-jit/pypy/objspace/std/sliceobject.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/objspace/std/sliceobject.py pypy/branch/oo-jit/pypy/objspace/std/stringobject.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/objspace/std/stringobject.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/tupleobject.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/objspace/std/tupleobject.py pypy/branch/oo-jit/pypy/objspace/std/unicodeobject.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/objspace/std/unicodeobject.py.merge.tmp pypy/branch/oo-jit/pypy/rlib/debug.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rlib/debug.py pypy/branch/oo-jit/pypy/rlib/jit.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rlib/jit.py pypy/branch/oo-jit/pypy/rlib/objectmodel.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rlib/objectmodel.py.merge.tmp pypy/branch/oo-jit/pypy/rlib/test/test_jit.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rlib/test/test_jit.py pypy/branch/oo-jit/pypy/rpython/annlowlevel.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/annlowlevel.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/error.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/error.py pypy/branch/oo-jit/pypy/rpython/llinterp.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/llinterp.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/llmemory.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/lltypesystem/llmemory.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/lloperation.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/lltypesystem/lloperation.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/lltype.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/lltypesystem/lltype.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/opimpl.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/opimpl.py pypy/branch/oo-jit/pypy/rpython/lltypesystem/rpbc.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/lltypesystem/rpbc.py pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_lloperation.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_lloperation.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/ooopimpl.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/ooopimpl.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rclass.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rclass.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rpbc.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rpbc.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/rtuple.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/ootypesystem/rtuple.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rtupletype.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/rtupletype.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/ - copied from r54216, pypy/branch/jit-hotpath/pypy/rpython/ootypesystem/test/ pypy/branch/oo-jit/pypy/rpython/rpbc.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/rpbc.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/rtyper.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/rtyper.py pypy/branch/oo-jit/pypy/rpython/test/test_llann.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/test/test_llann.py pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/rpython/test/test_rclass.py pypy/branch/oo-jit/pypy/rpython/test/test_rlist.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/rpython/test/test_rlist.py.merge.tmp pypy/branch/oo-jit/pypy/tool/ansi_print.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/tool/ansi_print.py pypy/branch/oo-jit/pypy/translator/backendopt/constfold.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/backendopt/constfold.py pypy/branch/oo-jit/pypy/translator/backendopt/graphanalyze.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/backendopt/graphanalyze.py pypy/branch/oo-jit/pypy/translator/backendopt/malloc.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/backendopt/malloc.py.merge.tmp pypy/branch/oo-jit/pypy/translator/backendopt/test/test_constfold.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_constfold.py pypy/branch/oo-jit/pypy/translator/backendopt/test/test_graphanalyze.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/backendopt/test/test_graphanalyze.py pypy/branch/oo-jit/pypy/translator/c/funcgen.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/c/funcgen.py.merge.tmp pypy/branch/oo-jit/pypy/translator/cli/opcodes.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/cli/opcodes.py.merge.tmp pypy/branch/oo-jit/pypy/translator/driver.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/driver.py.merge.tmp pypy/branch/oo-jit/pypy/translator/exceptiontransform.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/exceptiontransform.py pypy/branch/oo-jit/pypy/translator/goal/richards.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/goal/richards.py pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py.merge.tmp pypy/branch/oo-jit/pypy/translator/goal/translate.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/goal/translate.py.merge.tmp pypy/branch/oo-jit/pypy/translator/js/opcodes.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/js/opcodes.py.merge.tmp pypy/branch/oo-jit/pypy/translator/jvm/opcodes.py - copied unchanged from r54216, pypy/branch/oo-jit/pypy/translator/jvm/opcodes.py.merge.tmp pypy/branch/oo-jit/pypy/translator/translator.py - copied unchanged from r54216, pypy/branch/jit-hotpath/pypy/translator/translator.py Removed: pypy/branch/oo-jit/pypy/annotation/binaryop.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/builtin.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/description.py.merge.tmp pypy/branch/oo-jit/pypy/annotation/model.py.merge.tmp pypy/branch/oo-jit/pypy/config/translationoption.py.merge.tmp pypy/branch/oo-jit/pypy/interpreter/pyopcode.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/dump/test/test_rgenop.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_ts.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py.merge.tmp pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py.merge.tmp pypy/branch/oo-jit/pypy/jit/hintannotator/bookkeeper.py.merge.tmp pypy/branch/oo-jit/pypy/jit/timeshifter/exception.py.merge.tmp pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_0tlc.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_1tl.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_exception.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_frontend.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_portal.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_promotion.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_tlr.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_vdict.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_virtualizable.py pypy/branch/oo-jit/pypy/jit/timeshifter/test/test_vlist.py pypy/branch/oo-jit/pypy/jit/timeshifter/transform.py pypy/branch/oo-jit/pypy/objspace/flow/objspace.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/flow/test/test_objspace.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/floatobject.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/intobject.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/stringobject.py.merge.tmp pypy/branch/oo-jit/pypy/objspace/std/unicodeobject.py.merge.tmp pypy/branch/oo-jit/pypy/rlib/objectmodel.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/annlowlevel.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/llinterp.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/llmemory.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/lloperation.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/lltype.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_lloperation.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rclass.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/ootypesystem/rtuple.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/rpbc.py.merge.tmp pypy/branch/oo-jit/pypy/rpython/test/test_rlist.py.merge.tmp pypy/branch/oo-jit/pypy/translator/backendopt/malloc.py.merge.tmp pypy/branch/oo-jit/pypy/translator/c/funcgen.py.merge.tmp pypy/branch/oo-jit/pypy/translator/cli/opcodes.py.merge.tmp pypy/branch/oo-jit/pypy/translator/driver.py.merge.tmp pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py.merge.tmp pypy/branch/oo-jit/pypy/translator/goal/translate.py.merge.tmp pypy/branch/oo-jit/pypy/translator/js/opcodes.py.merge.tmp pypy/branch/oo-jit/pypy/translator/jvm/opcodes.py.merge.tmp Log: (antocuni, arigo) Complete the merge of jit-hotpath into oo-jit, which is a fresh copy of the trunk. From antocuni at codespeak.net Tue Apr 29 12:01:24 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 29 Apr 2008 12:01:24 +0200 (CEST) Subject: [pypy-svn] r54224 - in pypy/branch/oo-jit/pypy/jit/codegen/cli: . test Message-ID: <20080429100124.CE20D16805F@codespeak.net> Author: antocuni Date: Tue Apr 29 12:01:24 2008 New Revision: 54224 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: split the tests into direct and compiled, as in rgenop_tests; lot of them are broken in strange ways Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Tue Apr 29 12:01:24 2008 @@ -18,6 +18,7 @@ cInt32 = classof(System.Int32) cBoolean = classof(System.Boolean) +cDouble = classof(System.Double) cObject = classof(System.Object) class SigToken: @@ -105,6 +106,27 @@ def __repr__(self): return "const=%s" % self.value + +class FloatConst(GenConst): + + def __init__(self, value): + self.value = value + + @specialize.arg(1) + def revealconst(self, T): + assert T is ootype.Float + if T is ootype.Float: + return self.value + + def getCliType(self): + return typeof(System.Double) + + def load(self, builder): + builder.il.Emit(OpCodes.Ldc_R8, self.value) + + def __repr__(self): + return "const=%s" % self.value + class BaseConst(GenConst): def _get_index(self, builder): @@ -161,7 +183,8 @@ def getobj(self): # XXX: should the conversion be done automatically? - return ootype.ooupcast(OBJECT, self.holder) + #return ootype.ooupcast(OBJECT, self.holder) + return self.holder def load(self, builder): holdertype = box(self.holder).GetType() @@ -197,6 +220,8 @@ return IntConst(llvalue) elif T is ootype.Bool: return IntConst(int(llvalue)) + elif T is ootype.Float: + return FloatConst(llvalue) elif T is llmemory.Address: assert llvalue is llmemory.NULL return zero_const @@ -234,6 +259,8 @@ return cInt32 elif T is ootype.Bool: return cBoolean + elif T is ootype.Float: + return cDouble elif isinstance(T, ootype.Instance): return cObject # XXX? else: Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Tue Apr 29 12:01:24 2008 @@ -1,69 +1,53 @@ import py from pypy.rpython.ootypesystem import ootype from pypy.jit.codegen.cli.rgenop import RCliGenOp -from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests, OOType +from pypy.jit.codegen.test.rgenop_tests import OOType +from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTestsDirect +from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTestsCompile from pypy.translator.cli.test.runtest import compile_function -class TestRCliGenop(AbstractRGenOpTests): +# for the individual tests see +# ====> ../../test/rgenop_tests.py + +class TestRCliGenopDirect(AbstractRGenOpTestsDirect): RGenOp = RCliGenOp T = OOType - # for the individual tests see - # ====> ../../test/rgenop_tests.py - - def getcompiled(self, fn, annotation, annotatorpolicy): - return compile_function(fn, annotation, - annotatorpolicy=annotatorpolicy, - nowrap=False) - - def cast(self, gv, nb_args): + def cast(self, gv, nb_args, RESULT='not used'): "NOT_RPYTHON" def fn(*args): return gv.getobj().func.Invoke(*args) return fn + cast_float = cast + cast_whatever = cast def directtesthelper(self, FUNCTYPE, func): py.test.skip('???') - def test_largedummy_compile(self): - py.test.skip('it works only if we increase .maxstack') + def test_cast_raising(self): + py.test.skip('fixme') def test_switch_direct(self): py.test.skip('no promotion/flexswitch for now please :-)') - def test_switch_compile(self): - py.test.skip('no promotion/flexswitch for now please :-)') - def test_large_switch_direct(self): py.test.skip('no promotion/flexswitch for now please :-)') - def test_large_switch_compile(self): - py.test.skip('no promotion/flexswitch for now please :-)') - def test_defaultonly_switch(self): py.test.skip('no promotion/flexswitch for now please :-)') def test_read_frame_var_direct(self): py.test.skip('fixme: add support for frames') - def test_read_frame_var_compile(self): - py.test.skip('fixme: add support for frames') - def test_write_frame_place_direct(self): py.test.skip('fixme: add support for frames') - def test_write_frame_place_compile(self): - py.test.skip('fixme: add support for frames') - def test_write_lots_of_frame_places_direct(self): py.test.skip('fixme: add support for frames') def test_read_frame_place_direct(self): py.test.skip('fixme: add support for frames') - - def test_read_frame_place_compile(self): - py.test.skip('fixme: add support for frames') - + def test_frame_vars_like_the_frontend_direct(self): py.test.skip('fixme: add support for frames') @@ -79,15 +63,9 @@ def test_ovfcheck_adder_direct(self): py.test.skip('fixme') - def test_ovfcheck_adder_compile(self): - py.test.skip('fixme') - def test_ovfcheck1_direct(self): py.test.skip('fixme') - def test_ovfcheck1_compile(self): - py.test.skip('fixme') - def test_ovfcheck2_direct(self): py.test.skip('fixme') @@ -99,3 +77,37 @@ def test_interior_access(self): py.test.skip('fixme') + + +class TestRCliGenopCompile(AbstractRGenOpTestsCompile): + RGenOp = RCliGenOp + T = OOType + + def getcompiled(self, fn, annotation, annotatorpolicy): + return compile_function(fn, annotation, + annotatorpolicy=annotatorpolicy, + nowrap=False) + + def test_largedummy_compile(self): + py.test.skip('it works only if we increase .maxstack') + + def test_switch_compile(self): + py.test.skip('no promotion/flexswitch for now please :-)') + + def test_large_switch_compile(self): + py.test.skip('no promotion/flexswitch for now please :-)') + + def test_read_frame_var_compile(self): + py.test.skip('fixme: add support for frames') + + def test_write_frame_place_compile(self): + py.test.skip('fixme: add support for frames') + + def test_read_frame_place_compile(self): + py.test.skip('fixme: add support for frames') + + def test_ovfcheck_adder_compile(self): + py.test.skip('fixme') + + def test_ovfcheck1_compile(self): + py.test.skip('fixme') From antocuni at codespeak.net Tue Apr 29 12:34:39 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 29 Apr 2008 12:34:39 +0200 (CEST) Subject: [pypy-svn] r54227 - pypy/branch/oo-jit/pypy/jit/rainbow Message-ID: <20080429103439.2F6A316805C@codespeak.net> Author: antocuni Date: Tue Apr 29 12:34:38 2008 New Revision: 54227 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Log: don't crash on abstract methods Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Tue Apr 29 12:34:38 2008 @@ -1820,9 +1820,10 @@ if methname in desc.methodcodes: break # we already filled the codes for this type _, meth = T._lookup(methname) - tsgraph = graph2tsgraph[meth.graph] - jitcode = self.get_jitcode(tsgraph) - desc.methodcodes[methname] = jitcode + if not getattr(meth, 'abstract', False): + tsgraph = graph2tsgraph[meth.graph] + jitcode = self.get_jitcode(tsgraph) + desc.methodcodes[methname] = jitcode class GraphTransformer(object): From antocuni at codespeak.net Tue Apr 29 12:35:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 29 Apr 2008 12:35:56 +0200 (CEST) Subject: [pypy-svn] r54228 - in pypy/branch/oo-jit/pypy: jit/codegen/cli jit/codegen/cli/test jit/codegen/llgraph/test jit/codegen/test translator/cli translator/cli/src Message-ID: <20080429103556.2587C16804C@codespeak.net> Author: antocuni Date: Tue Apr 29 12:35:55 2008 New Revision: 54228 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/llgraph/test/test_rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py pypy/branch/oo-jit/pypy/translator/cli/dotnet.py pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Log: skip or fix all the direct tests Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Tue Apr 29 12:35:55 2008 @@ -127,7 +127,8 @@ return None def emit(self): - self.gv_x.load(self.builder) + if self.gv_x is not None: + self.gv_x.load(self.builder) self.builder.il.Emit(OpCodes.Ret) class Call(Operation): Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Tue Apr 29 12:35:55 2008 @@ -255,7 +255,9 @@ @staticmethod @specialize.memo() def kindToken(T): - if T is ootype.Signed: + if T is ootype.Void: + return None + elif T is ootype.Signed: return cInt32 elif T is ootype.Bool: return cBoolean @@ -346,7 +348,7 @@ self.emit(op) return op.gv_res() - def genop_same_as(self, kindtoken, gv_x): + def genop_same_as(self, gv_x): op = ops.SameAs(self, gv_x) self.emit(op) return op.gv_res() @@ -402,7 +404,7 @@ myfunc = self.meth.CreateDelegate(self.delegatetype, consts) self.gv_entrypoint.holder.SetFunc(myfunc) - def enter_next_block(self, kinds, args_gv): + def enter_next_block(self, args_gv): for i in range(len(args_gv)): op = ops.SameAs(self, args_gv[i]) op.emit() Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Tue Apr 29 12:35:55 2008 @@ -27,6 +27,12 @@ def test_cast_raising(self): py.test.skip('fixme') + def test_float_adder(self): + py.test.skip('fixme') + + def test_float_loop_direct(self): + py.test.skip('fixme') + def test_switch_direct(self): py.test.skip('no promotion/flexswitch for now please :-)') @@ -39,6 +45,18 @@ def test_read_frame_var_direct(self): py.test.skip('fixme: add support for frames') + def test_read_frame_var_float_direct(self): + py.test.skip('fixme: add support for frames') + + def test_genconst_from_frame_var_direct(self): + py.test.skip('fixme: add support for frames') + + def test_write_frame_place_float_direct(self): + py.test.skip('fixme: add support for frames') + + def test_read_float_frame_place_direct(self): + py.test.skip('fixme: add support for frames') + def test_write_frame_place_direct(self): py.test.skip('fixme: add support for frames') Modified: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/llgraph/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/llgraph/test/test_rgenop.py Tue Apr 29 12:35:55 2008 @@ -31,7 +31,9 @@ class TestLLGraphRGenopDirect(BaseLLGraphRGenop, AbstractRGenOpTestsDirect): - pass + + def test_cast_raising(self): + py.test.skip('fixme') class TestLLGraphRGenopCompile(BaseLLGraphRGenop, AbstractRGenOpTestsCompile): pass Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Tue Apr 29 12:35:55 2008 @@ -22,6 +22,7 @@ FUNC100 = lltype.FuncType([lltype.Signed]*100, lltype.Signed) FLOATFUNC = lltype.FuncType([lltype.Float], lltype.Float) FUNCMIX = lltype.FuncType([lltype.Signed, lltype.Float], lltype.Float) + FUNCV = lltype.FuncType([lltype.Signed], lltype.Void) @staticmethod def Ptr(T): @@ -46,6 +47,7 @@ FUNC100 = ootype.StaticMethod([lltype.Signed]*100, lltype.Signed) FLOATFUNC = ootype.StaticMethod([lltype.Float], lltype.Float) FUNCMIX = ootype.StaticMethod([lltype.Signed, lltype.Float], lltype.Float) + FUNCV = ootype.StaticMethod([lltype.Signed], lltype.Void) @staticmethod def Ptr(T): @@ -1237,11 +1239,9 @@ assert res == 42 - - def test_cast_raising(self): rgenop = self.RGenOp() - FUNC = lltype.FuncType([lltype.Float], lltype.Signed) + FUNC = self.T.FLOATFUNC sigtoken = rgenop.sigToken(FUNC) builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, 'cast_raising') builder.start_writing() @@ -2565,8 +2565,7 @@ def test_void_return(self): # XXX minimal test only rgenop = self.RGenOp() - FUNCV = lltype.FuncType([lltype.Signed], lltype.Void) - sigtoken = rgenop.sigToken(FUNCV) + sigtoken = rgenop.sigToken(self.T.FUNCV) builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "nothing") builder.start_writing() builder.finish_and_return(sigtoken, None) Modified: pypy/branch/oo-jit/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/dotnet.py Tue Apr 29 12:35:55 2008 @@ -711,11 +711,14 @@ CLR._buildtree() known_delegates = { + ootype.StaticMethod([ootype.Signed, ootype.Float], ootype.Float): CLR.pypy.test.DelegateType_double_int_double, + ootype.StaticMethod([ootype.Float], ootype.Float): CLR.pypy.test.DelegateType_double__double_1, + ootype.StaticMethod([ootype.Signed], ootype.Void): CLR.pypy.test.DelegateType_void_int_1, ootype.StaticMethod([ootype.Signed], ootype.Signed): CLR.pypy.test.DelegateType_int__int_1, ootype.StaticMethod([ootype.Signed] * 2, ootype.Signed): CLR.pypy.test.DelegateType_int__int_2, ootype.StaticMethod([ootype.Signed] * 3, ootype.Signed): CLR.pypy.test.DelegateType_int__int_3, ootype.StaticMethod([ootype.Signed] * 5, ootype.Signed): CLR.pypy.test.DelegateType_int__int_5, - ootype.StaticMethod([ootype.Signed] * 27, ootype.Signed): CLR.pypy.test.DelegateType_int__int_27, + ootype.StaticMethod([ootype.Signed] * 27, ootype.Signed): CLR.pypy.test.DelegateType_int__int_27, ootype.StaticMethod([ootype.Signed] * 100, ootype.Signed): CLR.pypy.test.DelegateType_int__int_100 } Modified: pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Tue Apr 29 12:35:55 2008 @@ -82,6 +82,9 @@ } } + public delegate double DelegateType_double__double_1(double a); + public delegate double DelegateType_double_int_double(int a, double b); + public delegate void DelegateType_void_int_1(int a); public delegate int DelegateType_int__int_1(int a); public delegate int DelegateType_int__int_2(int a, int b); public delegate int DelegateType_int__int_3(int a, int b, int c); From antocuni at codespeak.net Tue Apr 29 13:15:31 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 29 Apr 2008 13:15:31 +0200 (CEST) Subject: [pypy-svn] r54232 - pypy/branch/oo-jit/pypy/jit/codegen/cli/test Message-ID: <20080429111531.15AEF16806D@codespeak.net> Author: antocuni Date: Tue Apr 29 13:15:30 2008 New Revision: 54232 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: skip some failing tests Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Tue Apr 29 13:15:30 2008 @@ -118,14 +118,24 @@ def test_read_frame_var_compile(self): py.test.skip('fixme: add support for frames') + def test_read_frame_float_var_compile(self): + py.test.skip('fixme: add support for frames') + def test_write_frame_place_compile(self): py.test.skip('fixme: add support for frames') def test_read_frame_place_compile(self): py.test.skip('fixme: add support for frames') + + def test_genconst_from_frame_var_compile(self): + py.test.skip('fixme: add support for frames') + def test_genconst_from_frame_float_var_compile(self): + py.test.skip('fixme: add support for frames') + def test_ovfcheck_adder_compile(self): py.test.skip('fixme') def test_ovfcheck1_compile(self): py.test.skip('fixme') + From fijal at codespeak.net Tue Apr 29 16:10:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 29 Apr 2008 16:10:08 +0200 (CEST) Subject: [pypy-svn] r54242 - in pypy/dist/pypy: config objspace/std objspace/std/test Message-ID: <20080429141008.E9CD91683DD@codespeak.net> Author: fijal Date: Tue Apr 29 16:10:08 2008 New Revision: 54242 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_tupleobject.py pypy/dist/pypy/objspace/std/tupleobject.py pypy/dist/pypy/objspace/std/tupletype.py Log: * Add optimized_comparison to faassen * Add multituple option * Rather failed experiment with multituple. Either are going to be deleted or will stay turned off, because it slows down things. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue Apr 29 16:10:08 2008 @@ -253,6 +253,9 @@ requires=[("objspace.std.withrangelist", False), ("objspace.name", "std"), ("objspace.std.withtproxy", False)]), + BoolOption("withmultituple", + "use tuples optimized for sizes", + default=False), BoolOption("withfastslice", "make list slicing lazy", default=False, @@ -306,6 +309,7 @@ # ("objspace.std.withfastslice", True), ("objspace.std.withprebuiltchar", True), ("objspace.std.optimized_int_add", True), + ("objspace.std.optimized_comparison_op", True), ("translation.list_comprehension_operations",True), ], cmdline="--allopts --faassen", negation=False), Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Tue Apr 29 16:10:08 2008 @@ -14,6 +14,7 @@ "withstrjoin" : ["strjoinobject.W_StringJoinObject"], "withmultidict" : ["dictmultiobject.W_DictMultiObject", "dictmultiobject.W_DictMultiIterObject"], + "withmultituple" : ["tuplemultiobject.W_TupleMultiObject"], "withmultilist" : ["listmultiobject.W_ListMultiObject"], "withrope" : ["ropeobject.W_RopeObject", "ropeobject.W_RopeIterObject"], @@ -64,6 +65,7 @@ from pypy.objspace.std import setobject from pypy.objspace.std import smallintobject from pypy.objspace.std import tupleobject + from pypy.objspace.std import tuplemultiobject from pypy.objspace.std import listobject from pypy.objspace.std import dictobject from pypy.objspace.std import dictmultiobject @@ -120,6 +122,7 @@ dictobject.W_DictIterObject: True, listobject.W_ListObject: True, stringobject.W_StringObject: True, + tupleobject.W_TupleObject: True, } for option, value in config.objspace.std: if option.startswith("with") and option in option_to_typename: @@ -139,6 +142,9 @@ if config.objspace.std.withrope: del self.typeorder[stringobject.W_StringObject] + if config.objspace.std.withmultituple: + del self.typeorder[tupleobject.W_TupleObject] + #check if we missed implementations from pypy.objspace.std.objspace import _registered_implementations for implcls in _registered_implementations: Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Tue Apr 29 16:10:08 2008 @@ -240,6 +240,13 @@ self.DictObjectCls = dictobject.W_DictObject assert self.DictObjectCls in self.model.typeorder + if self.config.objspace.std.withmultituple: + from pypy.objspace.std import tuplemultiobject + self.TupleObjectCls = tuplemultiobject.W_TupleMultiObject + else: + from pypy.objspace.std import tupleobject + self.TupleObjectCls = tupleobject.W_TupleObject + if not self.config.objspace.std.withrope: from pypy.objspace.std import stringobject self.StringObjectCls = stringobject.W_StringObject @@ -481,7 +488,7 @@ return r if isinstance(x, tuple): wrappeditems = [self.wrap(item) for item in list(x)] - return W_TupleObject(wrappeditems) + return self.newtuple(wrappeditems) if isinstance(x, list): wrappeditems = [self.wrap(item) for item in x] return self.newlist(wrappeditems) @@ -564,8 +571,9 @@ return W_LongObject.fromint(self, val) def newtuple(self, list_w): + from pypy.objspace.std.tupletype import wraptuple assert isinstance(list_w, list) - return W_TupleObject(list_w) + return wraptuple(self, list_w) def newlist(self, list_w): if self.config.objspace.std.withmultilist: @@ -630,8 +638,8 @@ allocate_instance._annspecialcase_ = "specialize:arg(1)" def unpacktuple(self, w_tuple, expected_length=-1): - assert isinstance(w_tuple, W_TupleObject) - t = w_tuple.wrappeditems + assert isinstance(w_tuple, self.TupleObjectCls) + t = w_tuple.getitems() if expected_length != -1 and expected_length != len(t): raise ValueError, "got a tuple of length %d instead of %d" % ( len(t), expected_length) Modified: pypy/dist/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_tupleobject.py Tue Apr 29 16:10:08 2008 @@ -2,8 +2,6 @@ from pypy.objspace.std.tupleobject import W_TupleObject from pypy.interpreter.error import OperationError - - class TestW_TupleObject: def test_is_true(self): @@ -234,6 +232,78 @@ class AppTestW_TupleObject: + def test_is_true(self): + assert not () + assert (5,) + assert (5,3) + + def test_len(self): + assert len(()) == 0 + assert len((5,)) == 1 + assert len((5,3,99,1,2,3,4,5,6)) == 9 + + def test_getitem(self): + assert (5,3)[0] == 5 + assert (5,3)[1] == 3 + assert (5,3)[-1] == 3 + assert (5,3)[-2] == 5 + raises(IndexError, "(5,3)[2]") + raises(IndexError, "(5,)[1]") + raises(IndexError, "()[0]") + + def test_iter(self): + t = (5,3,99) + i = iter(t) + assert i.next() == 5 + assert i.next() == 3 + assert i.next() == 99 + raises(StopIteration, i.next) + + def test_contains(self): + t = (5,3,99) + assert 5 in t + assert 99 in t + assert not 11 in t + assert not t in t + + def test_add(self): + t0 = () + t1 = (5,3,99) + assert t0 + t0 == t0 + assert t1 + t0 == t1 + assert t1 + t1 == (5,3,99,5,3,99) + + def test_mul(self): + assert () * 10 == () + assert (5,) * 3 == (5,5,5) + assert (5,2) * 2 == (5,2,5,2) + + def test_getslice(self): + assert (5,2,3)[1:2] == (2,) + + def test_eq(self): + t0 = () + t1 = (5,3,99) + t2 = (5,3,99) + t3 = (5,3,99,-1) + t4 = (5,3,9,1) + assert not t0 == t1 + assert t0 != t1 + assert t1 == t2 + assert t2 == t1 + assert t3 != t2 + assert not t3 == t2 + assert not t2 == t3 + assert t3 > t4 + assert t2 > t4 + assert t3 > t2 + assert t1 > t0 + assert t0 <= t0 + assert not t0 < t0 + assert t4 >= t0 + assert t3 >= t2 + assert t2 <= t3 + def test_hash(self): # check that hash behaves as in 2.4 for at least 31 bits assert hash(()) & 0x7fffffff == 0x35d373 @@ -242,3 +312,14 @@ def test_getnewargs(self): assert () .__getnewargs__() == ((),) + + def test_repr(self): + assert repr((1,)) == '(1,)' + assert repr(()) == '()' + assert repr((1,2,3)) == '(1, 2, 3)' + +class AppTestMultiTuple(AppTestW_TupleObject): + def setup_class(cls): + from pypy.conftest import gettestobjspace + cls.space = gettestobjspace(**{"objspace.std.withmultituple": True}) + Modified: pypy/dist/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/tupleobject.py Tue Apr 29 16:10:08 2008 @@ -19,6 +19,8 @@ items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] # XXX generic mixed types unwrap return tuple(items) + def getitems(self): + return self.wrappeditems registerimplementation(W_TupleObject) @@ -122,15 +124,15 @@ # No more items to compare -- compare sizes return space.newbool(len(items1) > len(items2)) -app = gateway.applevel(""" - def repr__Tuple(t): - if len(t) == 1: - return "(" + repr(t[0]) + ",)" - else: - return "(" + ", ".join([repr(x) for x in t]) + ')' -""", filename=__file__) - -repr__Tuple = app.interphook('repr__Tuple') +def repr__Tuple(space, w_tuple): + items = w_tuple.wrappeditems + # XXX this is quite innefficient, still better than calling + # it via applevel + if len(items) == 1: + return space.wrap("(" + space.str_w(space.repr(items[0])) + ",)") + return space.wrap("(" + + (", ".join([space.str_w(space.repr(item)) for item in items])) + + ")") def hash__Tuple(space, w_tuple): # this is the CPython 2.4 algorithm (changed from 2.3) @@ -148,5 +150,4 @@ def getnewargs__Tuple(space, w_tuple): return space.newtuple([W_TupleObject(w_tuple.wrappeditems)]) - register_all(vars()) Modified: pypy/dist/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupletype.py (original) +++ pypy/dist/pypy/objspace/std/tupletype.py Tue Apr 29 16:10:08 2008 @@ -1,6 +1,13 @@ from pypy.objspace.std.stdtypedef import * from pypy.interpreter.gateway import NoneNotWrapped +def wraptuple(space, list_w): + from pypy.objspace.std.tupleobject import W_TupleObject + if space.config.objspace.std.withmultituple: + from pypy.objspace.std.tuplemultiobject import W_TupleMultiObject + return W_TupleMultiObject(list_w) + return W_TupleObject(list_w) + def descr__new__(space, w_tupletype, w_sequence=NoneNotWrapped): from pypy.objspace.std.tupleobject import W_TupleObject if w_sequence is None: @@ -10,8 +17,8 @@ return w_sequence else: tuple_w = space.unpackiterable(w_sequence) - w_obj = space.allocate_instance(W_TupleObject, w_tupletype) - W_TupleObject.__init__(w_obj, tuple_w) + w_obj = space.allocate_instance(space.TupleObjectCls, w_tupletype) + space.TupleObjectCls.__init__(w_obj, tuple_w) return w_obj # ____________________________________________________________ From fijal at codespeak.net Tue Apr 29 16:40:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 29 Apr 2008 16:40:51 +0200 (CEST) Subject: [pypy-svn] r54244 - pypy/dist/pypy/objspace/std Message-ID: <20080429144051.869211683EC@codespeak.net> Author: fijal Date: Tue Apr 29 16:40:49 2008 New Revision: 54244 Added: pypy/dist/pypy/objspace/std/tuplemultiobject.py (contents, props changed) Log: Add forgotten tuplemultiobject Added: pypy/dist/pypy/objspace/std/tuplemultiobject.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/std/tuplemultiobject.py Tue Apr 29 16:40:49 2008 @@ -0,0 +1,360 @@ + +""" Multituple implementation +""" + +from pypy.objspace.std.objspace import * +from pypy.objspace.std.inttype import wrapint +from pypy.rlib.rarithmetic import intmask +from pypy.objspace.std.sliceobject import W_SliceObject +from pypy.interpreter import gateway + +class BaseTupleImplementation(object): + size = -1 # interface definition goes here + + def get(self, index): + raise NotImplementedError + + def getitems(self): + raise NotImplementedError + + def contains(self, space, w_obj): + raise NotImplementedError + + def eq(self, space, impl): + raise NotImplementedError + + def repr(self, space): + raise NotImplementedError + + def hash(self, space): + raise NotImplementedError + +class EmptyTupleImplementation(BaseTupleImplementation): + size = 0 + + def get(self, index): + raise IndexError + + def getitems(self): + return [] + + def contains(self, space, w_obj): + return space.w_False + + def eq(self, space, impl): + return space.w_True + + def repr(self, space): + return space.wrap("()") + + def hash(self, space): + return space.wrap(3527539) + +class SingleTupleImplementation(BaseTupleImplementation): + size = 1 + + def __init__(self, w_item): + self.w_item = w_item + + def get(self, index): + assert index == 0 + return self.w_item + + def getitems(self): + return [self.w_item] + + def contains(self, space, w_obj): + return space.eq(w_obj, self.w_item) + + def eq(self, space, impl): + assert isinstance(impl, SingleTupleImplementation) + return space.eq(self.w_item, impl.w_item) + + def repr(self, space): + return space.wrap("(" + space.str_w(space.repr(self.w_item)) + ",)") + + def hash(self, space): + mult = 1000003 + x = 0x345678 + y = space.int_w(space.hash(self.w_item)) + x = (x ^ y) * mult + mult += 82520 + x += 97531 + return space.wrap(intmask(x)) + +class DoubleTupleImplementation(BaseTupleImplementation): + size = 2 + + def __init__(self, w_item1, w_item2): + self.w_item1 = w_item1 + self.w_item2 = w_item2 + + def get(self, index): + assert index < 2 + if index == 1: + return self.w_item2 + return self.w_item1 + + def getitems(self): + return [self.w_item1, self.w_item2] + + def contains(self, space, w_obj): + return space.newbool(space.eq_w(self.w_item1, w_obj) or + space.eq_w(self.w_item2, w_obj)) + + def eq(self, space, impl): + assert isinstance(impl, DoubleTupleImplementation) + return space.newbool(space.eq_w(self.w_item1, impl.w_item1) and + space.eq_w(self.w_item2, impl.w_item2)) + + def repr(self, space): + return space.wrap("(" + space.str_w(space.repr(self.w_item1)) + ", " + + space.str_w(space.repr(self.w_item2)) + ")") + + def hash(self, space): + mult = 1000003 + x = 0x345678 + y = space.int_w(space.hash(self.w_item1)) + x = (x ^ y) * mult + mult += 82522 + y = space.int_w(space.hash(self.w_item2)) + x = (x ^ y) * mult + mult += 82520 + x += 97531 + return space.wrap(intmask(x)) + +class TripleTupleImplementation(BaseTupleImplementation): + size = 3 + + def __init__(self, w_item1, w_item2, w_item3): + self.w_item1 = w_item1 + self.w_item2 = w_item2 + self.w_item3 = w_item3 + + def get(self, index): + assert index < 3 + if index == 2: + return self.w_item3 + elif index == 1: + return self.w_item2 + return self.w_item1 + + def getitems(self): + return [self.w_item1, self.w_item2, self.w_item3] + + def contains(self, space, w_obj): + return space.newbool(space.eq_w(self.w_item1, w_obj) or + space.eq_w(self.w_item2, w_obj) or + space.eq_w(self.w_item3, w_obj)) + + def eq(self, space, impl): + assert isinstance(impl, TripleTupleImplementation) + return space.newbool(space.eq_w(self.w_item1, impl.w_item1) and + space.eq_w(self.w_item2, impl.w_item2) and + space.eq_w(self.w_item3, impl.w_item3)) + + def repr(self, space): + return space.wrap("(" + space.str_w(space.repr(self.w_item1)) + ", " + + space.str_w(space.repr(self.w_item2)) + ", " + + space.str_w(space.repr(self.w_item3)) + ")") + + def hash(self, space): + mult = 1000003 + x = 0x345678 + y = space.int_w(space.hash(self.w_item1)) + x = (x ^ y) * mult + mult += 82524 + y = space.int_w(space.hash(self.w_item2)) + x = (x ^ y) * mult + mult += 82522 + y = space.int_w(space.hash(self.w_item3)) + x = (x ^ y) * mult + mult += 82520 + x += 97531 + return space.wrap(intmask(x)) + +class BigTupleImplementation(BaseTupleImplementation): + def __init__(self, wrappeditems): + self.size = len(wrappeditems) + self.wrappeditems = wrappeditems + + def get(self, index): + return self.wrappeditems[index] + + def getitems(self): + return self.wrappeditems + + def contains(self, space, w_obj): + for w_item in self.wrappeditems: + if space.eq_w(w_item, w_obj): + return space.w_True + return space.w_False + + def eq(self, space, impl): + assert isinstance(impl, BigTupleImplementation) + items1 = self.wrappeditems + items2 = impl.wrappeditems + for i in range(len(items1)): + item1 = items1[i] + item2 = items2[i] + if not space.eq_w(item1, item2): + return space.w_False + return space.w_True + + def hash(self, space): + mult = 1000003 + x = 0x345678 + z = len(self.wrappeditems) + for w_item in self.wrappeditems: + y = space.int_w(space.hash(w_item)) + x = (x ^ y) * mult + z -= 1 + mult += 82520 + z + z + x += 97531 + return space.wrap(intmask(x)) + + def repr(self, space): + items = self.wrappeditems + return space.wrap("(" + + (", ".join([space.str_w(space.repr(item)) for item in items])) + + ")") + + +empty_tuple = EmptyTupleImplementation() + +class W_TupleMultiObject(W_Object): + from pypy.objspace.std.tupletype import tuple_typedef as typedef + + def __init__(w_self, wrappeditems): + lgt = len(wrappeditems) + if lgt == 0: + w_self.implementation = empty_tuple + elif lgt == 1: + w_self.implementation = SingleTupleImplementation(wrappeditems[0]) + elif lgt == 2: + w_self.implementation = DoubleTupleImplementation(wrappeditems[0], + wrappeditems[1]) + elif lgt == 3: + w_self.implementation = TripleTupleImplementation(wrappeditems[0], + wrappeditems[1], + wrappeditems[2]) + else: + w_self.implementation = BigTupleImplementation(wrappeditems) + + def __repr__(w_self): + """ representation for debugging purposes """ + reprlist = [repr(w_item) for w_item in w_self.wrappeditems] + return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist)) + + def unwrap(w_tuple, space): + items = [space.unwrap(w_item) for w_item in w_tuple.getitems()] # XXX generic mixed types unwrap + return tuple(items) + + def getitems(self): + return self.implementation.getitems() + +registerimplementation(W_TupleMultiObject) + + +def len__TupleMulti(space, w_tuple): + return wrapint(space, w_tuple.implementation.size) + +def getitem__TupleMulti_ANY(space, w_tuple, w_index): + # getindex_w should get a second argument space.w_IndexError, + # but that doesn't exist the first time this is called. + try: + w_IndexError = space.w_IndexError + except AttributeError: + w_IndexError = None + index = space.getindex_w(w_index, w_IndexError, "tuple index") + impl = w_tuple.implementation + if impl.size <= index: + raise OperationError(space.w_IndexError, + space.wrap("tuple index out of range")) + return impl.get(index) + +def getitem__TupleMulti_Slice(space, w_tuple, w_slice): + # XXX eventually optimize this + length = w_tuple.implementation.size + start, stop, step, slicelength = w_slice.indices4(space, length) + assert slicelength >= 0 + subitems = [None] * slicelength + for i in range(slicelength): + subitems[i] = w_tuple.implementation.get(start) + start += step + return W_TupleMultiObject(subitems) + +def contains__TupleMulti_ANY(space, w_tuple, w_obj): + return w_tuple.implementation.contains(space, w_obj) + +def iter__TupleMulti(space, w_tuple): + from pypy.objspace.std import iterobject + return iterobject.W_FastSeqIterObject(w_tuple, w_tuple.getitems()) + +def add__TupleMulti_TupleMulti(space, w_tuple1, w_tuple2): + items1 = w_tuple1.getitems() + items2 = w_tuple2.getitems() + return W_TupleMultiObject(items1 + items2) + +def mul_tuple_times(space, w_tuple, w_times): + try: + times = space.getindex_w(w_times, space.w_OverflowError) + except OperationError, e: + if e.match(space, space.w_TypeError): + raise FailedToImplement + raise + items = w_tuple.getitems() + return W_TupleMultiObject(items * times) + +def mul__TupleMulti_ANY(space, w_tuple, w_times): + return mul_tuple_times(space, w_tuple, w_times) + +def mul__ANY_TupleMulti(space, w_times, w_tuple): + return mul_tuple_times(space, w_tuple, w_times) + +def eq__TupleMulti_TupleMulti(space, w_tuple1, w_tuple2): + if w_tuple1.implementation.size != w_tuple2.implementation.size: + return space.w_False + return w_tuple1.implementation.eq(space, w_tuple2.implementation) + +def _min(a, b): + if a < b: + return a + return b + +def lt__TupleMulti_TupleMulti(space, w_tuple1, w_tuple2): + # XXX optimize + items1 = w_tuple1.getitems() + items2 = w_tuple2.getitems() + ncmp = _min(len(items1), len(items2)) + # Search for the first index where items are different + for p in range(ncmp): + if not space.eq_w(items1[p], items2[p]): + return space.lt(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(len(items1) < len(items2)) + +def gt__TupleMulti_TupleMulti(space, w_tuple1, w_tuple2): + # XXX optimize + items1 = w_tuple1.getitems() + items2 = w_tuple2.getitems() + ncmp = _min(len(items1), len(items2)) + # Search for the first index where items are different + for p in range(ncmp): + if not space.eq_w(items1[p], items2[p]): + return space.gt(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(len(items1) > len(items2)) + +def repr__TupleMulti(space, w_tuple): + return w_tuple.implementation.repr(space) + +def hash__TupleMulti(space, w_tuple): + # this is the CPython 2.4 algorithm (changed from 2.3) + return w_tuple.implementation.hash(space) + +def getnewargs__TupleMulti(space, w_tuple): + return space.newtuple([W_TupleMultiObject(w_tuple.getitems())]) + +register_all(vars()) + From bgola at codespeak.net Tue Apr 29 17:59:11 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Tue, 29 Apr 2008 17:59:11 +0200 (CEST) Subject: [pypy-svn] r54245 - in pypy/branch/2.5-features/pypy: module/__builtin__/test objspace objspace/test Message-ID: <20080429155911.EACCE1683F3@codespeak.net> Author: bgola Date: Tue Apr 29 17:59:10 2008 New Revision: 54245 Modified: pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py pypy/branch/2.5-features/pypy/objspace/descroperation.py pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py Log: __hash__ now can return a long but hash(obj) always return an int, as cpython 2.5 Modified: pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/branch/2.5-features/pypy/module/__builtin__/test/test_classobj.py Tue Apr 29 17:59:10 2008 @@ -486,9 +486,9 @@ raises(TypeError, hash, a) class A: # can return long def __hash__(self): - return long(1) + return long(2**31) a = A() - assert hash(a) == long(1) + assert hash(a) == -2147483648 def test_index(self): import sys Modified: pypy/branch/2.5-features/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/2.5-features/pypy/objspace/descroperation.py (original) +++ pypy/branch/2.5-features/pypy/objspace/descroperation.py Tue Apr 29 17:59:10 2008 @@ -289,7 +289,16 @@ w_result = space.get_and_call_function(w_hash, w_obj) if (space.is_true(space.isinstance(w_result, space.w_int)) or space.is_true(space.isinstance(w_result, space.w_long))): - return w_result + try: + space.int_w(w_result) + return space.int(w_result) + except OperationError, e: + if not e.match(space, space.w_OverflowError): + raise + from sys import maxint + w_result = space.mod(w_result, space.wrap(maxint+1)) + w_result = space.sub(w_result, space.wrap(maxint+1)) + return space.int(w_result) else: raise OperationError(space.w_TypeError, space.wrap("__hash__() should return an int or long")) Modified: pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py ============================================================================== --- pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py (original) +++ pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py Tue Apr 29 17:59:10 2008 @@ -73,5 +73,10 @@ raises(TypeError, hash, E()) class F: # can return long def __hash__(self): - return long(1) - assert hash(F()) == long(1) + return long(2**31) + assert hash(F()) == -2147483648 # 2.5 behavior + + class G: + def __hash__(self): + return 1 + assert isinstance(hash(G()), int) From bgola at codespeak.net Tue Apr 29 18:33:41 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Tue, 29 Apr 2008 18:33:41 +0200 (CEST) Subject: [pypy-svn] r54246 - in pypy/branch/2.5-features/pypy/objspace: . test Message-ID: <20080429163341.0579B1683F3@codespeak.net> Author: bgola Date: Tue Apr 29 18:33:41 2008 New Revision: 54246 Modified: pypy/branch/2.5-features/pypy/objspace/descroperation.py pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py Log: when __hash__ returns a long, the long is hashed Modified: pypy/branch/2.5-features/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/2.5-features/pypy/objspace/descroperation.py (original) +++ pypy/branch/2.5-features/pypy/objspace/descroperation.py Tue Apr 29 18:33:41 2008 @@ -287,21 +287,13 @@ space.wrap("unhashable type")) return default_identity_hash(space, w_obj) w_result = space.get_and_call_function(w_hash, w_obj) - if (space.is_true(space.isinstance(w_result, space.w_int)) or - space.is_true(space.isinstance(w_result, space.w_long))): - try: - space.int_w(w_result) - return space.int(w_result) - except OperationError, e: - if not e.match(space, space.w_OverflowError): - raise - from sys import maxint - w_result = space.mod(w_result, space.wrap(maxint+1)) - w_result = space.sub(w_result, space.wrap(maxint+1)) - return space.int(w_result) + if space.is_true(space.isinstance(w_result, space.w_int)): + return w_result + elif space.is_true(space.isinstance(w_result, space.w_long)): + return space.hash(w_result) else: raise OperationError(space.w_TypeError, - space.wrap("__hash__() should return an int or long")) + space.wrap("__hash__() should return an int or long")) def userdel(space, w_obj): w_del = space.lookup(w_obj, '__del__') Modified: pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py ============================================================================== --- pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py (original) +++ pypy/branch/2.5-features/pypy/objspace/test/test_descriptor.py Tue Apr 29 18:33:41 2008 @@ -73,8 +73,8 @@ raises(TypeError, hash, E()) class F: # can return long def __hash__(self): - return long(2**31) - assert hash(F()) == -2147483648 # 2.5 behavior + return long(2**33) + assert hash(F()) == 2 # 2.5 behavior class G: def __hash__(self): From bgola at codespeak.net Tue Apr 29 18:38:01 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Tue, 29 Apr 2008 18:38:01 +0200 (CEST) Subject: [pypy-svn] r54247 - in pypy/branch/2.5-features/pypy: config interpreter/pyparser interpreter/pyparser/data Message-ID: <20080429163801.89AB31683F5@codespeak.net> Author: bgola Date: Tue Apr 29 18:37:58 2008 New Revision: 54247 Added: pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 Modified: pypy/branch/2.5-features/pypy/config/pypyoption.py pypy/branch/2.5-features/pypy/interpreter/pyparser/pythonutil.py Log: Adding 2.5 Grammar file and options to interpreter, not really working yet... Modified: pypy/branch/2.5-features/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/2.5-features/pypy/config/pypyoption.py (original) +++ pypy/branch/2.5-features/pypy/config/pypyoption.py Tue Apr 29 18:37:58 2008 @@ -87,7 +87,7 @@ cmdline='--compiler'), ChoiceOption("pyversion", "which grammar to use for app-level code", - ["2.3", "2.4", "2.5a"], "2.4", + ["2.3", "2.4", "2.5a", "2.5"], "2.4", cmdline='--pyversion'), OptionDescription("opcodes", "opcodes to enable in the interpreter", [ Added: pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 ============================================================================== --- (empty file) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 Tue Apr 29 18:37:58 2008 @@ -0,0 +1,148 @@ +# Grammar for Python + +# Note: Changing the grammar specified in this file will most likely +# require corresponding changes in the parser module +# (../Modules/parsermodule.c). If you can't make the changes to +# that module yourself, please co-ordinate the required changes +# with someone who can; ask around on python-dev for help. Fred +# Drake will probably be listening there. + +# NOTE WELL: You should also follow all the steps listed in PEP 306, +# "How to Change Python's Grammar" + +# Commands for Kees Blom's railroad program +#diagram:token NAME +#diagram:token NUMBER +#diagram:token STRING +#diagram:token NEWLINE +#diagram:token ENDMARKER +#diagram:token INDENT +#diagram:output\input python.bla +#diagram:token DEDENT +#diagram:output\textwidth 20.04cm\oddsidemargin 0.0cm\evensidemargin 0.0cm +#diagram:rules + +# Start symbols for the grammar: +# single_input is a single interactive statement; +# file_input is a module or sequence of commands read from an input file; +# eval_input is the input for the eval() and input() functions. +# NB: compound_stmt in single_input is followed by extra NEWLINE! +single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE +file_input: (NEWLINE | stmt)* ENDMARKER +eval_input: testlist NEWLINE* ENDMARKER + +decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE +decorators: decorator+ +funcdef: [decorators] 'def' NAME parameters ':' suite +parameters: '(' [varargslist] ')' +varargslist: ((fpdef ['=' test] ',')* + ('*' NAME [',' '**' NAME] | '**' NAME) | + fpdef ['=' test] (',' fpdef ['=' test])* [',']) +fpdef: NAME | '(' fplist ')' +fplist: fpdef (',' fpdef)* [','] + +stmt: simple_stmt | compound_stmt +simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE +small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | + import_stmt | global_stmt | exec_stmt | assert_stmt) +expr_stmt: testlist (augassign (yield_expr|testlist) | + ('=' (yield_expr|testlist))*) +augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | + '<<=' | '>>=' | '**=' | '//=') +# For normal assignments, additional restrictions enforced by the interpreter +print_stmt: 'print' ( [ test (',' test)* [','] ] | + '>>' test [ (',' test)+ [','] ] ) +del_stmt: 'del' exprlist +pass_stmt: 'pass' +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt +break_stmt: 'break' +continue_stmt: 'continue' +return_stmt: 'return' [testlist] +yield_stmt: yield_expr +raise_stmt: 'raise' [test [',' test [',' test]]] +import_stmt: import_name | import_from +import_name: 'import' dotted_as_names +import_from: ('from' ('.'* dotted_name | '.'+) + 'import' ('*' | '(' import_as_names ')' | import_as_names)) +import_as_name: NAME [('as' | NAME) NAME] +dotted_as_name: dotted_name [('as' | NAME) NAME] +import_as_names: import_as_name (',' import_as_name)* [','] +dotted_as_names: dotted_as_name (',' dotted_as_name)* +dotted_name: NAME ('.' NAME)* +global_stmt: 'global' NAME (',' NAME)* +exec_stmt: 'exec' expr ['in' test [',' test]] +assert_stmt: 'assert' test [',' test] + +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef +if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] +while_stmt: 'while' test ':' suite ['else' ':' suite] +for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] +try_stmt: ('try' ':' suite + ((except_clause ':' suite)+ + ['else' ':' suite] + ['finally' ':' suite] | + 'finally' ':' suite)) +with_stmt: 'with' test [ with_var ] ':' suite +with_var: ('as' | NAME) expr +# NB compile.c makes sure that the default except clause is last +except_clause: 'except' [test [',' test]] +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT + +# Backward compatibility cruft to support: +# [ x for x in lambda: True, lambda: False if x() ] +# even while also allowing: +# lambda x: 5 if x else 2 +# (But not a mix of the two) +testlist_safe: old_test [(',' old_test)+ [',']] +old_test: or_test | old_lambdef +old_lambdef: 'lambda' [varargslist] ':' old_test + +test: or_test ['if' or_test 'else' test] | lambdef +or_test: and_test ('or' and_test)* +and_test: not_test ('and' not_test)* +not_test: 'not' not_test | comparison +comparison: expr (comp_op expr)* +comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' +expr: xor_expr ('|' xor_expr)* +xor_expr: and_expr ('^' and_expr)* +and_expr: shift_expr ('&' shift_expr)* +shift_expr: arith_expr (('<<'|'>>') arith_expr)* +arith_expr: term (('+'|'-') term)* +term: factor (('*'|'/'|'%'|'//') factor)* +factor: ('+'|'-'|'~') factor | power +power: atom trailer* ['**' factor] +atom: ('(' [yield_expr|testlist_gexp] ')' | + '[' [listmaker] ']' | + '{' [dictmaker] '}' | + '`' testlist1 '`' | + NAME | NUMBER | STRING+) +listmaker: test ( list_for | (',' test)* [','] ) +testlist_gexp: test ( gen_for | (',' test)* [','] ) +lambdef: 'lambda' [varargslist] ':' test +trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +subscriptlist: subscript (',' subscript)* [','] +subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] +sliceop: ':' [test] +exprlist: expr (',' expr)* [','] +testlist: test (',' test)* [','] +dictmaker: test ':' test (',' test ':' test)* [','] + +classdef: 'class' NAME ['(' [testlist] ')'] ':' suite + +arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +argument: test [gen_for] | test '=' test # Really [keyword '='] test + +list_iter: list_for | list_if +list_for: 'for' exprlist 'in' testlist_safe [list_iter] +list_if: 'if' old_test [list_iter] + +gen_iter: gen_for | gen_if +gen_for: 'for' exprlist 'in' or_test [gen_iter] +gen_if: 'if' old_test [gen_iter] + +testlist1: test (',' test)* + +# not used in grammar, but may appear in "node" passed from Parser to Compiler +encoding_decl: NAME + +yield_expr: 'yield' [testlist] Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/2.5-features/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/pythonutil.py Tue Apr 29 18:37:58 2008 @@ -31,7 +31,7 @@ _ver = PYTHON_VERSION elif version == "stable": _ver = "_stablecompiler" - elif version in ("2.3","2.4","2.5a"): + elif version in ("2.3","2.4","2.5a","2.5"): _ver = version else: raise ValueError('no such grammar version: %s' % version) From antocuni at codespeak.net Tue Apr 29 20:39:41 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 29 Apr 2008 20:39:41 +0200 (CEST) Subject: [pypy-svn] r54250 - pypy/branch/oo-jit/pypy/jit/rainbow/test Message-ID: <20080429183941.307F51683EE@codespeak.net> Author: antocuni Date: Tue Apr 29 20:39:39 2008 New Revision: 54250 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py Log: use hlstr to make this test passing both on lltype and ootype Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py Tue Apr 29 20:39:39 2008 @@ -12,6 +12,7 @@ from pypy.jit.timeshifter import rtimeshift, rvalue from pypy.rpython.lltypesystem import lltype, rstr from pypy.rpython.ootypesystem import ootype +from pypy.rpython.module.support import LLSupport, OOSupport from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.annotation import model as annmodel from pypy.annotation.policy import AnnotatorPolicy @@ -93,6 +94,8 @@ # these staticmethods should go to TestLLType, they are here only # for compatibility with other tests that inherit from # InterpretationTest + + to_rstr = staticmethod(LLSupport.to_rstr) @staticmethod def Ptr(T): @@ -817,9 +820,9 @@ assert res.x == 123 def test_plus_minus(self): - PROGRAMS = ["+-+"] - def ll_plus_minus(i, x, y): - s = PROGRAMS[i] # to prevent constant-folding + from pypy.rpython.annlowlevel import hlstr + def ll_plus_minus(llstr, x, y): + s = hlstr(llstr) acc = x n = len(s) pc = 0 @@ -832,9 +835,10 @@ acc -= y pc += 1 return acc - res = self.interpret(ll_plus_minus, [0, 0, 2], [0]) - assert res == ll_plus_minus(0, 0, 2) - self.check_insns({'int_add': 2, 'int_sub': 1, 'direct_call': 1}) + ll_plus_minus.convert_arguments = [self.to_rstr, int, int] + res = self.interpret(ll_plus_minus, ["+-+", 0, 2], [0]) + assert res == ll_plus_minus(self.to_rstr("+-+"), 0, 2) + self.check_insns({'int_add': 2, 'int_sub': 1}) def test_red_virtual_container(self): # this checks that red boxes are able to be virtualized dynamically by @@ -2226,6 +2230,8 @@ class OOTypeMixin(object): type_system = "ootype" + to_rstr = staticmethod(OOSupport.to_rstr) + @staticmethod def Ptr(T): return T From antocuni at codespeak.net Tue Apr 29 20:57:20 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 29 Apr 2008 20:57:20 +0200 (CEST) Subject: [pypy-svn] r54252 - pypy/branch/oo-jit/pypy/jit/timeshifter Message-ID: <20080429185720.24BE41683DF@codespeak.net> Author: antocuni Date: Tue Apr 29 20:57:19 2008 New Revision: 54252 Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py Log: don't try to get token for _ll_resize method when it doesn't exits, e.g. in ootype.Array. Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py Tue Apr 29 20:57:19 2008 @@ -136,9 +136,16 @@ def _setup(self, RGenOp, rtyper, LIST): self.alloctoken = RGenOp.allocToken(LIST) - self.tok_ll_resize = RGenOp.methToken(LIST, '_ll_resize') - self.tok_ll_setitem_fast = RGenOp.methToken(LIST, - 'll_setitem_fast') + self.tok_ll_resize = self._tok(RGenOp, LIST, '_ll_resize') + self.tok_ll_setitem_fast = self._tok(RGenOp, LIST, + 'll_setitem_fast') + + def _tok(self, RGenOp, LIST, name): + _, meth = LIST._lookup(name) + if meth is None: + return None + else: + return RGenOp.methToken(LIST, name) def _define_devirtualize(self): pass # XXX From antocuni at codespeak.net Wed Apr 30 10:17:41 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 10:17:41 +0200 (CEST) Subject: [pypy-svn] r54255 - pypy/branch/oo-jit/pypy/jit/rainbow Message-ID: <20080430081741.800E12A018F@codespeak.net> Author: antocuni Date: Wed Apr 30 10:17:40 2008 New Revision: 54255 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Log: remove outdated comment Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Wed Apr 30 10:17:40 2008 @@ -1700,7 +1700,6 @@ def serialize_op_new(self, op): TYPE = op.args[0].value if TYPE.oopspec_name is not None: - # XXX: works only for List oopspecdescindex = self.oopspecdesc_position('new', TYPE, False) oopspecdesc = self.oopspecdescs[oopspecdescindex] args, args_v = self.serialize_argtuple([], oopspecdesc.argtuple) From antocuni at codespeak.net Wed Apr 30 10:56:21 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 10:56:21 +0200 (CEST) Subject: [pypy-svn] r54256 - in pypy/branch/oo-jit/pypy: jit/rainbow jit/rainbow/test jit/timeshifter rpython/ootypesystem Message-ID: <20080430085621.84E8A2A0194@codespeak.net> Author: antocuni Date: Wed Apr 30 10:56:19 2008 New Revision: 54256 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Log: - make vlist working also with ootype.Array - test_bogus_index_while_compiling passes these days Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Wed Apr 30 10:56:19 2008 @@ -1702,7 +1702,8 @@ if TYPE.oopspec_name is not None: oopspecdescindex = self.oopspecdesc_position('new', TYPE, False) oopspecdesc = self.oopspecdescs[oopspecdescindex] - args, args_v = self.serialize_argtuple([], oopspecdesc.argtuple) + opargs = op.args[1:] # it's != [] if TYPE is an Array + args, args_v = self.serialize_argtuple(opargs, oopspecdesc.argtuple) deepfrozen = False self.emit('red_oopspec_call_%s' % len(args)) self.emit(oopspecdescindex) @@ -1715,6 +1716,8 @@ self.emit("red_new", index) self.register_redvar(op.result) + serialize_op_oonewarray = serialize_op_new + def serialize_op_oosend(self, op): assert not self.hannotator.policy.hotpath, 'TODO' kind, withexc = self.guess_call_kind(op) Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py Wed Apr 30 10:56:19 2008 @@ -18,6 +18,18 @@ assert res == 12 self.check_insns({}) + def test_fixed_vlist(self): + def ll_function(flag): + lst = [0, 0, 0] + if flag: + lst[0] = 42 + else: + lst[0] = 1 + return lst[0] + res = self.interpret(ll_function, [True], [], policy=P_OOPSPEC) + assert res == 42 + self.check_insns({}) + def test_enter_block(self): def ll_function(flag): lst = [] @@ -160,7 +172,6 @@ self.check_insns({}) def test_bogus_index_while_compiling(self): - py.test.skip("implement me") class Y: pass Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py Wed Apr 30 10:56:19 2008 @@ -250,13 +250,20 @@ self.typename = TYPE.oopspec_name self.method = 'oop_new%s' % self.typename self.is_method = False - opname, argtuple = parse_oopspec(TYPE.oopspec_new, []) + opname, argtuple = parse_oopspec(TYPE.oopspec_new, + TYPE.oopspec_new_argnames) assert opname == 'new' self.argtuple = argtuple - def allocate(): - return ootype.new(TYPE) - self.fnptr = self.rtyper.annotate_helper_fn(allocate, []) + if isinstance(TYPE, ootype.Array): + def allocate(length): + return ootype.oonewarray(TYPE, length) + self.fnptr = self.rtyper.annotate_helper_fn(allocate, + [ootype.Signed]) + else: + def allocate(): + return ootype.new(TYPE) + self.fnptr = self.rtyper.annotate_helper_fn(allocate, []) class NewOopSpecDesc_list(NewOopSpecDesc): pass Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Wed Apr 30 10:56:19 2008 @@ -490,6 +490,7 @@ ITEMTYPE_T = object() oopspec_name = 'list' oopspec_new = 'new(0)' + oopspec_new_argnames = () def __init__(self, ITEMTYPE=None): self.ITEM = ITEMTYPE @@ -582,6 +583,9 @@ SELFTYPE_T = object() ITEMTYPE_T = object() + oopspec_name = 'list' + oopspec_new = 'new(length)' + oopspec_new_argnames = ('length',) def __init__(self, ITEMTYPE=None): self.ITEM = ITEMTYPE @@ -662,6 +666,7 @@ VALUETYPE_T = object() oopspec_name = 'dict' oopspec_new = 'new()' + oopspec_new_argnames = () def __init__(self, KEYTYPE=None, VALUETYPE=None): self._KEYTYPE = KEYTYPE From arigo at codespeak.net Wed Apr 30 11:43:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 11:43:18 +0200 (CEST) Subject: [pypy-svn] r54257 - pypy/dist/pypy/interpreter Message-ID: <20080430094318.C494F398007@codespeak.net> Author: arigo Date: Wed Apr 30 11:43:17 2008 New Revision: 54257 Modified: pypy/dist/pypy/interpreter/typedef.py Log: Trying to reduce a little bit (translated) code duplication. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Wed Apr 30 11:43:17 2008 @@ -235,12 +235,7 @@ parent_destructor = getattr(supercls, '__del__', None) class Proto(object): def __del__(self): - self.clear_all_weakrefs() - try: - self.space.userdel(self) - except OperationError, e: - e.write_unraisable(self.space, 'method __del__ of ', self) - e.clear(self.space) # break up reference cycles + call_user_destructor(self.space, self) if parent_destructor is not None: parent_destructor(self) add(Proto) @@ -263,12 +258,7 @@ return self.w__dict__ def setdict(self, space, w_dict): - if not space.is_true(space.isinstance(w_dict, space.w_dict)): - raise OperationError(space.w_TypeError, - space.wrap("setting dictionary to a non-dict")) - if space.config.objspace.std.withmultidict: - from pypy.objspace.std import dictmultiobject - assert isinstance(w_dict, dictmultiobject.W_DictMultiObject) + check_new_dictionary(space, w_dict) self.w__dict__ = w_dict def user_setup(self, space, w_subtype): @@ -307,6 +297,28 @@ _allusersubcls_cache[subcls] = True return subcls +# a couple of helpers for the Proto classes above, factored out to reduce +# the translated code size +def check_new_dictionary(space, w_dict): + if not space.is_true(space.isinstance(w_dict, space.w_dict)): + raise OperationError(space.w_TypeError, + space.wrap("setting dictionary to a non-dict")) + if space.config.objspace.std.withmultidict: + from pypy.objspace.std import dictmultiobject + assert isinstance(w_dict, dictmultiobject.W_DictMultiObject) +check_new_dictionary._dont_inline_ = True + +def call_user_destructor(space, w_self): + w_self.clear_all_weakrefs() + try: + space.userdel(w_self) + except OperationError, e: + e.write_unraisable(space, 'method __del__ of ', w_self) + e.clear(space) # break up reference cycles +call_user_destructor._dont_inline_ = True + +# ____________________________________________________________ + def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): if func is None: return None From arigo at codespeak.net Wed Apr 30 11:44:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 11:44:27 +0200 (CEST) Subject: [pypy-svn] r54258 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080430094427.04F30398007@codespeak.net> Author: arigo Date: Wed Apr 30 11:44:26 2008 New Revision: 54258 Modified: pypy/dist/pypy/objspace/std/multimethod.py pypy/dist/pypy/objspace/std/test/test_multimethod.py Log: Decide precisely how multimethods should interact with RPython-level subclassing. A minor fix in InstallerVersion1 is enough to ensure it works this way. Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Wed Apr 30 11:44:26 2008 @@ -1,6 +1,29 @@ from pypy.tool.sourcetools import compile2 +# This provide two compatible implementations of "multimethods". A +# multimethod is a callable object which chooses and calls a real +# function from a table of pre-registered functions. The choice depends +# on the '__class__' of all arguments. For example usages see +# test_multimethod. + +# These multimethods support delegation: for each class A we must +# provide a "typeorder", which is list of pairs ((B, converter)) where B +# is a class and 'converter' is a function that can convert from an +# instance of A to an instance of B. If 'converter' is None it is +# assumed that the instance needs no conversion. The first entry in the +# typeorder of a class A must almost always be (A, None). + +# A slightly non-standard feature of PyPy's multimethods is the way in +# which they interact with normal subclassing. Basically, they don't. +# Suppose that A is a parent class of B. Then a function registered for +# an argument class A only accepts an instance whose __class__ is A, not +# B. To make it accept an instance of B, the typeorder for B must +# contain (A, None). An exception to this strict rule is if C is +# another subclass of A which is not mentioned at all in the typeorder; +# in this case C is considered to be equivalent to A. + + class FailedToImplement(Exception): def __init__(self, w_type=None, w_value=None): self.w_type = w_type @@ -121,6 +144,7 @@ self.prefix = prefix self.prefix_memo[prefix] = 1 self.list_of_typeorders = list_of_typeorders + self.check_typeorders() self.subtree_cache = {} self.to_install = [] self.non_empty = self.build_tree([], multimethod.dispatch_tree) @@ -135,6 +159,18 @@ self.perform_call = self.build_function(None, prefix+'_perform_call', None, perform) + def check_typeorders(self): + # xxx we use a '__'-separated list of the '__name__' of the types + # in build_single_method(), so types with the same __name__ or + # with '__' in them would obscurely break this logic + for typeorder in self.list_of_typeorders: + for type in typeorder: + assert '__' not in type.__name__, ( + "avoid '__' in the name of %r" % (type,)) + names = dict.fromkeys([type.__name__ for type in typeorder]) + assert len(names) == len(typeorder), ( + "duplicate type.__name__ in %r" % (typeorder,)) + def is_empty(self): return not self.non_empty @@ -143,9 +179,31 @@ #print >> f, '_'*60 #import pprint #pprint.pprint(self.list_of_typeorders, f) + + def class_key(cls): + "Returns an object such that class_key(subcls) > class_key(cls)." + return len(cls.__mro__) + + # Sort 'to_install' so that base classes come first, which is + # necessary for the 'parentfunc' logic in the loop below to work. + # Moreover, 'to_install' can contain two functions with the same + # name for the root class: the default fallback one and the real + # one. So we have to sort the real one just after the default one + # so that the default one gets overridden. + def key(target, funcname, func, source, fallback): + if target is None: + return () + return (class_key(target), not fallback) + self.to_install.sort(lambda a, b: cmp(key(*a), key(*b))) + for target, funcname, func, source, fallback in self.to_install: if target is not None: - if hasattr(target, funcname) and fallback: + # If the parent class provides a method of the same + # name which is actually the same 'func', we don't need + # to install it again. Useful with fallback functions. + parentfunc = getattr(target, funcname, None) + parentfunc = getattr(parentfunc, 'im_func', None) + if parentfunc is func: continue #print >> f, target.__name__, funcname #if source: @@ -194,13 +252,10 @@ if func is not None: things_to_call.append((conversion, func, None)) - if things_to_call: - funcname = intern(funcname) - self.build_function(next_type, funcname, len(types_so_far), - things_to_call) - return True - else: - return False + funcname = intern(funcname) + self.build_function(next_type, funcname, len(types_so_far), + things_to_call) + return bool(things_to_call) def build_function(self, target, funcname, func_selfarg_index, things_to_call): @@ -244,7 +299,9 @@ miniglobals['raiseFailedToImplement'] = raiseFailedToImplement bodylines = ['return raiseFailedToImplement()'] fallback = True - + # NB. make sure that there is only one fallback function object, + # i.e. the key used in the mmfunccache below is always the same + # for all functions with the same name and an empty bodylines. # protect all lines apart from the last one by a try:except: for i in range(len(bodylines)-2, -1, -1): @@ -291,10 +348,10 @@ class MMDispatcher(object): """NOT_RPYTHON - Explicit dispatcher class. This is not used in normal execution, which - uses the complex Installer below to install single-dispatch methods to - achieve the same result. The MMDispatcher is only used by - rpython.lltypesystem.rmultimethod. It is also nice for documentation. + Explicit dispatcher class. The __call__ and dispatch() methods + are only present for documentation purposes. The InstallerVersion2 + uses the expressions() method to precompute fast RPython-friendly + dispatch tables. """ _revcache = None @@ -323,6 +380,9 @@ return v.function(*[expr(w) for w in v.arguments]) else: return v + # XXX this is incomplete: for each type in argtypes but not + # in the typeorder, we should look for the first base class + # that is in the typeorder. e = None for v in self.expressions(argtypes, prefixargs, args, suffixargs): try: Modified: pypy/dist/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/dist/pypy/objspace/std/test/test_multimethod.py Wed Apr 30 11:44:26 2008 @@ -119,6 +119,45 @@ raises(FailedToImplement, "add2(space, w_b2, w_s)") raises(FailedToImplement, "add2(space, w_s, w_b1)") + def test_forbidden_subclasses(self): + mul = multimethod.MultiMethodTable(2, root_class=W_Root, + argnames_before=['space']) + class UserW_StringObject(W_StringObject): + pass + def mul__Int_String(space, w_x, w_y): + assert space == 'space' + assert isinstance(w_x, W_IntObject) + assert isinstance(w_y, W_StringObject) + return 'fine' + mul.register(mul__Int_String, W_IntObject, W_StringObject) + + mul1 = mul.install('__mul1', [self.typeorder, self.typeorder]) + assert mul1('space', W_IntObject(), W_StringObject()) == 'fine' + assert mul1('space', W_IntObject(), UserW_StringObject()) == 'fine' + + ext_typeorder = self.typeorder.copy() + ext_typeorder[UserW_StringObject] = [] + mul2 = mul.install('__mul2', [ext_typeorder, ext_typeorder]) + assert mul2('space', W_IntObject(), W_StringObject()) == 'fine' + raises(FailedToImplement, + mul2, 'baz', W_IntObject(), UserW_StringObject()) + + def test_ANY(self): + setattr = multimethod.MultiMethodTable(3, root_class=W_Root, + argnames_before=['space']) + def setattr__Int_ANY_ANY(space, w_x, w_y, w_z): + assert space == 'space' + assert isinstance(w_x, W_IntObject) + assert isinstance(w_y, W_Root) + assert isinstance(w_z, W_Root) + return w_y.__class__.__name__ + w_z.__class__.__name__ + setattr.register(setattr__Int_ANY_ANY, W_IntObject, W_Root, W_Root) + setattr1 = setattr.install('__setattr1', [self.typeorder]*3) + for cls1 in self.typeorder: + for cls2 in self.typeorder: + assert setattr1('space', W_IntObject(), cls1(), cls2()) == ( + cls1.__name__ + cls2.__name__) + def test_all_cases(self): import random space = 'space' From arigo at codespeak.net Wed Apr 30 11:46:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 11:46:30 +0200 (CEST) Subject: [pypy-svn] r54259 - in pypy/dist/pypy: annotation/test bin config doc/config jit/codegen/demo jit/codegen/i386 jit/codegen/llvm jit/codegen/ppc/ppcgen jit/codegen/ppc/ppcgen/test lang/js lang/prolog/interpreter lang/scheme lang/smalltalk/tool lib/test2 module/__builtin__/test module/_codecs/test module/_sre/test module/sys/test rlib/parsing/test rpython/microbench tool tool/algo/test tool/pytest tool/test translator translator/benchmark translator/c translator/c/test translator/cli/test translator/goal translator/goal/test2 translator/js translator/js/examples translator/js/examples/bnb translator/microbench/pybench translator/sandbox translator/sandbox/test translator/test translator/tool Message-ID: <20080430094630.9B34F398007@codespeak.net> Author: arigo Date: Wed Apr 30 11:46:28 2008 New Revision: 54259 Modified: pypy/dist/pypy/annotation/test/autopath.py pypy/dist/pypy/bin/autopath.py pypy/dist/pypy/config/autopath.py pypy/dist/pypy/doc/config/autopath.py pypy/dist/pypy/jit/codegen/demo/autopath.py pypy/dist/pypy/jit/codegen/i386/autopath.py pypy/dist/pypy/jit/codegen/llvm/autopath.py pypy/dist/pypy/jit/codegen/ppc/ppcgen/autopath.py pypy/dist/pypy/jit/codegen/ppc/ppcgen/test/autopath.py pypy/dist/pypy/lang/js/autopath.py pypy/dist/pypy/lang/prolog/interpreter/autopath.py pypy/dist/pypy/lang/scheme/autopath.py pypy/dist/pypy/lang/smalltalk/tool/autopath.py pypy/dist/pypy/lib/test2/autopath.py pypy/dist/pypy/module/__builtin__/test/autopath.py pypy/dist/pypy/module/_codecs/test/autopath.py pypy/dist/pypy/module/_sre/test/autopath.py pypy/dist/pypy/module/sys/test/autopath.py pypy/dist/pypy/rlib/parsing/test/autopath.py pypy/dist/pypy/rpython/microbench/autopath.py pypy/dist/pypy/tool/algo/test/autopath.py pypy/dist/pypy/tool/autopath.py pypy/dist/pypy/tool/pytest/autopath.py pypy/dist/pypy/tool/test/autopath.py pypy/dist/pypy/translator/autopath.py pypy/dist/pypy/translator/benchmark/autopath.py pypy/dist/pypy/translator/c/autopath.py pypy/dist/pypy/translator/c/test/autopath.py pypy/dist/pypy/translator/cli/test/autopath.py pypy/dist/pypy/translator/goal/autopath.py pypy/dist/pypy/translator/goal/test2/autopath.py pypy/dist/pypy/translator/js/autopath.py pypy/dist/pypy/translator/js/examples/autopath.py pypy/dist/pypy/translator/js/examples/bnb/autopath.py pypy/dist/pypy/translator/microbench/pybench/autopath.py pypy/dist/pypy/translator/sandbox/autopath.py pypy/dist/pypy/translator/sandbox/test/autopath.py pypy/dist/pypy/translator/test/autopath.py pypy/dist/pypy/translator/tool/autopath.py Log: Update autopath.py to detect and report more cleanly a broken checkout. Also detects cleanly if the py lib is missing, e.g. if the svn:externals was not checked out. Modified: pypy/dist/pypy/annotation/test/autopath.py ============================================================================== --- pypy/dist/pypy/annotation/test/autopath.py (original) +++ pypy/dist/pypy/annotation/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/bin/autopath.py ============================================================================== --- pypy/dist/pypy/bin/autopath.py (original) +++ pypy/dist/pypy/bin/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/config/autopath.py ============================================================================== --- pypy/dist/pypy/config/autopath.py (original) +++ pypy/dist/pypy/config/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/doc/config/autopath.py ============================================================================== --- pypy/dist/pypy/doc/config/autopath.py (original) +++ pypy/dist/pypy/doc/config/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/jit/codegen/demo/autopath.py ============================================================================== --- pypy/dist/pypy/jit/codegen/demo/autopath.py (original) +++ pypy/dist/pypy/jit/codegen/demo/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/jit/codegen/i386/autopath.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/autopath.py (original) +++ pypy/dist/pypy/jit/codegen/i386/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/jit/codegen/llvm/autopath.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/autopath.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/jit/codegen/ppc/ppcgen/autopath.py ============================================================================== --- pypy/dist/pypy/jit/codegen/ppc/ppcgen/autopath.py (original) +++ pypy/dist/pypy/jit/codegen/ppc/ppcgen/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/jit/codegen/ppc/ppcgen/test/autopath.py ============================================================================== --- pypy/dist/pypy/jit/codegen/ppc/ppcgen/test/autopath.py (original) +++ pypy/dist/pypy/jit/codegen/ppc/ppcgen/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/lang/js/autopath.py ============================================================================== --- pypy/dist/pypy/lang/js/autopath.py (original) +++ pypy/dist/pypy/lang/js/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/lang/prolog/interpreter/autopath.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/autopath.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/lang/scheme/autopath.py ============================================================================== --- pypy/dist/pypy/lang/scheme/autopath.py (original) +++ pypy/dist/pypy/lang/scheme/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/lang/smalltalk/tool/autopath.py ============================================================================== --- pypy/dist/pypy/lang/smalltalk/tool/autopath.py (original) +++ pypy/dist/pypy/lang/smalltalk/tool/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/lib/test2/autopath.py ============================================================================== --- pypy/dist/pypy/lib/test2/autopath.py (original) +++ pypy/dist/pypy/lib/test2/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/module/__builtin__/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/autopath.py (original) +++ pypy/dist/pypy/module/__builtin__/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/module/_codecs/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/_codecs/test/autopath.py (original) +++ pypy/dist/pypy/module/_codecs/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/module/_sre/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/_sre/test/autopath.py (original) +++ pypy/dist/pypy/module/_sre/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/module/sys/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/sys/test/autopath.py (original) +++ pypy/dist/pypy/module/sys/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/rlib/parsing/test/autopath.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/autopath.py (original) +++ pypy/dist/pypy/rlib/parsing/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/rpython/microbench/autopath.py ============================================================================== --- pypy/dist/pypy/rpython/microbench/autopath.py (original) +++ pypy/dist/pypy/rpython/microbench/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/tool/algo/test/autopath.py ============================================================================== --- pypy/dist/pypy/tool/algo/test/autopath.py (original) +++ pypy/dist/pypy/tool/algo/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/tool/autopath.py ============================================================================== --- pypy/dist/pypy/tool/autopath.py (original) +++ pypy/dist/pypy/tool/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/tool/pytest/autopath.py ============================================================================== --- pypy/dist/pypy/tool/pytest/autopath.py (original) +++ pypy/dist/pypy/tool/pytest/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/tool/test/autopath.py ============================================================================== --- pypy/dist/pypy/tool/test/autopath.py (original) +++ pypy/dist/pypy/tool/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/autopath.py ============================================================================== --- pypy/dist/pypy/translator/autopath.py (original) +++ pypy/dist/pypy/translator/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/benchmark/autopath.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/autopath.py (original) +++ pypy/dist/pypy/translator/benchmark/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/c/autopath.py ============================================================================== --- pypy/dist/pypy/translator/c/autopath.py (original) +++ pypy/dist/pypy/translator/c/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/c/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/c/test/autopath.py (original) +++ pypy/dist/pypy/translator/c/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/cli/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/autopath.py (original) +++ pypy/dist/pypy/translator/cli/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/goal/autopath.py ============================================================================== --- pypy/dist/pypy/translator/goal/autopath.py (original) +++ pypy/dist/pypy/translator/goal/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/goal/test2/autopath.py ============================================================================== --- pypy/dist/pypy/translator/goal/test2/autopath.py (original) +++ pypy/dist/pypy/translator/goal/test2/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/js/autopath.py ============================================================================== --- pypy/dist/pypy/translator/js/autopath.py (original) +++ pypy/dist/pypy/translator/js/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/js/examples/autopath.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/autopath.py (original) +++ pypy/dist/pypy/translator/js/examples/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/js/examples/bnb/autopath.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/bnb/autopath.py (original) +++ pypy/dist/pypy/translator/js/examples/bnb/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/microbench/pybench/autopath.py ============================================================================== --- pypy/dist/pypy/translator/microbench/pybench/autopath.py (original) +++ pypy/dist/pypy/translator/microbench/pybench/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/sandbox/autopath.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/autopath.py (original) +++ pypy/dist/pypy/translator/sandbox/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/sandbox/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/test/autopath.py (original) +++ pypy/dist/pypy/translator/sandbox/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/test/autopath.py (original) +++ pypy/dist/pypy/translator/test/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: Modified: pypy/dist/pypy/translator/tool/autopath.py ============================================================================== --- pypy/dist/pypy/translator/tool/autopath.py (original) +++ pypy/dist/pypy/translator/tool/autopath.py Wed Apr 30 11:46:28 2008 @@ -33,13 +33,22 @@ except NameError: head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + error = None while head: partdir = head head, tail = os.path.split(head) if tail == part: + # check if "../py/__init__.py" exists + checkfile = os.path.join(partdir, os.pardir, 'py', '__init__.py') + if not os.path.exists(checkfile): + error = "Cannot find %r" % (os.path.normpath(checkfile),) break else: - raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + error = "Cannot find the parent directory %r of the path %r" % ( + partdir, this_dir) + if error: + raise EnvironmentError("Invalid source tree - bogus checkout! " + + error) pypy_root = os.path.join(head, '') try: From antocuni at codespeak.net Wed Apr 30 11:51:15 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 11:51:15 +0200 (CEST) Subject: [pypy-svn] r54260 - in pypy/branch/oo-jit/pypy/jit: codegen codegen/llgraph timeshifter Message-ID: <20080430095115.4E551398007@codespeak.net> Author: antocuni Date: Wed Apr 30 11:51:14 2008 New Revision: 54260 Modified: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/model.py pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py Log: fix force_runtime_container for ootype-fixedsize-list Modified: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py Wed Apr 30 11:51:14 2008 @@ -273,6 +273,13 @@ return LLVar(llimpl.genop(self.b, 'new', vars_gv, gv_OBJTYPE.v)) + def genop_oonewarray(self, (gv_TYPE, gv_OBJTYPE), gv_length): + ll_assert(self.rgenop.currently_writing is self, + "genop_oonewarray: bad currently_writing") + vars_gv = [gv_TYPE.v, gv_length.v] + return LLVar(llimpl.genop(self.b, 'oonewarray', vars_gv, + gv_OBJTYPE.v)) + def genop_same_as(self, gv_value): ll_assert(self.rgenop.currently_writing is self, "genop_same_as: bad currently_writing") Modified: pypy/branch/oo-jit/pypy/jit/codegen/model.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/model.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/model.py Wed Apr 30 11:51:14 2008 @@ -88,11 +88,18 @@ ## def genop_malloc_fixedsize(self, alloctoken): ## def genop_malloc_varsize(self, varsizealloctoken, gv_size): ## def genop_call(self, sigtoken, gv_fnptr, args_gv): -## def genop_oosend(self, methtoken, gv_self, args_gv): ## def genop_same_as(self, gv_x): ## def genop_debug_pdb(self): # may take an args_gv later ## def genop_cast_int_to_ptr(self, kind, gv_int) +## # ootype-specific operations +## def genop_new(self, alloctoken): +## def genop_oonewarray(self, alloctoken, gv_length): +## def genop_oosend(self, methtoken, gv_self, args_gv): +## def genop_oononnull(self, gv_obj): +## def genop_oogetfield(self, fieldtoken, gv_obj): +## def genop_oosetfield(self, fieldtoken, gv_obj, gv_value): + # the other thing that happens for a given chunk is entering and # leaving basic blocks inside it. Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/vlist.py Wed Apr 30 11:51:14 2008 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype from pypy.jit.timeshifter.rcontainer import VirtualContainer, FrozenContainer from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, rvirtualizable, oop @@ -135,11 +136,23 @@ PtrRedBox = rvalue.InstanceRedBox def _setup(self, RGenOp, rtyper, LIST): - self.alloctoken = RGenOp.allocToken(LIST) - self.tok_ll_resize = self._tok(RGenOp, LIST, '_ll_resize') self.tok_ll_setitem_fast = self._tok(RGenOp, LIST, 'll_setitem_fast') + alloctoken = RGenOp.allocToken(LIST) + tok_ll_resize = self._tok(RGenOp, LIST, '_ll_resize') + if isinstance(LIST, ootype.Array): + def gen_newlist_impl(builder, args_gv): + assert len(args_gv) == 1 + gv_length = args_gv[0] + return builder.genop_oonewarray(alloctoken, gv_length) + else: + def gen_newlist_impl(builder, args_gv): + gv_lst = builder.genop_new(alloctoken) + builder.genop_oosend(tok_ll_resize, gv_lst, args_gv) + return gv_lst + self.gen_newlist_impl = gen_newlist_impl + def _tok(self, RGenOp, LIST, name): _, meth = LIST._lookup(name) if meth is None: @@ -151,9 +164,7 @@ pass # XXX def gen_newlist(self, builder, args_gv): - gv_lst = builder.genop_new(self.alloctoken) - builder.genop_oosend(self.tok_ll_resize, gv_lst, args_gv) - return gv_lst + return self.gen_newlist_impl(builder, args_gv) def gen_setitem_fast(self, builder, args_gv): gv_lst = args_gv.pop(0) From arigo at codespeak.net Wed Apr 30 11:54:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 11:54:31 +0200 (CEST) Subject: [pypy-svn] r54261 - in pypy/dist/pypy: doc doc/config doc/discussion jit/codegen/cli jit/codegen/cli/test lib module/_file/test module/clr module/posix/test objspace/flow/test rlib rlib/test rpython/memory/gctransform rpython/memory/test rpython/module/test rpython/test tool tool/algo/test translator/goal translator/jvm translator/jvm/test translator/llvm translator/llvm/test translator/oosupport/test_template Message-ID: <20080430095431.0D313398007@codespeak.net> Author: arigo Date: Wed Apr 30 11:54:30 2008 New Revision: 54261 Modified: pypy/dist/pypy/doc/config/translation.llvm.opt_options.txt (props changed) pypy/dist/pypy/doc/discussion/paper-wishlist.txt (props changed) pypy/dist/pypy/doc/home.txt (props changed) pypy/dist/pypy/jit/codegen/cli/ (props changed) pypy/dist/pypy/jit/codegen/cli/test/ (props changed) pypy/dist/pypy/lib/readline.py (props changed) pypy/dist/pypy/module/_file/test/test_large_file.py (props changed) pypy/dist/pypy/module/clr/app_importer.py (props changed) pypy/dist/pypy/module/posix/test/__init__.py (props changed) pypy/dist/pypy/objspace/flow/test/test___import__.py (contents, props changed) pypy/dist/pypy/rlib/rjvm.py (props changed) pypy/dist/pypy/rlib/test/test_rjvm.py (props changed) pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py (props changed) pypy/dist/pypy/rpython/memory/gctransform/llvmgcroot.py (props changed) pypy/dist/pypy/rpython/memory/test/snippet.py (props changed) pypy/dist/pypy/rpython/module/test/execve_tests.py (props changed) pypy/dist/pypy/rpython/test/test_stack.py (props changed) pypy/dist/pypy/tool/algo/test/test_unionfind.py (props changed) pypy/dist/pypy/tool/descriptor.py (props changed) pypy/dist/pypy/translator/goal/targetimageloadingsmalltalk.py (props changed) pypy/dist/pypy/translator/jvm/cmpopcodes.py (props changed) pypy/dist/pypy/translator/jvm/test/test_extreme.py (props changed) pypy/dist/pypy/translator/llvm/test/test_bigtest.py (props changed) pypy/dist/pypy/translator/llvm/test/test_newgc.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rbool.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rbuiltin.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rconstantdict.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rfloat.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rint.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rlist.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rpbc.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rstr.py (props changed) pypy/dist/pypy/translator/llvm/test/test_rtuple.py (props changed) pypy/dist/pypy/translator/llvm/test/test_runtest.py (props changed) pypy/dist/pypy/translator/llvm/test/test_standalone.py (props changed) pypy/dist/pypy/translator/llvm/typedefnode.py (props changed) pypy/dist/pypy/translator/oosupport/test_template/extreme.py (props changed) Log: fixeol Modified: pypy/dist/pypy/objspace/flow/test/test___import__.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test___import__.py (original) +++ pypy/dist/pypy/objspace/flow/test/test___import__.py Wed Apr 30 11:54:30 2008 @@ -1,12 +1,12 @@ -from py.test import raises - -def test___import_(): - import os - mod = os.name - raises(TypeError, __import__, ()) - assert __import__(mod).__name__ == os.name - assert __import__(mod, None).__name__ == os.name - assert __import__(mod, None, None).__name__ == os.name - assert __import__(mod, None, None, None).__name__ == os.name - raises(TypeError, __import__, (mod, None, None, None, None)) +from py.test import raises + +def test___import_(): + import os + mod = os.name + raises(TypeError, __import__, ()) + assert __import__(mod).__name__ == os.name + assert __import__(mod, None).__name__ == os.name + assert __import__(mod, None, None).__name__ == os.name + assert __import__(mod, None, None, None).__name__ == os.name + raises(TypeError, __import__, (mod, None, None, None, None)) # XXX this will have to be adjusted for Python 2.5 pretty soon-ish :-) \ No newline at end of file From arigo at codespeak.net Wed Apr 30 12:21:00 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 12:21:00 +0200 (CEST) Subject: [pypy-svn] r54262 - pypy/dist/pypy/doc Message-ID: <20080430102100.8C04E498001@codespeak.net> Author: arigo Date: Wed Apr 30 12:21:00 2008 New Revision: 54262 Modified: pypy/dist/pypy/doc/objspace.txt Log: Link to the source code, which now contains an overview of its own features. Modified: pypy/dist/pypy/doc/objspace.txt ============================================================================== --- pypy/dist/pypy/doc/objspace.txt (original) +++ pypy/dist/pypy/doc/objspace.txt Wed Apr 30 12:21:00 2008 @@ -403,9 +403,13 @@ ------------ The Standard Object Space allows multiple object implementations per -Python type - this is based on multimethods_, although the more precise -picture spans several levels in order to emulate the exact Python -semantics. +Python type - this is based on multimethods_. For a description of the +multimethod variant that we implemented and which features it supports, +see the comment at the start of the source__. However, multimethods +alone are not enough for the Standard Object Space: the complete picture +spans several levels in order to emulate the exact Python semantics. + +.. __: ../objspace/std/multimethod.py Consider the example of the ``space.getitem(w_a, w_b)`` operation, corresponding to the application-level syntax ``a[b]``. The Standard From arigo at codespeak.net Wed Apr 30 12:23:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 12:23:24 +0200 (CEST) Subject: [pypy-svn] r54263 - pypy/dist/pypy/objspace/std Message-ID: <20080430102324.A2CD8398007@codespeak.net> Author: arigo Date: Wed Apr 30 12:23:24 2008 New Revision: 54263 Modified: pypy/dist/pypy/objspace/std/multimethod.py Log: Typo. Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Wed Apr 30 12:23:24 2008 @@ -8,7 +8,7 @@ # test_multimethod. # These multimethods support delegation: for each class A we must -# provide a "typeorder", which is list of pairs ((B, converter)) where B +# provide a "typeorder", which is list of pairs (B, converter) where B # is a class and 'converter' is a function that can convert from an # instance of A to an instance of B. If 'converter' is None it is # assumed that the instance needs no conversion. The first entry in the From arigo at codespeak.net Wed Apr 30 12:24:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 12:24:49 +0200 (CEST) Subject: [pypy-svn] r54264 - pypy/branch/faster-binop Message-ID: <20080430102449.ADB0E398007@codespeak.net> Author: arigo Date: Wed Apr 30 12:24:49 2008 New Revision: 54264 Added: pypy/branch/faster-binop/ - copied from r54263, pypy/dist/ Log: A branch in which to try to improve the speed of binary operations between objects of a built-in type. From arigo at codespeak.net Wed Apr 30 12:31:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 12:31:35 +0200 (CEST) Subject: [pypy-svn] r54265 - pypy/dist/pypy/rpython/memory/test Message-ID: <20080430103135.6DE0A398003@codespeak.net> Author: arigo Date: Wed Apr 30 12:31:32 2008 New Revision: 54265 Modified: pypy/dist/pypy/rpython/memory/test/snippet.py Log: Add an import in preparation for a merge. Modified: pypy/dist/pypy/rpython/memory/test/snippet.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/snippet.py (original) +++ pypy/dist/pypy/rpython/memory/test/snippet.py Wed Apr 30 12:31:32 2008 @@ -1,4 +1,4 @@ -import os +import os, py from pypy.tool.udir import udir from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop From arigo at codespeak.net Wed Apr 30 12:35:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 12:35:26 +0200 (CEST) Subject: [pypy-svn] r54266 - in pypy/dist/pypy: rpython/lltypesystem rpython/memory/gc rpython/memory/test translator/c/gcc Message-ID: <20080430103526.01446398003@codespeak.net> Author: arigo Date: Wed Apr 30 12:35:26 2008 New Revision: 54266 Added: pypy/dist/pypy/rpython/lltypesystem/ - copied from r54265, pypy/branch/gc-improvements/pypy/rpython/lltypesystem/ pypy/dist/pypy/rpython/memory/gc/ - copied from r54265, pypy/branch/gc-improvements/pypy/rpython/memory/gc/ pypy/dist/pypy/rpython/memory/test/test_gc.py - copied unchanged from r54265, pypy/branch/gc-improvements/pypy/rpython/memory/test/test_gc.py pypy/dist/pypy/translator/c/gcc/ - copied from r54265, pypy/branch/gc-improvements/pypy/translator/c/gcc/ Log: Merge the gc-improvements branch. This adds support to the hybrid GC for making objects non-movable after they have been moved a few times by the semispace logic. Fine-tuning is still missing. From arigo at codespeak.net Wed Apr 30 12:35:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 12:35:45 +0200 (CEST) Subject: [pypy-svn] r54267 - pypy/branch/gc-improvements Message-ID: <20080430103545.911B2398003@codespeak.net> Author: arigo Date: Wed Apr 30 12:35:44 2008 New Revision: 54267 Removed: pypy/branch/gc-improvements/ Log: Remove merged branch. From antocuni at codespeak.net Wed Apr 30 13:46:48 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 13:46:48 +0200 (CEST) Subject: [pypy-svn] r54268 - in pypy/branch/oo-jit/pypy/rpython: ootypesystem test Message-ID: <20080430114648.46C72398003@codespeak.net> Author: antocuni Date: Wed Apr 30 13:46:47 2008 New Revision: 54268 Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ooopimpl.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py Log: implement rtype_is_true for ootype.Object Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ooopimpl.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ooopimpl.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ooopimpl.py Wed Apr 30 13:46:47 2008 @@ -56,7 +56,10 @@ return getattr(inst, name) def is_inst(inst): - return isinstance(ootype.typeOf(inst), (ootype.Instance, ootype.BuiltinType, ootype.StaticMethod)) + T = ootype.typeOf(inst) + return T is ootype.Object or isinstance(T, (ootype.Instance, + ootype.BuiltinType, + ootype.StaticMethod,)) def checkinst(inst): assert is_inst(inst) Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/rootype.py Wed Apr 30 13:46:47 2008 @@ -38,6 +38,10 @@ class OOObjectRepr(Repr): lowleveltype = Object + + def rtype_is_true(self, hop): + vlist = hop.inputargs(self) + return hop.genop('oononnull', vlist, resulttype=ootype.Bool) ooobject_repr = OOObjectRepr() Modified: pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py Wed Apr 30 13:46:47 2008 @@ -842,3 +842,13 @@ assert ootype.cast_from_object(A, obj1) == a assert ootype.cast_from_object(B, obj2) == b self.interpret(fn_null, []) + + def fn_is_true(flag): + if flag: + a = ootype.new(A) + else: + a = ootype.null(A) + obj = ootype.cast_to_object(a) + return bool(obj) + assert self.interpret(fn_is_true, [True]) is True + assert self.interpret(fn_is_true, [False]) is False From arigo at codespeak.net Wed Apr 30 14:02:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 14:02:40 +0200 (CEST) Subject: [pypy-svn] r54269 - in pypy/branch/faster-binop/pypy: interpreter objspace/std objspace/std/test Message-ID: <20080430120240.32D5E398003@codespeak.net> Author: arigo Date: Wed Apr 30 14:02:39 2008 New Revision: 54269 Added: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py (contents, props changed) Modified: pypy/branch/faster-binop/pypy/interpreter/typedef.py pypy/branch/faster-binop/pypy/objspace/std/model.py pypy/branch/faster-binop/pypy/objspace/std/objspace.py pypy/branch/faster-binop/pypy/objspace/std/test/test_tupleobject.py pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py Log: A first attempt. Idea described in builtinshortcut.py. Modified: pypy/branch/faster-binop/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/faster-binop/pypy/interpreter/typedef.py (original) +++ pypy/branch/faster-binop/pypy/interpreter/typedef.py Wed Apr 30 14:02:39 2008 @@ -144,6 +144,21 @@ get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" _subclass_cache = {} +def enum_interplevel_subclasses(cls): + """Return a list of all the extra interp-level subclasses of 'cls' that + can be built by get_unique_interplevel_subclass().""" + result = [] + for flag1 in (False, True): + for flag2 in (False, True): + for flag3 in (False, True): + for flag4 in (False, True): + result.append(get_unique_interplevel_subclass(cls, flag1, + flag2, flag3, + flag4)) + result = dict.fromkeys(result) + assert len(result) <= 6 + return result.keys() + def _getusercls(cls, wants_dict, wants_slots, wants_del, weakrefable): typedef = cls.typedef if wants_dict and typedef.hasdict: Added: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py ============================================================================== --- (empty file) +++ pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py Wed Apr 30 14:02:39 2008 @@ -0,0 +1,46 @@ +from pypy.interpreter.baseobjspace import ObjSpace +from pypy.objspace.descroperation import DescrOperation +from pypy.objspace.std.multimethod import FailedToImplement +from pypy.tool.sourcetools import func_with_new_name + + +METHODS_WITH_SHORTCUT = dict.fromkeys( + ['add', 'sub', 'mul', 'truediv', 'floordiv', 'div', + 'mod', 'lshift', 'rshift', 'and_', 'or_', 'xor', + 'lt', 'le', 'eq', 'ne', 'gt', 'ge', + ]) +# XXX inplace_ +# XXX unary ops + + +def install(space, mm): + name = mm.name + if name not in METHODS_WITH_SHORTCUT: + return + print 'shortcut for:', name + assert hasattr(DescrOperation, name) + + base_method = getattr(space.__class__, name) + assert name not in space.__dict__ + + # Basic idea: we first try to dispatch the operation using purely + # the multimethod. If this is done naively, subclassing a built-in + # type like 'int' and overriding a special method like '__add__' + # doesn't work any more, because the multimethod will accept the int + # subclass and compute the result in the built-in way. To avoid + # this issue, we tweak the shortcut multimethods so that these ones + # (and only these ones) never match the interp-level subclasses + # built in pypy.interpreter.typedef.get_unique_interplevel_subclass. + expanded_order = space.model.get_typeorder_with_empty_usersubcls() + shortcut_method = mm.install_not_sliced(expanded_order) + + def operate(*args_w): + try: + w_result = shortcut_method(space, *args_w) + #print 'shortcut:', name, args_w + return w_result + except FailedToImplement: + pass + return base_method(space, *args_w) + + setattr(space, name, func_with_new_name(operate, name)) Modified: pypy/branch/faster-binop/pypy/objspace/std/model.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/model.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/model.py Wed Apr 30 14:02:39 2008 @@ -234,6 +234,8 @@ self.typeorder[type].append((type.typedef.any, None)) self.typeorder[type].append((W_Root, None)) + self._typeorder_with_empty_usersubcls = None + # ____________________________________________________________ # Prebuilt common integer values @@ -248,6 +250,19 @@ # ____________________________________________________________ + def get_typeorder_with_empty_usersubcls(self): + if self._typeorder_with_empty_usersubcls is None: + from pypy.interpreter.typedef import enum_interplevel_subclasses + result = self.typeorder.copy() + for cls in self.typeorder: + if (hasattr(cls, 'typedef') and + cls.typedef.acceptable_as_base_class): + subclslist = enum_interplevel_subclasses(cls) + for subcls in subclslist: + if cls in subcls.__bases__: # only direct subclasses + result[subcls] = [] + self._typeorder_with_empty_usersubcls = result + return self._typeorder_with_empty_usersubcls # ____________________________________________________________ Modified: pypy/branch/faster-binop/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/objspace.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/objspace.py Wed Apr 30 14:02:39 2008 @@ -257,7 +257,9 @@ # install all the MultiMethods into the space instance for name, mm in self.MM.__dict__.items(): - if isinstance(mm, StdObjSpaceMultiMethod) and not hasattr(self, name): + if not isinstance(mm, StdObjSpaceMultiMethod): + continue + if not hasattr(self, name): if name.endswith('_w'): # int_w, str_w...: these do not return a wrapped object func = mm.install_not_sliced(self.model.typeorder, baked_perform_call=True) else: @@ -275,6 +277,10 @@ return func_with_new_name(boundmethod, 'boundmethod_'+name) boundmethod = make_boundmethod() setattr(self, name, boundmethod) # store into 'space' instance + else: + # if config...: + from pypy.objspace.std import builtinshortcut + builtinshortcut.install(self, mm) # hack to avoid imports in the time-critical functions below for cls in self.model.typeorder: Modified: pypy/branch/faster-binop/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_tupleobject.py Wed Apr 30 14:02:39 2008 @@ -318,8 +318,8 @@ assert repr(()) == '()' assert repr((1,2,3)) == '(1, 2, 3)' -class AppTestMultiTuple(AppTestW_TupleObject): - def setup_class(cls): - from pypy.conftest import gettestobjspace - cls.space = gettestobjspace(**{"objspace.std.withmultituple": True}) +##class AppTestMultiTuple(AppTestW_TupleObject): +## def setup_class(cls): +## from pypy.conftest import gettestobjspace +## cls.space = gettestobjspace(**{"objspace.std.withmultituple": True}) Modified: pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py Wed Apr 30 14:02:39 2008 @@ -182,3 +182,29 @@ c.m = lambda: "instance" res = c.m() assert res == "instance" + + def test_override_builtin_methods(self): + class myint(int): + def __add__(self, other): + return 'add' + def __rsub__(self, other): + return 'rsub' + assert myint(3) + 5 == 'add' + assert 5 + myint(3) == 8 + assert myint(3) - 5 == -2 + assert 5 - myint(3) == 'rsub' + + +class AppTestWithMultiMethodVersion2(AppTestUserObject): + + def setup_class(cls): + from pypy import conftest + from pypy.objspace.std import multimethod + + cls.prev_installer = multimethod.Installer + multimethod.Installer = multimethod.InstallerVersion2 + cls.space = conftest.maketestobjspace() + + def teardown_class(cls): + from pypy.objspace.std import multimethod + multimethod.Installer = cls.prev_installer From arigo at codespeak.net Wed Apr 30 14:57:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 14:57:24 +0200 (CEST) Subject: [pypy-svn] r54270 - in pypy/branch/faster-binop/pypy/objspace/std: . test Message-ID: <20080430125724.8E9A239B5AD@codespeak.net> Author: arigo Date: Wed Apr 30 14:57:22 2008 New Revision: 54270 Modified: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py pypy/branch/faster-binop/pypy/objspace/std/floatobject.py pypy/branch/faster-binop/pypy/objspace/std/objspace.py pypy/branch/faster-binop/pypy/objspace/std/test/test_floatobject.py Log: builtinshortcut support for most of the remaining operations as well as is_true(). Modified: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py Wed Apr 30 14:57:22 2008 @@ -1,27 +1,52 @@ from pypy.interpreter.baseobjspace import ObjSpace from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std.multimethod import FailedToImplement +from pypy.objspace.std.boolobject import W_BoolObject from pypy.tool.sourcetools import func_with_new_name +# ____________________________________________________________ +# +# The sole purpose of this file is performance. +# It speeds up the dispatch of operations between +# built-in objects. +# +# this is a selection... a few operations are missing because they are +# thought to be very rare or most commonly used with non-builtin types METHODS_WITH_SHORTCUT = dict.fromkeys( ['add', 'sub', 'mul', 'truediv', 'floordiv', 'div', - 'mod', 'lshift', 'rshift', 'and_', 'or_', 'xor', - 'lt', 'le', 'eq', 'ne', 'gt', 'ge', - ]) -# XXX inplace_ -# XXX unary ops + 'mod', 'lshift', 'rshift', 'and_', 'or_', 'xor', 'pow', + 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'contains', + # unary + 'len', 'nonzero', 'repr', 'str', 'hash', + 'neg', 'invert', 'index', 'iter', 'next', 'buffer', + # in-place + 'inplace_add', 'inplace_sub', 'inplace_mul', 'inplace_truediv', + 'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow', + 'inplace_lshift', 'inplace_rshift', 'inplace_and', 'inplace_or', + 'inplace_xor', + ]) def install(space, mm): + """Install a function () on the space instance which invokes + a shortcut for built-in types. Returns the shortcutting multimethod + object or None. + """ name = mm.name if name not in METHODS_WITH_SHORTCUT: - return - print 'shortcut for:', name + return None + + # can be called multiple times without re-installing + if name in space.__dict__: + mm1, shortcut_method = space.__dict__[name].builtinshortcut + assert mm1 is mm + return shortcut_method + + print 'installing shortcut for:', name assert hasattr(DescrOperation, name) base_method = getattr(space.__class__, name) - assert name not in space.__dict__ # Basic idea: we first try to dispatch the operation using purely # the multimethod. If this is done naively, subclassing a built-in @@ -36,11 +61,51 @@ def operate(*args_w): try: - w_result = shortcut_method(space, *args_w) - #print 'shortcut:', name, args_w - return w_result + return shortcut_method(space, *args_w) except FailedToImplement: pass return base_method(space, *args_w) - setattr(space, name, func_with_new_name(operate, name)) + operate = func_with_new_name(operate, name) + operate.builtinshortcut = (mm, shortcut_method) + setattr(space, name, operate) + return shortcut_method + + +def install_is_true(space, mm_nonzero, mm_len): + nonzero_shortcut = install(space, mm_nonzero) + len_shortcut = install(space, mm_len) + assert 'is_true' not in space.__dict__ + + def is_true(w_obj): + # a bit of duplication of the logic from DescrOperation.is_true... + # first try 'nonzero' + try: + w_res = nonzero_shortcut(space, w_obj) + except FailedToImplement: + pass + else: + # the __nonzero__ method of built-in objects should + # always directly return a Bool + assert isinstance(w_res, W_BoolObject) + return w_res.boolval + + # then try 'len' + try: + w_res = len_shortcut(space, w_obj) + except FailedToImplement: + pass + else: + # the __len__ method of built-in objects typically + # returns an unwrappable integer + try: + return space.int_w(w_res) != 0 + except OperationError: + # I think no OperationError other than w_OverflowError + # could occur here + w_obj = w_res + + # general case fallback + return DescrOperation.is_true(space, w_obj) + + space.is_true = is_true Modified: pypy/branch/faster-binop/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/floatobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/floatobject.py Wed Apr 30 14:57:22 2008 @@ -349,8 +349,13 @@ def pow__Float_Float_ANY(space, w_float1, w_float2, thirdArg): # XXX it makes sense to do more here than in the backend # about sorting out errors! + + # This raises FailedToImplement in cases like overflow where a + # (purely theoretical) big-precision float implementation would have + # a chance to give a result, and directly OperationError for errors + # that we want to force to be reported to the user. if not space.is_w(thirdArg, space.w_None): - raise FailedToImplement(space.w_TypeError, space.wrap( + raise OperationError(space.w_TypeError, space.wrap( "pow() 3rd argument not allowed unless all arguments are integers")) x = w_float1.floatval y = w_float2.floatval @@ -359,13 +364,13 @@ z = 1.0 elif x == 0.0: if y < 0.0: - raise FailedToImplement(space.w_ZeroDivisionError, + raise OperationError(space.w_ZeroDivisionError, space.wrap("0.0 cannot be raised to a negative power")) z = 0.0 else: if x < 0.0: if math.floor(y) != y: - raise FailedToImplement(space.w_ValueError, + raise OperationError(space.w_ValueError, space.wrap("negative number " "cannot be raised to a fractional power")) if x == -1.0: Modified: pypy/branch/faster-binop/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/objspace.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/objspace.py Wed Apr 30 14:57:22 2008 @@ -282,6 +282,10 @@ from pypy.objspace.std import builtinshortcut builtinshortcut.install(self, mm) + if 1: # if config...: + from pypy.objspace.std import builtinshortcut + builtinshortcut.install_is_true(self, self.MM.nonzero, self.MM.len) + # hack to avoid imports in the time-critical functions below for cls in self.model.typeorder: globals()[cls.__name__] = cls @@ -674,16 +678,11 @@ return w_one is w_two def is_true(self, w_obj): - # first a few shortcuts for performance + # a shortcut for performance + # NOTE! this method is typically overridden by builtinshortcut.py. if type(w_obj) is W_BoolObject: return w_obj.boolval - if w_obj is self.w_None: - return False - # then a shortcut for bootstrapping reasons - if type(w_obj) is self.DictObjectCls: - return w_obj.len() != 0 - else: - return DescrOperation.is_true(self, w_obj) + return DescrOperation.is_true(self, w_obj) def finditem(self, w_obj, w_key): # performance shortcut to avoid creating the OperationError(KeyError) Modified: pypy/branch/faster-binop/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/test/test_floatobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_floatobject.py Wed Apr 30 14:57:22 2008 @@ -4,14 +4,6 @@ class TestW_FloatObject: - def _unwrap_nonimpl(self, func, *args, **kwds): - """ make sure that the expected exception occurs, and unwrap it """ - try: - res = func(*args, **kwds) - raise Exception, "should have failed but returned '%s'!" %repr(res) - except FailedToImplement, arg: - return arg.w_type - def test_pow_fff(self): x = 10.0 y = 2.0 @@ -19,9 +11,9 @@ f1 = fobj.W_FloatObject(x) f2 = fobj.W_FloatObject(y) f3 = fobj.W_FloatObject(z) - assert self.space.w_TypeError == ( - self._unwrap_nonimpl(fobj.pow__Float_Float_ANY, - self.space, f1, f2, f3)) + self.space.raises_w(self.space.w_TypeError, + fobj.pow__Float_Float_ANY, + self.space, f1, f2, f3) def test_pow_ffn(self): x = 10.0 @@ -32,10 +24,10 @@ assert v.floatval == x ** y f1 = fobj.W_FloatObject(-1.23) f2 = fobj.W_FloatObject(-4.56) - assert self.space.w_ValueError == ( - self._unwrap_nonimpl(fobj.pow__Float_Float_ANY, - self.space, f1, f2, - self.space.w_None)) + self.space.raises_w(self.space.w_ValueError, + fobj.pow__Float_Float_ANY, + self.space, f1, f2, + self.space.w_None) x = -10 y = 2.0 f1 = fobj.W_FloatObject(x) From arigo at codespeak.net Wed Apr 30 15:00:42 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 15:00:42 +0200 (CEST) Subject: [pypy-svn] r54271 - pypy/branch/faster-binop/pypy/objspace/std Message-ID: <20080430130042.14C0E16850C@codespeak.net> Author: arigo Date: Wed Apr 30 15:00:41 2008 New Revision: 54271 Modified: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py Log: Translation fix. Modified: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py Wed Apr 30 15:00:41 2008 @@ -1,4 +1,5 @@ from pypy.interpreter.baseobjspace import ObjSpace +from pypy.interpreter.error import OperationError from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std.multimethod import FailedToImplement from pypy.objspace.std.boolobject import W_BoolObject From antocuni at codespeak.net Wed Apr 30 15:22:00 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 15:22:00 +0200 (CEST) Subject: [pypy-svn] r54272 - pypy/branch/oo-jit/pypy/jit/timeshifter Message-ID: <20080430132200.CDD7239B5AC@codespeak.net> Author: antocuni Date: Wed Apr 30 15:22:00 2008 New Revision: 54272 Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py Log: translation fix (thanks to armin) Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py Wed Apr 30 15:22:00 2008 @@ -913,8 +913,7 @@ self.ownbox.setgenvar_hint(gv, known_nonzero=True) self.ownbox.content = None return - #name = getattr(typedesc.TYPE, '_name', str(typedesc.TYPE)) - name = str(typedesc.TYPE) + name = typedesc.name debug_print(lltype.Void, "FORCE CONTAINER: "+ name) #debug_pdb(lltype.Void) genvar = jitstate.ts.genop_malloc_fixedsize(builder, typedesc.alloctoken) From arigo at codespeak.net Wed Apr 30 15:26:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 15:26:47 +0200 (CEST) Subject: [pypy-svn] r54273 - pypy/dist/pypy/interpreter Message-ID: <20080430132647.1109539B5AC@codespeak.net> Author: arigo Date: Wed Apr 30 15:26:46 2008 New Revision: 54273 Modified: pypy/dist/pypy/interpreter/typedef.py Log: Translation fix (propagate the effect of isinstance(w_dict)). Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Wed Apr 30 15:26:46 2008 @@ -258,8 +258,7 @@ return self.w__dict__ def setdict(self, space, w_dict): - check_new_dictionary(space, w_dict) - self.w__dict__ = w_dict + self.w__dict__ = check_new_dictionary(space, w_dict) def user_setup(self, space, w_subtype): self.space = space @@ -306,6 +305,7 @@ if space.config.objspace.std.withmultidict: from pypy.objspace.std import dictmultiobject assert isinstance(w_dict, dictmultiobject.W_DictMultiObject) + return w_dict check_new_dictionary._dont_inline_ = True def call_user_destructor(space, w_self): From arigo at codespeak.net Wed Apr 30 15:42:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 15:42:08 +0200 (CEST) Subject: [pypy-svn] r54274 - pypy/branch/faster-binop/pypy/interpreter Message-ID: <20080430134208.39ADA39B5AC@codespeak.net> Author: arigo Date: Wed Apr 30 15:42:06 2008 New Revision: 54274 Modified: pypy/branch/faster-binop/pypy/interpreter/typedef.py Log: Merge r54273 from the trunk. Modified: pypy/branch/faster-binop/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/faster-binop/pypy/interpreter/typedef.py (original) +++ pypy/branch/faster-binop/pypy/interpreter/typedef.py Wed Apr 30 15:42:06 2008 @@ -273,8 +273,7 @@ return self.w__dict__ def setdict(self, space, w_dict): - check_new_dictionary(space, w_dict) - self.w__dict__ = w_dict + self.w__dict__ = check_new_dictionary(space, w_dict) def user_setup(self, space, w_subtype): self.space = space @@ -321,6 +320,7 @@ if space.config.objspace.std.withmultidict: from pypy.objspace.std import dictmultiobject assert isinstance(w_dict, dictmultiobject.W_DictMultiObject) + return w_dict check_new_dictionary._dont_inline_ = True def call_user_destructor(space, w_self): From antocuni at codespeak.net Wed Apr 30 15:55:37 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 15:55:37 +0200 (CEST) Subject: [pypy-svn] r54275 - pypy/branch/oo-jit/pypy/jit/timeshifter Message-ID: <20080430135537.4A64339B5B9@codespeak.net> Author: antocuni Date: Wed Apr 30 15:55:36 2008 New Revision: 54275 Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py Log: other translation fixes Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py Wed Apr 30 15:55:36 2008 @@ -191,8 +191,8 @@ args_gv) def gen_insertclean(self, builder, args_gv): - return builder.genop_call(typedesc.tok_ll_insertclean, - typedesc.gv_ll_insertclean, + return builder.genop_call(self.tok_ll_insertclean, + self.gv_ll_insertclean, args_gv) @@ -211,10 +211,10 @@ return operator.eq, hash def gen_newdict(self, builder, args_gv): - XXX + raise NotImplementedError def gen_insertclean(self, builder, args_gv): - XXX + raise NotImplementedError class AbstractFrozenVirtualDict(FrozenContainer): _attrs_ = ('typedesc',) From antocuni at codespeak.net Wed Apr 30 16:00:37 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 16:00:37 +0200 (CEST) Subject: [pypy-svn] r54276 - in pypy/branch/oo-jit/pypy/jit: codegen/llgraph rainbow rainbow/test timeshifter Message-ID: <20080430140037.0B5BE39B5B9@codespeak.net> Author: antocuni Date: Wed Apr 30 16:00:36 2008 New Revision: 54276 Modified: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py Log: start making test_llinterp passing also for ootype Modified: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/llgraph/llimpl.py Wed Apr 30 16:00:36 2008 @@ -786,6 +786,8 @@ setannotation(gengetarraysubstruct, s_ConstOrVar) setannotation(gensetfield, None) setannotation(gengetfield, s_ConstOrVar) +setannotation(genoosetfield, None) +setannotation(genoogetfield, s_ConstOrVar) setannotation(gensetarrayitem, None) setannotation(gengetarrayitem, s_ConstOrVar) setannotation(gengetarraysize, s_ConstOrVar) Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py Wed Apr 30 16:00:36 2008 @@ -6,8 +6,14 @@ py.test.skip("slow") +class TestLLInterpretedOOType(test_portal.TestPortalOOType): + translate_support_code = True + + # for the individual tests see + # ====> test_portal.py + -class TestLLInterpreted(test_portal.TestPortalLLType): +class TestLLInterpretedLLType(test_portal.TestPortalLLType): translate_support_code = True # for the individual tests see Modified: pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py Wed Apr 30 16:00:36 2008 @@ -1,3 +1,4 @@ +from pypy.rpython.annlowlevel import base_ptr_lltype from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype @@ -25,6 +26,7 @@ name = 'lltype' ROOT_TYPE = llmemory.Address + NULL_OBJECT = base_ptr_lltype()._defl() def get_typeptr(self, obj): return obj.typeptr @@ -53,6 +55,7 @@ name = 'ootype' ROOT_TYPE = ootype.Object + NULL_OBJECT = ootype.NULL def get_typeptr(self, obj): return obj.meta Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py Wed Apr 30 16:00:36 2008 @@ -15,8 +15,6 @@ FOLDABLE_GREEN_OPS['getarrayitem'] = None FOLDABLE_GREEN_OPS['getinteriorfield'] = None -NULL_OBJECT = base_ptr_lltype()._defl() - debug_view = lloperation.llop.debug_view debug_print = lloperation.llop.debug_print debug_pdb = lloperation.llop.debug_pdb @@ -419,10 +417,11 @@ return exitgvar.revealconst(lltype.Bool) else: return split_nonconstantcase(jitstate, exitgvar, resumepoint, - switchredbox, False, list(greens_gv)) + switchredbox, False, list(greens_gv), + jitstate.ts.NULL_OBJECT) def split_nonconstantcase(jitstate, exitgvar, resumepoint, - condbox, reverse, greens_gv, ll_evalue=NULL_OBJECT): + condbox, reverse, greens_gv, ll_evalue): resuming = jitstate.get_resuming() if resuming is not None and resuming.mergesleft == 0: node = resuming.path.pop() From antocuni at codespeak.net Wed Apr 30 16:04:49 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 30 Apr 2008 16:04:49 +0200 (CEST) Subject: [pypy-svn] r54277 - pypy/branch/oo-jit/pypy/jit/timeshifter Message-ID: <20080430140449.CF98A39B5BB@codespeak.net> Author: antocuni Date: Wed Apr 30 16:04:49 2008 New Revision: 54277 Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py Log: remove unused imports Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/rcontainer.py Wed Apr 30 16:04:49 2008 @@ -1,8 +1,8 @@ import operator from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype -from pypy.rpython.annlowlevel import cachedtype, cast_base_ptr_to_instance -from pypy.rpython.annlowlevel import base_ptr_lltype, cast_instance_to_base_ptr +from pypy.rpython.annlowlevel import cachedtype +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import llhelper from pypy.jit.timeshifter import rvalue, rvirtualizable from pypy.jit.rainbow.typesystem import deref, fieldType From fijal at codespeak.net Wed Apr 30 16:42:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 30 Apr 2008 16:42:23 +0200 (CEST) Subject: [pypy-svn] r54278 - pypy/branch/interpreter-optimizations Message-ID: <20080430144223.E2B6639B5B1@codespeak.net> Author: fijal Date: Wed Apr 30 16:42:21 2008 New Revision: 54278 Added: pypy/branch/interpreter-optimizations/ - copied from r54277, pypy/dist/ Log: Branch to play with interpreter optimizations From fijal at codespeak.net Wed Apr 30 16:46:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 30 Apr 2008 16:46:47 +0200 (CEST) Subject: [pypy-svn] r54279 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080430144647.D3C0239B5B1@codespeak.net> Author: fijal Date: Wed Apr 30 16:46:47 2008 New Revision: 54279 Removed: pypy/dist/pypy/objspace/std/tuplemultiobject.py Modified: pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_tupleobject.py pypy/dist/pypy/objspace/std/tupletype.py Log: Revert multituple, stays on branch Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Wed Apr 30 16:46:47 2008 @@ -14,7 +14,6 @@ "withstrjoin" : ["strjoinobject.W_StringJoinObject"], "withmultidict" : ["dictmultiobject.W_DictMultiObject", "dictmultiobject.W_DictMultiIterObject"], - "withmultituple" : ["tuplemultiobject.W_TupleMultiObject"], "withmultilist" : ["listmultiobject.W_ListMultiObject"], "withrope" : ["ropeobject.W_RopeObject", "ropeobject.W_RopeIterObject"], @@ -65,7 +64,6 @@ from pypy.objspace.std import setobject from pypy.objspace.std import smallintobject from pypy.objspace.std import tupleobject - from pypy.objspace.std import tuplemultiobject from pypy.objspace.std import listobject from pypy.objspace.std import dictobject from pypy.objspace.std import dictmultiobject @@ -142,9 +140,6 @@ if config.objspace.std.withrope: del self.typeorder[stringobject.W_StringObject] - if config.objspace.std.withmultituple: - del self.typeorder[tupleobject.W_TupleObject] - #check if we missed implementations from pypy.objspace.std.objspace import _registered_implementations for implcls in _registered_implementations: Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Apr 30 16:46:47 2008 @@ -240,12 +240,8 @@ self.DictObjectCls = dictobject.W_DictObject assert self.DictObjectCls in self.model.typeorder - if self.config.objspace.std.withmultituple: - from pypy.objspace.std import tuplemultiobject - self.TupleObjectCls = tuplemultiobject.W_TupleMultiObject - else: - from pypy.objspace.std import tupleobject - self.TupleObjectCls = tupleobject.W_TupleObject + from pypy.objspace.std import tupleobject + self.TupleObjectCls = tupleobject.W_TupleObject if not self.config.objspace.std.withrope: from pypy.objspace.std import stringobject Modified: pypy/dist/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_tupleobject.py Wed Apr 30 16:46:47 2008 @@ -317,9 +317,4 @@ assert repr((1,)) == '(1,)' assert repr(()) == '()' assert repr((1,2,3)) == '(1, 2, 3)' - -class AppTestMultiTuple(AppTestW_TupleObject): - def setup_class(cls): - from pypy.conftest import gettestobjspace - cls.space = gettestobjspace(**{"objspace.std.withmultituple": True}) Modified: pypy/dist/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupletype.py (original) +++ pypy/dist/pypy/objspace/std/tupletype.py Wed Apr 30 16:46:47 2008 @@ -3,9 +3,6 @@ def wraptuple(space, list_w): from pypy.objspace.std.tupleobject import W_TupleObject - if space.config.objspace.std.withmultituple: - from pypy.objspace.std.tuplemultiobject import W_TupleMultiObject - return W_TupleMultiObject(list_w) return W_TupleObject(list_w) def descr__new__(space, w_tupletype, w_sequence=NoneNotWrapped): From fijal at codespeak.net Wed Apr 30 16:53:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 30 Apr 2008 16:53:36 +0200 (CEST) Subject: [pypy-svn] r54280 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080430145336.6F4D239B5C9@codespeak.net> Author: fijal Date: Wed Apr 30 16:53:35 2008 New Revision: 54280 Modified: pypy/branch/io-improvements/pypy/rlib/streamio.py Log: * Speed up readlines() by avoiding list.pop(0) * Alternative implementation of _read_next_bunch, actually slower. Modified: pypy/branch/io-improvements/pypy/rlib/streamio.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/streamio.py (original) +++ pypy/branch/io-improvements/pypy/rlib/streamio.py Wed Apr 30 16:53:35 2008 @@ -466,14 +466,14 @@ self.buf = "" return while self.lines: - line = self.lines[0] + line = self.lines[-1] if offset <= len(line): intoffset = intmask(offset) assert intoffset >= 0 - self.lines[0] = line[intoffset:] + self.lines[-1] = line[intoffset:] return - offset -= len(self.lines[0]) - 1 - del self.lines[0] + offset -= len(self.lines[-1]) - 1 + self.lines.pop() assert not self.lines if offset <= len(self.buf): intoffset = intmask(offset) @@ -500,6 +500,7 @@ # Skip relative to EOF by reading and saving only just as # much as needed intoffset = offset2int(offset) + self.lines.reverse() data = "\n".join(self.lines + [self.buf]) total = len(data) buffers = [data] @@ -525,6 +526,7 @@ raise StreamError("whence should be 0, 1 or 2") def readall(self): + self.lines.reverse() self.lines.append(self.buf) more = ["\n".join(self.lines)] self.lines = [] @@ -543,31 +545,33 @@ assert n >= 0 if self.lines: # See if this can be satisfied from self.lines[0] - line = self.lines[0] + line = self.lines[-1] if len(line) >= n: - self.lines[0] = line[n:] + self.lines[-1] = line[n:] return line[:n] # See if this can be satisfied *without exhausting* self.lines k = 0 i = 0 - for line in self.lines: + lgt = len(self.lines) + for linenum in range(lgt-1,-1,-1): + line = self.lines[linenum] k += len(line) if k >= n: - lines = self.lines[:i] - data = self.lines[i] + lines = self.lines[linenum + 1:] + data = self.lines[linenum] cutoff = len(data) - (k-n) assert cutoff >= 0 lines.append(data[:cutoff]) - del self.lines[:i] - self.lines[0] = data[cutoff:] + del self.lines[linenum:] + self.lines.append(data[cutoff:]) return "\n".join(lines) k += 1 - i += 1 # See if this can be satisfied from self.lines plus self.buf if k + len(self.buf) >= n: lines = self.lines + lines.reverse() self.lines = [] cutoff = n - k assert cutoff >= 0 @@ -587,6 +591,7 @@ return data[:cutoff] lines = self.lines + lines.reverse() self.lines = [] lines.append(self.buf) self.buf = "" @@ -608,16 +613,39 @@ more[-1] = data[:cutoff] return "".join(more) + def _read_next_bunch(self): + self.lines = self.buf.split("\n") + self.buf = self.lines.pop() + self.lines.reverse() + + # slightly more optimized version, because of indirection actually slower + #def _read_next_bunch(self): + # numlines = self.buf.count("\n") + # self.lines = [None] * numlines + # last = -1 + # num = numlines - 1 + # while True: + # start = last + 1 + # assert start >= 0 + # next = self.buf.find("\n", start) + # if next == -1: + # if last != -1: + # self.buf = self.buf[start:] + # break + # assert next >= 0 + # self.lines[num] = self.buf[start:next] + # last = next + # num -= 1 + def readline(self): if self.lines: - return self.lines.pop(0) + "\n" + return self.lines.pop() + "\n" # This block is needed because read() can leave self.buf # containing newlines - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() + self._read_next_bunch() if self.lines: - return self.lines.pop(0) + "\n" + return self.lines.pop() + "\n" if self.buf: buf = [self.buf] @@ -625,10 +653,9 @@ buf = [] while 1: self.buf = self.do_read(self.bufsize) - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() + self._read_next_bunch() if self.lines: - buf.append(self.lines.pop(0)) + buf.append(self.lines.pop()) buf.append("\n") break if not self.buf: @@ -639,7 +666,7 @@ def peek(self): if self.lines: - return self.lines[0] + "\n" + return self.lines[-1] + "\n" else: return self.buf From fijal at codespeak.net Wed Apr 30 16:54:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 30 Apr 2008 16:54:59 +0200 (CEST) Subject: [pypy-svn] r54281 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080430145459.D0A3839B5C9@codespeak.net> Author: fijal Date: Wed Apr 30 16:54:59 2008 New Revision: 54281 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Log: Refactoring of rstr in order to have a single place where characters are copied, in-progress Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Wed Apr 30 16:54:59 2008 @@ -15,6 +15,9 @@ Bool, Void, GcArray, nullptr, pyobjectptr, cast_primitive, typeOf,\ staticAdtMethod, GcForwardReference from pypy.rpython.rmodel import Repr +from pypy.rpython.lltypesystem import llmemory +from pypy.rlib.objectmodel import we_are_translated +from pypy.tool.sourcetools import func_with_new_name # ____________________________________________________________ # @@ -28,7 +31,7 @@ STR = GcForwardReference() UNICODE = GcForwardReference() -def new_malloc(TP): +def new_malloc(TP, name): def mallocstr(length): ll_assert(length >= 0, "negative string length") r = malloc(TP, length) @@ -36,10 +39,10 @@ r.hash = 0 return r mallocstr._annspecialcase_ = 'specialize:semierased' - return mallocstr + return func_with_new_name(mallocstr, name) -mallocstr = new_malloc(STR) -mallocunicode = new_malloc(UNICODE) +mallocstr = new_malloc(STR, 'mallocstr') +mallocunicode = new_malloc(UNICODE, 'mallocunicode') def emptystrfun(): return emptystr @@ -47,14 +50,32 @@ def emptyunicodefun(): return emptyunicode +def _new_copy_contents_fun(TP, CHAR_TP, name): + def _str_ofs(item): + return (llmemory.offsetof(TP, 'chars') + + llmemory.itemoffsetof(TP.chars, 0) + + llmemory.sizeof(CHAR_TP) * item) + + def copy_string_contents(s1, s2, s1start, s2start, lgt): + src = llmemory.cast_ptr_to_adr(s1) + _str_ofs(s1start) + dest = llmemory.cast_ptr_to_adr(s2) + _str_ofs(s2start) + llmemory.raw_memcopy(src, dest, llmemory.sizeof(CHAR_TP) * lgt) + copy_string_contents._always_inline_ = True + return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name) + +copy_string_contents = _new_copy_contents_fun(STR, Char, 'string') +copy_unicode_contents = _new_copy_contents_fun(UNICODE, UniChar, 'unicode') + STR.become(GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocstr), - 'empty' : staticAdtMethod(emptystrfun)})) + 'empty' : staticAdtMethod(emptystrfun), + 'copy_contents' : staticAdtMethod(copy_string_contents)})) UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocunicode), - 'empty' : staticAdtMethod(emptyunicodefun)} + 'empty' : staticAdtMethod(emptyunicodefun), + 'copy_contents' : staticAdtMethod(copy_unicode_contents)} )) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() @@ -268,15 +289,8 @@ len1 = len(s1.chars) len2 = len(s2.chars) newstr = s1.malloc(len1 + len2) - j = 0 - while j < len1: - newstr.chars[j] = s1.chars[j] - j += 1 - i = 0 - while i < len2: - newstr.chars[j] = s2.chars[i] - i += 1 - j += 1 + s1.copy_contents(s1, newstr, 0, 0, len1) + s1.copy_contents(s2, newstr, 0, len1, len2) return newstr def ll_strip(s, ch, left, right): @@ -293,15 +307,11 @@ rpos -= 1 r_len = rpos - lpos + 1 result = s.malloc(r_len) - i = 0 - j = lpos - while i < r_len: - result.chars[i] = s.chars[j] - i += 1 - j += 1 + s.copy_contents(s, result, lpos, 0, r_len) return result def ll_upper(s): + # XXX WUAAAA! this is not true anymore for unicode s_chars = s.chars s_len = len(s_chars) if s_len == 0: @@ -317,6 +327,7 @@ return result def ll_lower(s): + # XXX WUAAAA! this is not true anymore for unicode s_chars = s.chars s_len = len(s_chars) if s_len == 0: @@ -343,31 +354,15 @@ itemslen += len(items[i].chars) i += 1 result = s.malloc(itemslen + s_len * (num_items - 1)) - res_chars = result.chars - res_index = 0 - i = 0 - item_chars = items[i].chars - item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 - i += 1 + res_index = len(items[0].chars) + s.copy_contents(items[0], result, 0, 0, res_index) + i = 1 while i < num_items: - j = 0 - while j < s_len: - res_chars[res_index] = s_chars[j] - j += 1 - res_index += 1 - - item_chars = items[i].chars - item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 + s.copy_contents(s, result, 0, res_index, s_len) + res_index += s_len + lgt = len(items[i].chars) + s.copy_contents(items[i], result, 0, res_index, lgt) + res_index += lgt i += 1 return result @@ -633,11 +628,7 @@ def ll_stringslice_startonly(s1, start): len1 = len(s1.chars) newstr = s1.malloc(len1 - start) - j = 0 - while start < len1: - newstr.chars[j] = s1.chars[start] - start += 1 - j += 1 + s1.copy_contents(s1, newstr, start, 0, len1 - start) return newstr def ll_stringslice(s1, slice): @@ -648,20 +639,13 @@ return s1 stop = len(s1.chars) newstr = s1.malloc(stop - start) - j = 0 - while start < stop: - newstr.chars[j] = s1.chars[start] - start += 1 - j += 1 + s1.copy_contents(s1, newstr, start, 0, stop - start) return newstr def ll_stringslice_minusone(s1): newlen = len(s1.chars) - 1 newstr = s1.malloc(newlen) - j = 0 - while j < newlen: - newstr.chars[j] = s1.chars[j] - j += 1 + s1.copy_contents(s1, newstr, 0, 0, newlen) return newstr def ll_split_chr(LIST, s, c): @@ -681,22 +665,12 @@ while j < strlen: if chars[j] == c: item = items[resindex] = s.malloc(j - i) - newchars = item.chars - k = i - while k < j: - newchars[k - i] = chars[k] - k += 1 + item.copy_contents(s, item, i, 0, j - i) resindex += 1 i = j + 1 j += 1 item = items[resindex] = s.malloc(j - i) - newchars = item.chars - k = i - while k < j: - newchars[k - i] = chars[k] - k += 1 - resindex += 1 - + item.copy_contents(s, item, i, 0, j - i) return res def ll_replace_chr_chr(s, c1, c2): From fijal at codespeak.net Wed Apr 30 17:27:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 30 Apr 2008 17:27:17 +0200 (CEST) Subject: [pypy-svn] r54282 - pypy/branch/io-improvements/pypy/translator/goal Message-ID: <20080430152717.320D639B5B5@codespeak.net> Author: fijal Date: Wed Apr 30 17:27:16 2008 New Revision: 54282 Modified: pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py Log: make interface slightly different Modified: pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py (original) +++ pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py Wed Apr 30 17:27:16 2008 @@ -1,13 +1,13 @@ -from pypy.rlib.streamio import fdopen_as_stream +from pypy.rlib.streamio import open_file_as_stream def target(*args): return main, None def main(args): - search = args[0] - FD = 0 - s = fdopen_as_stream(FD, 'r', 1024) + search = args[1] + fname = args[2] + s = open_file_as_stream(fname, 'r', 1024) while True: next_line = s.readline() if not next_line: @@ -16,11 +16,16 @@ print next_line return 0 -def cpy_main(s): - for x in sys.stdin.readlines(): +def cpy_main(args): + s = args[1] + f = open(args[2]) + while True: + x = f.readline() + if not x: + break if s in x: print x if __name__ == '__main__': import sys - cpy_main(sys.argv[1]) + main(sys.argv) From arigo at codespeak.net Wed Apr 30 17:39:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 17:39:26 +0200 (CEST) Subject: [pypy-svn] r54283 - pypy/branch/faster-binop/pypy/objspace/std Message-ID: <20080430153926.90C8239B5C7@codespeak.net> Author: arigo Date: Wed Apr 30 17:39:24 2008 New Revision: 54283 Modified: pypy/branch/faster-binop/pypy/objspace/std/model.py Log: Missing optimization opportunity: "ANY" should not prevent a user subclass from being accepted in a shortcut mm call. Modified: pypy/branch/faster-binop/pypy/objspace/std/model.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/model.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/model.py Wed Apr 30 17:39:24 2008 @@ -260,7 +260,9 @@ subclslist = enum_interplevel_subclasses(cls) for subcls in subclslist: if cls in subcls.__bases__: # only direct subclasses - result[subcls] = [] + result[subcls] = [(W_Root, None)] + # W_Root="ANY" which always matches, + # even user subclasses self._typeorder_with_empty_usersubcls = result return self._typeorder_with_empty_usersubcls From arigo at codespeak.net Wed Apr 30 17:59:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 17:59:19 +0200 (CEST) Subject: [pypy-svn] r54284 - in pypy/branch/faster-binop/pypy: config doc/config objspace/std objspace/std/test Message-ID: <20080430155919.CFF8F39B5D2@codespeak.net> Author: arigo Date: Wed Apr 30 17:59:19 2008 New Revision: 54284 Added: pypy/branch/faster-binop/pypy/doc/config/objspace.std.builtinshortcut.txt (contents, props changed) pypy/branch/faster-binop/pypy/objspace/std/test/test_builtinshortcut.py (contents, props changed) Modified: pypy/branch/faster-binop/pypy/config/pypyoption.py pypy/branch/faster-binop/pypy/objspace/std/objspace.py pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py Log: Introduce this optimization as a config option. Modified: pypy/branch/faster-binop/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/faster-binop/pypy/config/pypyoption.py (original) +++ pypy/branch/faster-binop/pypy/config/pypyoption.py Wed Apr 30 17:59:19 2008 @@ -281,6 +281,9 @@ BoolOption("optimized_list_getitem", "special case the 'list[integer]' expressions", default=False), + BoolOption("builtinshortcut", + "a shortcut for operations between built-in types", + default=False), BoolOption("oldstyle", "specify whether the default metaclass should be classobj", @@ -308,8 +311,7 @@ ("objspace.std.withmethodcache", True), # ("objspace.std.withfastslice", True), ("objspace.std.withprebuiltchar", True), - ("objspace.std.optimized_int_add", True), - ("objspace.std.optimized_comparison_op", True), + ("objspace.std.builtinshortcut", True), ("translation.list_comprehension_operations",True), ], cmdline="--allopts --faassen", negation=False), Added: pypy/branch/faster-binop/pypy/doc/config/objspace.std.builtinshortcut.txt ============================================================================== --- (empty file) +++ pypy/branch/faster-binop/pypy/doc/config/objspace.std.builtinshortcut.txt Wed Apr 30 17:59:19 2008 @@ -0,0 +1,5 @@ +A shortcut speeding up primitive operations between built-in types. + +This is a space-time trade-off: at the moment, this option makes a +translated pypy-c executable bigger by about 1.7 MB. (This can probably +be improved with careful analysis.) Modified: pypy/branch/faster-binop/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/objspace.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/objspace.py Wed Apr 30 17:59:19 2008 @@ -277,12 +277,11 @@ return func_with_new_name(boundmethod, 'boundmethod_'+name) boundmethod = make_boundmethod() setattr(self, name, boundmethod) # store into 'space' instance - else: - # if config...: + elif self.config.objspace.std.builtinshortcut: from pypy.objspace.std import builtinshortcut builtinshortcut.install(self, mm) - if 1: # if config...: + if self.config.objspace.std.builtinshortcut: from pypy.objspace.std import builtinshortcut builtinshortcut.install_is_true(self, self.MM.nonzero, self.MM.len) Added: pypy/branch/faster-binop/pypy/objspace/std/test/test_builtinshortcut.py ============================================================================== --- (empty file) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_builtinshortcut.py Wed Apr 30 17:59:19 2008 @@ -0,0 +1,7 @@ +from pypy.objspace.std.test import test_userobject + +class AppTestUserObject(test_userobject.AppTestUserObject): + OPTIONS = {'objspace.std.builtinshortcut': True} + +class AppTestWithMultiMethodVersion2(test_userobject.AppTestWithMultiMethodVersion2): + OPTIONS = {'objspace.std.builtinshortcut': True} Modified: pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py Wed Apr 30 17:59:19 2008 @@ -1,6 +1,12 @@ class AppTestUserObject: + OPTIONS = {} # for test_builtinshortcut.py + + def setup_class(cls): + from pypy import conftest + cls.space = conftest.gettestobjspace(**cls.OPTIONS) + def test_emptyclass(self): class empty: pass inst = empty() @@ -196,6 +202,7 @@ class AppTestWithMultiMethodVersion2(AppTestUserObject): + OPTIONS = {} # for test_builtinshortcut.py def setup_class(cls): from pypy import conftest @@ -203,7 +210,8 @@ cls.prev_installer = multimethod.Installer multimethod.Installer = multimethod.InstallerVersion2 - cls.space = conftest.maketestobjspace() + config = conftest.make_config(conftest.option, **cls.OPTIONS) + cls.space = conftest.maketestobjspace(config) def teardown_class(cls): from pypy.objspace.std import multimethod From arigo at codespeak.net Wed Apr 30 19:03:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 19:03:33 +0200 (CEST) Subject: [pypy-svn] r54285 - in pypy/branch/faster-binop/pypy: config doc/config objspace objspace/std objspace/std/test Message-ID: <20080430170333.4E6D8498001@codespeak.net> Author: arigo Date: Wed Apr 30 19:03:32 2008 New Revision: 54285 Added: pypy/branch/faster-binop/pypy/doc/config/objspace.std.getattributeshortcut.txt (contents, props changed) Modified: pypy/branch/faster-binop/pypy/config/pypyoption.py pypy/branch/faster-binop/pypy/objspace/descroperation.py pypy/branch/faster-binop/pypy/objspace/std/callmethod.py pypy/branch/faster-binop/pypy/objspace/std/objspace.py pypy/branch/faster-binop/pypy/objspace/std/test/test_callmethod.py pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py pypy/branch/faster-binop/pypy/objspace/std/typeobject.py Log: Playing around with a possible getattr optimization. Not too happy about the code duplication. Modified: pypy/branch/faster-binop/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/faster-binop/pypy/config/pypyoption.py (original) +++ pypy/branch/faster-binop/pypy/config/pypyoption.py Wed Apr 30 19:03:32 2008 @@ -284,6 +284,9 @@ BoolOption("builtinshortcut", "a shortcut for operations between built-in types", default=False), + BoolOption("getattributeshortcut", + "track types that override __getattribute__", + default=False), BoolOption("oldstyle", "specify whether the default metaclass should be classobj", Added: pypy/branch/faster-binop/pypy/doc/config/objspace.std.getattributeshortcut.txt ============================================================================== --- (empty file) +++ pypy/branch/faster-binop/pypy/doc/config/objspace.std.getattributeshortcut.txt Wed Apr 30 19:03:32 2008 @@ -0,0 +1 @@ +Performance only: track types that override __getattribute__. Modified: pypy/branch/faster-binop/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/descroperation.py (original) +++ pypy/branch/faster-binop/pypy/objspace/descroperation.py Wed Apr 30 19:03:32 2008 @@ -129,7 +129,11 @@ return space.get_and_call_function(w_delete, w_descr, w_obj) def getattr(space, w_obj, w_name): + # may be overridden in StdObjSpace w_descr = space.lookup(w_obj, '__getattribute__') + return space._handle_getattribute(w_descr, w_obj, w_name) + + def _handle_getattribute(space, w_descr, w_obj, w_name): try: if w_descr is None: # obscure case raise OperationError(space.w_AttributeError, space.w_None) Modified: pypy/branch/faster-binop/pypy/objspace/std/callmethod.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/callmethod.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/callmethod.py Wed Apr 30 19:03:32 2008 @@ -32,10 +32,25 @@ w_obj = f.popvalue() w_name = f.getname_w(nameindex) w_value = None - w_getattribute = space.lookup(w_obj, '__getattribute__') - if w_getattribute is object_getattribute(space): + + if space.config.objspace.std.getattributeshortcut: + w_type = space.type(w_obj) + fastpath = w_type.uses_object_getattribute + # conservatively, 'uses_object_getattribute' can be False + # even if __getattribute__ was not overridden. In this + # case, the code below calls space.getattr(), which will + # set 'uses_object_getattribute' to True for the next time. + else: + w_getattribute = space.lookup(w_obj, '__getattribute__') + if w_getattribute is object_getattribute(space): + w_type = space.type(w_obj) + fastpath = True + else: + fastpath = False + + if fastpath: name = space.str_w(w_name) - w_descr = space.lookup(w_obj, name) + w_descr = w_type.lookup(name) if w_descr is None: # this handles directly the common case # module.function(args..) Modified: pypy/branch/faster-binop/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/objspace.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/objspace.py Wed Apr 30 19:03:32 2008 @@ -683,6 +683,51 @@ return w_obj.boolval return DescrOperation.is_true(self, w_obj) + def getattr(self, w_obj, w_name): + if not self.config.objspace.std.getattributeshortcut: + return DescrOperation.getattr(self, w_obj, w_name) + + # an optional shortcut for performance + from pypy.objspace.descroperation import raiseattrerror + from pypy.objspace.descroperation import object_getattribute + w_type = self.type(w_obj) + if not w_type.uses_object_getattribute: + # slow path: look for a custom __getattribute__ on the class + w_descr = w_type.lookup('__getattribute__') + # if it was not actually overriden in the class, we remember this + # fact for the next time. + if w_descr is object_getattribute(self): + w_type.uses_object_getattribute = True + return self._handle_getattribute(w_descr, w_obj, w_name) + + # fast path: XXX this is duplicating most of the logic + # from the default __getattribute__ and the getattr() method... + name = self.str_w(w_name) + w_descr = w_type.lookup(name) + e = None + if w_descr is not None: + if not self.is_data_descr(w_descr): + w_value = w_obj.getdictvalue_attr_is_in_class(self, w_name) + if w_value is not None: + return w_value + try: + return self.get(w_descr, w_obj) + except OperationError, e: + if not e.match(self, self.w_AttributeError): + raise + else: + w_value = w_obj.getdictvalue(self, w_name) + if w_value is not None: + return w_value + + w_descr = self.lookup(w_obj, '__getattr__') + if w_descr is not None: + return space.get_and_call_function(w_descr, w_obj, w_name) + elif e is not None: + raise e + else: + raiseattrerror(self, w_obj, name) + def finditem(self, w_obj, w_key): # performance shortcut to avoid creating the OperationError(KeyError) if type(w_obj) is self.DictObjectCls: Modified: pypy/branch/faster-binop/pypy/objspace/std/test/test_callmethod.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/test/test_callmethod.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_callmethod.py Wed Apr 30 19:03:32 2008 @@ -6,8 +6,10 @@ # The exec hacking is needed to have the code snippets compiled # by our own compiler, not CPython's + OPTIONS = {"objspace.opcodes.CALL_METHOD": True} + def setup_class(cls): - cls.space = gettestobjspace(**{"objspace.opcodes.CALL_METHOD": True}) + cls.space = gettestobjspace(**cls.OPTIONS) def test_call_method(self): exec """if 1: @@ -106,6 +108,11 @@ """ +class AppTestCallMethodWithGetattributeShortcut(AppTestCallMethod): + OPTIONS = AppTestCallMethod.OPTIONS.copy() + OPTIONS["objspace.std.getattributeshortcut"] = True + + class TestCallMethod: def setup_class(cls): Modified: pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py Wed Apr 30 19:03:32 2008 @@ -216,3 +216,8 @@ def teardown_class(cls): from pypy.objspace.std import multimethod multimethod.Installer = cls.prev_installer + + +class AppTestWithGetAttributeShortcut(AppTestUserObject): + OPTIONS = {"objspace.std.getattributeshortcut": True} + Modified: pypy/branch/faster-binop/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/typeobject.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/typeobject.py Wed Apr 30 19:03:32 2008 @@ -50,6 +50,10 @@ lazyloaders = {} # can be overridden by specific instances + uses_object_getattribute = False + # ^^^ for config.objspace.std.getattributeshortcut + # (False is a conservative default, fixed during real usage) + def __init__(w_self, space, name, bases_w, dict_w, overridetypedef=None): w_self.space = space @@ -221,6 +225,9 @@ def mutated(w_self): space = w_self.space + if space.config.objspace.std.getattributeshortcut: + w_self.uses_object_getattribute = False + # ^^^ conservative default, fixed during real usage if not space.config.objspace.std.withtypeversion: return # Invariant: version_tag is None if and only if From arigo at codespeak.net Wed Apr 30 19:10:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 19:10:52 +0200 (CEST) Subject: [pypy-svn] r54286 - pypy/branch/faster-binop/pypy/objspace/std Message-ID: <20080430171052.6438D498004@codespeak.net> Author: arigo Date: Wed Apr 30 19:10:51 2008 New Revision: 54286 Modified: pypy/branch/faster-binop/pypy/objspace/std/objspace.py Log: Typo. Modified: pypy/branch/faster-binop/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/objspace.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/objspace.py Wed Apr 30 19:10:51 2008 @@ -722,7 +722,7 @@ w_descr = self.lookup(w_obj, '__getattr__') if w_descr is not None: - return space.get_and_call_function(w_descr, w_obj, w_name) + return self.get_and_call_function(w_descr, w_obj, w_name) elif e is not None: raise e else: From arigo at codespeak.net Wed Apr 30 21:06:00 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:06:00 +0200 (CEST) Subject: [pypy-svn] r54287 - pypy/branch/faster-binop/pypy/config Message-ID: <20080430190600.A49C21684E9@codespeak.net> Author: arigo Date: Wed Apr 30 21:05:57 2008 New Revision: 54287 Modified: pypy/branch/faster-binop/pypy/config/pypyoption.py Log: objspace.std.getattributeshortcut is another big win, both on pystone and richards. Modified: pypy/branch/faster-binop/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/faster-binop/pypy/config/pypyoption.py (original) +++ pypy/branch/faster-binop/pypy/config/pypyoption.py Wed Apr 30 21:05:57 2008 @@ -315,6 +315,7 @@ # ("objspace.std.withfastslice", True), ("objspace.std.withprebuiltchar", True), ("objspace.std.builtinshortcut", True), + ("objspace.std.getattributeshortcut", True), ("translation.list_comprehension_operations",True), ], cmdline="--allopts --faassen", negation=False), From arigo at codespeak.net Wed Apr 30 21:12:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:12:49 +0200 (CEST) Subject: [pypy-svn] r54288 - pypy/branch/faster-binop/pypy/objspace/std Message-ID: <20080430191249.CAAFF1684F0@codespeak.net> Author: arigo Date: Wed Apr 30 21:12:47 2008 New Revision: 54288 Modified: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py Log: Comment out debugging print. Modified: pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py Wed Apr 30 21:12:47 2008 @@ -44,7 +44,7 @@ assert mm1 is mm return shortcut_method - print 'installing shortcut for:', name + #print 'installing shortcut for:', name assert hasattr(DescrOperation, name) base_method = getattr(space.__class__, name) From arigo at codespeak.net Wed Apr 30 21:16:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:16:31 +0200 (CEST) Subject: [pypy-svn] r54289 - pypy/branch/faster-binop/pypy/objspace/test Message-ID: <20080430191631.B59301684F0@codespeak.net> Author: arigo Date: Wed Apr 30 21:16:28 2008 New Revision: 54289 Modified: pypy/branch/faster-binop/pypy/objspace/test/test_descroperation.py Log: More tests to verify the correctness of builtinshortcut.py. Modified: pypy/branch/faster-binop/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/branch/faster-binop/pypy/objspace/test/test_descroperation.py (original) +++ pypy/branch/faster-binop/pypy/objspace/test/test_descroperation.py Wed Apr 30 21:16:28 2008 @@ -15,6 +15,11 @@ class AppTest_Descroperation: + OPTIONS = {} + + def setup_class(cls): + from pypy import conftest + cls.space = conftest.gettestobjspace(**cls.OPTIONS) def test_special_methods(self): class A(object): @@ -312,3 +317,7 @@ a3 = A() a4 = A() assert (a1 < a3) == (a1 < a4) == (a2 < a3) == (a2 < a4) + + +class AppTestWithBuiltinShortcut(AppTest_Descroperation): + OPTIONS = {'objspace.std.builtinshortcut': True} From arigo at codespeak.net Wed Apr 30 21:21:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:21:15 +0200 (CEST) Subject: [pypy-svn] r54290 - pypy/dist/pypy/interpreter Message-ID: <20080430192115.90A811684F3@codespeak.net> Author: arigo Date: Wed Apr 30 21:21:14 2008 New Revision: 54290 Added: pypy/dist/pypy/interpreter/typedef.py.merge.tmp - copied, changed from r54289, pypy/dist/pypy/interpreter/typedef.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/faster-binop/pypy/interpreter/typedef.py revisions 54263 to 54289: ------------------------------------------------------------------------ r54274 | arigo | 2008-04-30 15:42:06 +0200 (Wed, 30 Apr 2008) | 2 lines Merge r54273 from the trunk. ------------------------------------------------------------------------ r54269 | arigo | 2008-04-30 14:02:39 +0200 (Wed, 30 Apr 2008) | 2 lines A first attempt. Idea described in builtinshortcut.py. ------------------------------------------------------------------------ r54264 | arigo | 2008-04-30 12:24:49 +0200 (Wed, 30 Apr 2008) | 3 lines A branch in which to try to improve the speed of binary operations between objects of a built-in type. ------------------------------------------------------------------------ From arigo at codespeak.net Wed Apr 30 21:21:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:21:17 +0200 (CEST) Subject: [pypy-svn] r54291 - pypy/dist/pypy/objspace/std Message-ID: <20080430192117.1C7B51684F3@codespeak.net> Author: arigo Date: Wed Apr 30 21:21:17 2008 New Revision: 54291 Added: pypy/dist/pypy/objspace/std/objspace.py.merge.tmp - copied, changed from r54289, pypy/dist/pypy/objspace/std/objspace.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/faster-binop/pypy/objspace/std/objspace.py revisions 54263 to 54289: ------------------------------------------------------------------------ r54286 | arigo | 2008-04-30 19:10:51 +0200 (Wed, 30 Apr 2008) | 2 lines Typo. ------------------------------------------------------------------------ r54285 | arigo | 2008-04-30 19:03:32 +0200 (Wed, 30 Apr 2008) | 3 lines Playing around with a possible getattr optimization. Not too happy about the code duplication. ------------------------------------------------------------------------ r54284 | arigo | 2008-04-30 17:59:19 +0200 (Wed, 30 Apr 2008) | 2 lines Introduce this optimization as a config option. ------------------------------------------------------------------------ r54270 | arigo | 2008-04-30 14:57:22 +0200 (Wed, 30 Apr 2008) | 3 lines builtinshortcut support for most of the remaining operations as well as is_true(). ------------------------------------------------------------------------ r54269 | arigo | 2008-04-30 14:02:39 +0200 (Wed, 30 Apr 2008) | 2 lines A first attempt. Idea described in builtinshortcut.py. ------------------------------------------------------------------------ r54264 | arigo | 2008-04-30 12:24:49 +0200 (Wed, 30 Apr 2008) | 3 lines A branch in which to try to improve the speed of binary operations between objects of a built-in type. ------------------------------------------------------------------------ From arigo at codespeak.net Wed Apr 30 21:21:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:21:22 +0200 (CEST) Subject: [pypy-svn] r54292 - pypy/dist/pypy/objspace/std Message-ID: <20080430192122.597E01684F7@codespeak.net> Author: arigo Date: Wed Apr 30 21:21:21 2008 New Revision: 54292 Added: pypy/dist/pypy/objspace/std/model.py.merge.tmp - copied, changed from r54289, pypy/dist/pypy/objspace/std/model.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/faster-binop/pypy/objspace/std/model.py revisions 54263 to 54289: ------------------------------------------------------------------------ r54283 | arigo | 2008-04-30 17:39:24 +0200 (Wed, 30 Apr 2008) | 3 lines Missing optimization opportunity: "ANY" should not prevent a user subclass from being accepted in a shortcut mm call. ------------------------------------------------------------------------ r54269 | arigo | 2008-04-30 14:02:39 +0200 (Wed, 30 Apr 2008) | 2 lines A first attempt. Idea described in builtinshortcut.py. ------------------------------------------------------------------------ r54264 | arigo | 2008-04-30 12:24:49 +0200 (Wed, 30 Apr 2008) | 3 lines A branch in which to try to improve the speed of binary operations between objects of a built-in type. ------------------------------------------------------------------------ From arigo at codespeak.net Wed Apr 30 21:24:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:24:32 +0200 (CEST) Subject: [pypy-svn] r54293 - in pypy/dist/pypy: config doc interpreter objspace objspace/std objspace/std/test objspace/test Message-ID: <20080430192432.61A54168520@codespeak.net> Author: arigo Date: Wed Apr 30 21:24:31 2008 New Revision: 54293 Added: pypy/dist/pypy/config/ - copied from r54292, pypy/branch/faster-binop/pypy/config/ pypy/dist/pypy/doc/ - copied from r54292, pypy/branch/faster-binop/pypy/doc/ pypy/dist/pypy/interpreter/typedef.py - copied unchanged from r54292, pypy/dist/pypy/interpreter/typedef.py.merge.tmp pypy/dist/pypy/objspace/descroperation.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/descroperation.py pypy/dist/pypy/objspace/std/builtinshortcut.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/builtinshortcut.py pypy/dist/pypy/objspace/std/callmethod.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/callmethod.py pypy/dist/pypy/objspace/std/floatobject.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/floatobject.py pypy/dist/pypy/objspace/std/model.py - copied unchanged from r54292, pypy/dist/pypy/objspace/std/model.py.merge.tmp pypy/dist/pypy/objspace/std/objspace.py - copied unchanged from r54292, pypy/dist/pypy/objspace/std/objspace.py.merge.tmp pypy/dist/pypy/objspace/std/test/test_builtinshortcut.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/test/test_builtinshortcut.py pypy/dist/pypy/objspace/std/test/test_callmethod.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/test/test_callmethod.py pypy/dist/pypy/objspace/std/test/test_floatobject.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/test/test_floatobject.py pypy/dist/pypy/objspace/std/test/test_userobject.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/test/test_userobject.py pypy/dist/pypy/objspace/std/typeobject.py - copied unchanged from r54292, pypy/branch/faster-binop/pypy/objspace/std/typeobject.py pypy/dist/pypy/objspace/test/ - copied from r54292, pypy/branch/faster-binop/pypy/objspace/test/ Removed: pypy/dist/pypy/interpreter/typedef.py.merge.tmp pypy/dist/pypy/objspace/std/model.py.merge.tmp pypy/dist/pypy/objspace/std/objspace.py.merge.tmp Log: Merge the "faster-binop" branch, with two good speed-ups (both optional and enabled by --faassen): * use direct multimethod dispatch for operations involving only built-in objects. * speed up space.getattr() by tracking for each app-level type if __getattribute__ is overridden or not. From arigo at codespeak.net Wed Apr 30 21:25:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 30 Apr 2008 21:25:03 +0200 (CEST) Subject: [pypy-svn] r54294 - pypy/branch/faster-binop Message-ID: <20080430192503.1D6DE16851E@codespeak.net> Author: arigo Date: Wed Apr 30 21:25:02 2008 New Revision: 54294 Removed: pypy/branch/faster-binop/ Log: Delete merged branch.