From fijal at codespeak.net Sun Mar 1 11:13:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 11:13:14 +0100 (CET) Subject: [pypy-svn] r62283 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090301101314.660451684BD@codespeak.net> Author: fijal Date: Sun Mar 1 11:13:11 2009 New Revision: 62283 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: remove the hack Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sun Mar 1 11:13:11 2009 @@ -284,11 +284,6 @@ args = () for i, ARG in portalfunc_ARGS: v = unwrap(ARG, e.args[i]) - # HACK for x86 backend always returning int - #if isinstance(ARG, lltype.Ptr) and type(v) is int: - # v = self.metainterp.cpu.cast_int_to_gcref(v) - #if lltype.typeOf(v) == llmemory.GCREF: - # v = lltype.cast_opaque_ptr(ARG, v) args = args + (v,) except DoneWithThisFrame, e: return unwrap(RESULT, e.resultbox) From fijal at codespeak.net Sun Mar 1 11:13:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 11:13:43 +0100 (CET) Subject: [pypy-svn] r62284 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090301101343.9C6341684C4@codespeak.net> Author: fijal Date: Sun Mar 1 11:13:43 2009 New Revision: 62284 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: simplify things. It's still disabled, but at least we have less code Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sun Mar 1 11:13:43 2009 @@ -848,24 +848,10 @@ op_listnonzero = op_listop_return def op_newlist(self, ll_newlist, lgt, default_val=None): - res = self.do_call(ll_newlist, lgt) - if (default_val is not None and - isinstance(lltype.typeOf(default_val), lltype.Ptr)): - if hasattr(res, 'items'): - TP = lltype.typeOf(res.items).TO.OF - else: - TP = lltype.typeOf(res).TO.OF - if default_val: - default_val = lltype.cast_opaque_ptr(TP, res) - else: - default_val = lltype.nullptr(TP.TO) if default_val is not None: - if hasattr(res, 'items'): - items = res.items - else: - items = res - for i in range(len(items)): - items[i] = default_val + res = self.do_call(ll_newlist, lgt, default_val) + else: + res = self.do_call(ll_newlist, lgt) return res for _opname in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', From fijal at codespeak.net Sun Mar 1 11:14:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 11:14:14 +0100 (CET) Subject: [pypy-svn] r62285 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090301101414.3C2A81684CF@codespeak.net> Author: fijal Date: Sun Mar 1 11:14:13 2009 New Revision: 62285 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py Log: progress with x86 backend. More tests and pass more stuff Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sun Mar 1 11:14:13 2009 @@ -26,6 +26,9 @@ self.mc2 = None self.rtyper = cpu.rtyper self.malloc_func_addr = 0 + self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, + zero=True, flavor='raw') + self._exception_addr = cpu.cast_ptr_to_int(self._exception_data) def make_sure_mc_exists(self): if self.mc is None: @@ -36,7 +39,8 @@ self.generic_return_addr = self.assemble_generic_return() # the address of the function called by 'new': directly use # Boehm's GC_malloc function. - self.malloc_func_addr = gc_malloc_fnaddr() + if self.malloc_func_addr == 0: + self.malloc_func_addr = gc_malloc_fnaddr() def assemble(self, operations, guard_op, verbose=False): self.verbose = verbose @@ -178,15 +182,21 @@ getattr(self.mc, asmop)(arglocs[0], arglocs[1]) return genop_binary - def _cmpop(cond): + def _cmpop(cond, rev_cond): def genop_cmp(self, op, arglocs, result_loc): - self.mc.CMP(arglocs[0], arglocs[1]) - self.mc.MOV(result_loc, imm8(0)) - getattr(self.mc, 'SET' + cond)(lower_byte(result_loc)) + if isinstance(op.args[0], Const): + self.mc.CMP(arglocs[1], arglocs[0]) + self.mc.MOV(result_loc, imm8(0)) + getattr(self.mc, 'SET' + rev_cond)(lower_byte(result_loc)) + else: + self.mc.CMP(arglocs[0], arglocs[1]) + self.mc.MOV(result_loc, imm8(0)) + getattr(self.mc, 'SET' + cond)(lower_byte(result_loc)) return genop_cmp def call(self, addr, args, res): - for arg in args: + for i in range(len(args)): + arg = args[i] self.mc.PUSH(arg) self.mc.CALL(rel32(addr)) self.mc.ADD(esp, imm(len(args) * WORD)) @@ -198,12 +208,12 @@ genop_int_mul = _binaryop("IMUL", True) genop_int_and = _binaryop("AND", True) - genop_int_lt = _cmpop("L") - genop_int_le = _cmpop("LE") - genop_int_eq = _cmpop("E") - genop_int_ne = _cmpop("NE") - genop_int_gt = _cmpop("G") - genop_int_ge = _cmpop("GE") + genop_int_lt = _cmpop("L", "G") + genop_int_le = _cmpop("LE", "GE") + genop_int_eq = _cmpop("E", "NE") + genop_int_ne = _cmpop("NE", "E") + genop_int_gt = _cmpop("G", "L") + genop_int_ge = _cmpop("GE", "LE") # for now all chars are being considered ints, although we should make # a difference at some point @@ -273,24 +283,43 @@ loc_size = arglocs[0] self.call(self.malloc_func_addr, [loc_size], eax) - def genop_newstr(self, op, arglocs, result_loc): + def genop_malloc_varsize(self, op, arglocs, result_loc): loc_size = arglocs[0] self.call(self.malloc_func_addr, [loc_size], eax) def genop_getfield_gc(self, op, arglocs, resloc): - base_loc, ofs_loc = arglocs - #if isinstance(op.args[0], Constant): - # x, _ = self.cpu.get_value_as_int(op.args[0].value) - # pos = mem(None, offset + x) - #else: - # ... - self.mc.MOV(resloc, addr_add(base_loc, ofs_loc)) + base_loc, ofs_loc, size_loc = arglocs + size = size_loc.value + if size == 1: + self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc)) + elif size == WORD: + self.mc.MOV(resloc, addr_add(base_loc, ofs_loc)) + else: + raise NotImplementedError("getfield size = %d" % size) + + def genop_getarrayitem_gc(self, op, arglocs, resloc): + base_loc, ofs_loc, scale, ofs = arglocs + self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, ofs.value, scale.value)) genop_getfield_raw = genop_getfield_gc def genop_setfield_gc(self, op, arglocs): - base_loc, ofs_loc, value_loc = arglocs - self.mc.MOV(addr_add(base_loc, ofs_loc), value_loc) + base_loc, ofs_loc, size_loc, value_loc = arglocs + size = size_loc.value + if size == WORD: + self.mc.MOV(addr_add(base_loc, ofs_loc), value_loc) + elif size == 2: + raise NotImplementedError("shorts and friends") + self.mc.MOV(addr16_add(base_loc, ofs_loc), lower_2_bytes(value_loc)) + elif size == 1: + self.mc.MOV(addr8_add(base_loc, ofs_loc), lower_byte(value_loc)) + else: + raise NotImplementedError("Addr size %d" % size) + + def genop_setarrayitem_gc(self, op, arglocs): + base_loc, ofs_loc, value_loc, scale_loc, baseofs = arglocs + self.mc.MOV(addr_add(base_loc, ofs_loc, baseofs.value, scale_loc.value), + value_loc) def genop_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs @@ -311,21 +340,8 @@ self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize)) def genop_merge_point(self, op, locs): - # encode the current machine code position and the current stack - # position of the live values into a flat array of c_long's. - # XXX update comment - # we load constants into arguments op.position = self.mc.tell() op.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(op) - #nb_args = len(op.args) - #array_type = ctypes.c_long * (2 + nb_args) - #label = array_type() - #label[0] = nb_args - #label[1] = self.mc.tell() - #for i in range(nb_args): - # v = op.args[i] - # label[2 + i] = self.stack_positions[v] - #op._asm_label = label genop_catch = genop_merge_point @@ -348,7 +364,20 @@ self.implement_guard(op, self.mc.JZ, locs[1:]) def genop_guard_no_exception(self, op, locs): - pass # XXX # exception handling + loc = locs[0] + self.mc.MOV(loc, heap(self._exception_addr)) + self.mc.TEST(loc, loc) + self.implement_guard(op, self.mc.JNZ, locs[1:]) + + def genop_guard_exception(self, op, locs, resloc): + loc = locs[0] + loc1 = locs[1] + self.mc.MOV(loc1, heap(self._exception_addr)) + self.mc.CMP(loc1, loc) + self.implement_guard(op, self.mc.JNE, locs[2:]) + if resloc is not None: + self.mc.MOV(resloc, addr_add(imm(self._exception_addr), imm(WORD))) + self.mc.MOV(heap(self._exception_addr), imm(0)) def genop_guard_false(self, op, locs): loc = locs[0] @@ -508,29 +537,44 @@ genop_discard_dict['call_void'] = Assembler386.genop_call_void -def addr_add(reg_or_imm1, reg_or_imm2, offset=0): +def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): + if isinstance(reg_or_imm1, IMM32): + if isinstance(reg_or_imm2, IMM32): + return heap(reg_or_imm1.value + offset + + (reg_or_imm2.value << scale)) + else: + return mem(reg_or_imm2, (reg_or_imm1.value << scale) + offset) + else: + if isinstance(reg_or_imm2, IMM32): + return mem(reg_or_imm1, offset + (reg_or_imm2.value << scale)) + else: + return memSIB(reg_or_imm1, reg_or_imm2, scale, offset) + +def addr8_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): if isinstance(reg_or_imm1, IMM32): if isinstance(reg_or_imm2, IMM32): - return heap(reg_or_imm1.value + offset + reg_or_imm2.value) + return heap8(reg_or_imm1.value + (offset << scale) + + reg_or_imm2.value) else: - return mem(reg_or_imm2, reg_or_imm1.value + offset) + return mem8(reg_or_imm2, reg_or_imm1.value + (offset << scale)) else: if isinstance(reg_or_imm2, IMM32): - return mem(reg_or_imm1, offset + reg_or_imm2.value) + return mem8(reg_or_imm1, (offset << scale) + reg_or_imm2.value) else: - return memSIB(reg_or_imm1, reg_or_imm2, 0, offset) + return memSIB8(reg_or_imm1, reg_or_imm2, scale, offset) -def addr8_add(reg_or_imm1, reg_or_imm2, offset=0): +def addr16_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): if isinstance(reg_or_imm1, IMM32): if isinstance(reg_or_imm2, IMM32): - return heap8(reg_or_imm1.value + offset + reg_or_imm2.value) + return heap16(reg_or_imm1.value + (offset << scale) + + reg_or_imm2.value) else: - return mem8(reg_or_imm2, reg_or_imm1.value + offset) + return mem16(reg_or_imm2, reg_or_imm1.value + (offset << scale)) else: if isinstance(reg_or_imm2, IMM32): - return mem8(reg_or_imm1, offset + reg_or_imm2.value) + return mem16(reg_or_imm1, (offset << scale) + reg_or_imm2.value) else: - return memSIB8(reg_or_imm1, reg_or_imm2, 0, offset) + return memSIB16(reg_or_imm1, reg_or_imm2, scale, offset) def addr_add_const(reg_or_imm1, offset): if isinstance(reg_or_imm1, IMM32): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Sun Mar 1 11:14:13 2009 @@ -9,6 +9,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.jit.backend.x86 import symbolic +from pypy.jit.metainterp.heaptracker import operations_without_side_effects # esi edi and ebp can be added to this list, provided they're correctly # saved and restored @@ -200,8 +201,19 @@ if op.opname.startswith('#'): continue self.position = i - new_ops += opdict[op.opname](self, op) - self._check_invariants() + canfold = True + if op.opname in operations_without_side_effects: + for result in op.results: + if result in self.longevity: + # means it's never used + canfold = False + break + else: + canfold = False + if not canfold: + new_ops += opdict[op.opname](self, op) + self.eventually_free_vars(op.results) + self._check_invariants() return new_ops def _compute_vars_longevity(self, operations): @@ -266,10 +278,13 @@ def return_constant(self, v, forbidden_vars, selected_reg=None, imm_fine=True): assert isinstance(v, Const) - if selected_reg: + if selected_reg or not imm_fine: # this means we cannot have it in IMM, eh if selected_reg in self.free_regs: return selected_reg, [Load(v, convert_to_imm(v), selected_reg)] + if selected_reg is None and self.free_regs: + loc = self.free_regs.pop() + return loc, [Load(v, convert_to_imm(v), loc)] v_to_spill = self.pick_variable_to_spill(v, forbidden_vars, selected_reg) if v_to_spill not in self.stack_bindings or v_to_spill in self.dirty_stack: newloc = self.stack_loc(v_to_spill) @@ -314,6 +329,8 @@ locs = [] for arg in guard_op.liveboxes: if isinstance(arg, Box): + if arg not in self.stack_bindings: + self.dirty_stack[arg] = True stacklocs.append(self.stack_loc(arg).position) locs.append(self.loc(arg)) if not we_are_translated(): @@ -353,7 +370,7 @@ def eventually_free_var(self, v): if isinstance(v, Const) or v not in self.reg_bindings: return - if self.longevity[v][1] <= self.position: + if v not in self.longevity or self.longevity[v][1] <= self.position: self.free_regs.append(self.reg_bindings[v]) del self.reg_bindings[v] @@ -401,10 +418,19 @@ """ Make sure that result is in the same register as v and v is copied away if it's further used """ + if isinstance(v, Const): + loc, ops = self.make_sure_var_in_reg(v, forbidden_vars, + selected_reg, + imm_fine=False) + assert not isinstance(loc, IMM8) + self.reg_bindings[result_v] = loc + self.free_regs = [reg for reg in self.free_regs if reg is not loc] + return loc, ops ops = [] if v in self.reg_bindings and selected_reg: _, ops = self.make_sure_var_in_reg(v, forbidden_vars, selected_reg) elif v not in self.reg_bindings: + assert v not in self.dirty_stack prev_loc = self.stack_bindings[v] loc, o = self.force_allocate_reg(v, forbidden_vars, selected_reg) ops += o @@ -438,6 +464,8 @@ reg = self.try_allocate_reg(arg) if reg: locs[i] = reg + # it's better to say here that we're always in dirty stack + # than worry at the jump point self.dirty_stack[arg] = True else: locs[i] = loc @@ -469,13 +497,32 @@ self.eventually_free_vars(op.liveboxes) return ops + [PerformDiscard(op, [loc] + locs)] + consider_guard_true = consider_guard + consider_guard_false = consider_guard + def consider_guard_no_exception(self, op): + box = TempBox() + loc, ops = self.force_allocate_reg(box, []) locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes) - return [] + self.eventually_free_var(box) + return ops + [PerformDiscard(op, [loc] + locs)] - consider_guard_true = consider_guard - consider_guard_false = consider_guard + def consider_guard_exception(self, op): + loc, ops = self.make_sure_var_in_reg(op.args[0], []) + box = TempBox() + loc1, ops1 = self.force_allocate_reg(box, op.args) + if op.results[0] in self.longevity: + # this means, is it ever used + resloc, ops2 = self.force_allocate_reg(op.results[0], + op.args + [box]) + else: + resloc, ops2 = None, [] + locs = self._locs_from_liveboxes(op) + self.eventually_free_vars(op.liveboxes) + self.eventually_free_vars(op.args) + self.eventually_free_var(box) + return ops + ops1 + ops2 + [Perform(op, [loc, loc1] + locs, resloc)] #def consider_guard2(self, op): # loc1, ops1 = self.make_sure_var_in_reg(op.args[0], []) @@ -539,6 +586,11 @@ consider_int_sub = consider_binop consider_int_and = consider_binop + def consider_binop_ovf(self, op): + xxx + + consider_int_mul_ovf = consider_binop_ovf + def consider_int_neg(self, op): res, ops = self.force_result_in_reg(op.results[0], op.args[0], []) return ops + [Perform(op, [res], res)] @@ -597,16 +649,29 @@ consider_int_ne = consider_compop consider_int_eq = consider_compop + def sync_var(self, v): + ops = [] + if v in self.dirty_stack or v not in self.stack_bindings: + reg = self.reg_bindings[v] + ops.append(Store(v, reg, self.stack_loc(v))) + try: + del self.dirty_stack[v] + except KeyError: + pass + # otherwise it's clean + return ops + + def sync_var_if_survives(self, v): + if self.longevity[v][1] > self.position: + return self.sync_var(v) + return [] + def _call(self, op, arglocs, force_store=[]): ops = [] # we need to store all variables which are now in registers for v, reg in self.reg_bindings.items(): if self.longevity[v][1] > self.position or v in force_store: - ops.append(Store(v, reg, self.stack_loc(v))) - try: - del self.dirty_stack[v] - except KeyError: - pass + ops += self.sync_var(v) self.reg_bindings = newcheckdict() if op.results: self.reg_bindings = {op.results[0]: eax} @@ -632,18 +697,45 @@ return self._call(op, [self.loc(arg) for arg in op.args]) def consider_newstr(self, op): - ops = self._call(op, [self.loc(arg) for arg in op.args], - [op.args[0]]) - loc, ops1 = self.make_sure_var_in_reg(op.args[0], []) - assert self.loc(op.results[0]) == eax - # now we have to reload length to some reasonable place - # XXX hardcoded length offset - self.eventually_free_var(op.args[0]) ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] - res = ops + ops1 + [PerformDiscard(ResOperation('setfield_gc', [], []), - [eax, imm(ofs), loc])] + ofs_items = symbolic.get_field_token(rstr.STR.chars, 'items')[0] + ofs_length = symbolic.get_field_token(rstr.STR.chars, 'length')[0] + return self._malloc_varsize(ofs, ofs_items, ofs_length, 0, op.args[0], + op.results[0]) + + def _malloc_varsize(self, ofs, ofs_items, ofs_length, size, v, res_v): + if isinstance(v, Box): + loc, ops0 = self.make_sure_var_in_reg(v, [v]) + ops0 += self.sync_var(v) + if size != 0: + # XXX lshift? + ops0.append(Perform(ResOperation('int_mul', [], []), + [loc, imm(1 << size)], loc)) + ops0.append(Perform(ResOperation('int_add', [], []), + [loc, imm(ofs + ofs_items)], loc)) + else: + ops0 = [] + loc = imm(ofs + ofs_items + (v.getint() << size)) + ops = self._call(ResOperation('malloc_varsize', [v], [res_v]) + , [loc], [v]) + loc, ops1 = self.make_sure_var_in_reg(v, [res_v]) + assert self.loc(res_v) == eax + # now we have to reload length to some reasonable place + self.eventually_free_var(v) + res = (ops0 + ops + ops1 + + [PerformDiscard(ResOperation('setfield_gc', [], []), + [eax, imm(ofs + ofs_length), imm(WORD), loc])]) return res + + def consider_new_array(self, op): + arraydescr = op.args[0].getint() + assert arraydescr + size_of_field = arraydescr >> 16 + ofs = arraydescr & 0xffff + return self._malloc_varsize(0, ofs, 0, size_of_field, op.args[1], + op.results[0]) + def consider_oononnull(self, op): argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) @@ -651,27 +743,69 @@ assert reg return [Perform(op, [argloc], reg)] + def _unpack_fielddescr(self, fielddescr): + if fielddescr < 0: + fielddescr = -fielddescr + ofs_loc = imm(fielddescr & 0xffff) + size_loc = imm(fielddescr >> 16) + return ofs_loc, size_loc + def consider_setfield_gc(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) + ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) + value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) + self.eventually_free_vars([op.args[0], op.args[1], op.args[2]]) + return (ops0 + ops2 + + [PerformDiscard(op, [base_loc, ofs_loc, size_loc, value_loc])]) + + def consider_strsetitem(self, op): + base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) self.eventually_free_vars([op.args[0], op.args[1], op.args[2]]) return (ops0 + ops1 + ops2 + [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) - # XXX location is a bit smaller, but we don't care too much - consider_strsetitem = consider_setfield_gc + def consider_setarrayitem_gc(self, op): + arraydescr = op.args[1].getint() + assert arraydescr + scale = arraydescr >> 16 + ofs = arraydescr & 0xffff + assert scale == 2 + args = [op.args[0], op.args[2], op.args[3]] + base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) + ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[2], args) + value_loc, ops2 = self.make_sure_var_in_reg(op.args[3], args) + self.eventually_free_vars(op.args) + return (ops0 + ops2 + ops1 + + [PerformDiscard(op, [base_loc, ofs_loc, value_loc, + imm(scale), imm(ofs)])]) def consider_getfield_gc(self, op): + ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) result_loc, more_ops = self.force_allocate_reg(op.results[0], []) + return (ops0 + more_ops + + [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) + + def consider_getarrayitem_gc(self, op): + arraydescr = op.args[1].getint() + assert arraydescr + scale = arraydescr >> 16 + ofs = arraydescr & 0xffff + assert scale == 2 + args = [op.args[0], op.args[2]] + base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) + ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[2], args) + self.eventually_free_vars(op.args) + result_loc, more_ops = self.force_allocate_reg(op.results[0], []) return (ops0 + ops1 + more_ops + - [Perform(op, [base_loc, ofs_loc], result_loc)]) + [Perform(op, [base_loc, ofs_loc, imm(scale), imm(ofs)], + result_loc)]) consider_getfield_raw = consider_getfield_gc - consider_getfield_raw = consider_getfield_gc + def _consider_listop(self, op): return self._call(op, [self.loc(arg) for arg in op.args]) @@ -808,6 +942,10 @@ def lower_byte(reg): # argh + if isinstance(reg, MODRM): + return reg + if isinstance(reg, IMM32): + return imm8(reg.value) if reg is eax: return al elif reg is ebx: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 1 11:14:13 2009 @@ -2,13 +2,13 @@ import ctypes import py from pypy.rpython.lltypesystem import lltype, llmemory, ll2ctypes, rffi -from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize from pypy.rlib.objectmodel import we_are_translated, keepalive_until_here from pypy.annotation import model as annmodel - +from pypy.rpython.lltypesystem import rclass from pypy.jit.metainterp import history from pypy.jit.metainterp.history import (MergePoint, ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) @@ -27,9 +27,19 @@ self.stats = stats self.translate_support_code = translate_support_code if translate_support_code: + assert False, "need exception support" self.mixlevelann = MixLevelHelperAnnotator(rtyper) else: self.current_interpreter = LLInterpreter(self.rtyper) + + def _store_exception(lle): + tp_i = self.cast_ptr_to_int(lle.args[0]) + v_i = self.cast_gcref_to_int(lle.args[1]) + self.assembler._exception_data[0] = tp_i + self.assembler._exception_data[1] = v_i + + self.current_interpreter._store_exception = _store_exception + TP = lltype.GcArray(llmemory.GCREF) self.keepalives = [] self.keepalives_index = 0 self._bootstrap_cache = {} @@ -102,6 +112,14 @@ def set_meta_interp(self, metainterp): self.metainterp = metainterp + def get_exception(self, frame): + res = self.assembler._exception_data[0] + self.assembler._exception_data[0] = 0 + return res + + def get_exc_value(self, frame): + return self.cast_int_to_gcref(self.assembler._exception_data[1]) + def execute_operation(self, opname, valueboxes, result_type): # mostly a hack: fall back to compiling and executing the single # operation. @@ -109,13 +127,26 @@ return None key = [opname, result_type] for valuebox in valueboxes: - key.append(valuebox.type) - mp = self.get_compiled_single_operation(key) + if isinstance(valuebox, Box): + key.append(valuebox.type) + else: + key.append(repr(valuebox)) # XXX not RPython + mp = self.get_compiled_single_operation(key, valueboxes) res = self.execute_operations_in_new_frame(opname, mp, valueboxes, result_type) + if self.assembler._exception_data[0] != 0: + TP = lltype.Ptr(rclass.OBJECT_VTABLE) + TP_V = lltype.Ptr(rclass.OBJECT) + exc_t_a = self.cast_int_to_adr(self.assembler._exception_data[0]) + exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) + exc_v_a = self.cast_int_to_gcref(self.assembler._exception_data[1]) + exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) + # clean up the exception + self.assembler._exception_data[0] = 0 + raise LLException(exc_type, exc_val) return res - def get_compiled_single_operation(self, key): + def get_compiled_single_operation(self, key, valueboxes): real_key = ','.join([str(k) for k in key]) try: return self._compiled_ops[real_key] @@ -123,14 +154,20 @@ opname = key[0] result_type = key[1] livevarlist = [] - for type in key[2:]: - if type == 'int': - box = history.BoxInt() - elif type == 'ptr': - box = history.BoxPtr() + i = 0 + # clonebox below is necessary, because sometimes we know + # that the value is constant (ie ArrayDescr), but we're not + # going to get the contant. So instead we get a box with correct + # value + for box in valueboxes: + if box.type == 'int': + box = valueboxes[i].clonebox() + elif box.type == 'ptr': + box = valueboxes[i].clonebox() else: raise ValueError(type) livevarlist.append(box) + i += 1 mp = MergePoint('merge_point', livevarlist, []) if result_type == 'void': results = [] @@ -295,10 +332,6 @@ numof = sizeof addresssuffix = str(symbolic.get_size(llmemory.Address)) - def offsetof(self, S, fieldname): - ofs, size = symbolic.get_field_token(S, fieldname) - return ofs - def itemoffsetof(self, A): basesize, itemsize, ofs_length = symbolic.get_array_token(A) return basesize @@ -313,13 +346,34 @@ return res @staticmethod + def cast_ptr_to_int(x): + adr = llmemory.cast_ptr_to_adr(x) + return CPU386.cast_adr_to_int(adr) + + @staticmethod + def arraydescrof(A): + assert isinstance(A, lltype.GcArray) + basesize, itemsize, ofs_length = symbolic.get_array_token(A) + assert ofs_length == 0 + counter = 0 + while itemsize != 1: + itemsize >>= 1 + counter += 1 + return basesize + counter * 0x10000 + + @staticmethod def fielddescrof(S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname) - assert size == 4 - return ofs + val = (size << 16) + ofs + if (isinstance(getattr(S, fieldname), lltype.Ptr) and + getattr(S, fieldname).TO._gckind == 'gc'): + return ~val + return val @staticmethod def typefor(fielddesc): + if fielddesc < 0: + return "ptr" return "int" @staticmethod Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py Sun Mar 1 11:14:13 2009 @@ -3,8 +3,6 @@ from pypy.jit.backend.x86.test.test_basic import Jit386Mixin from pypy.jit.metainterp.test.test_exception import ExceptionTests -py.test.skip("exceptions are broken") - class TestExceptions(Jit386Mixin, ExceptionTests): # for the individual tests see # ====> ../../../metainterp/test/test_exception.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Sun Mar 1 11:14:13 2009 @@ -99,5 +99,32 @@ assert res.value == 42 assert meta_interp.recordedvalues == f() -def test_xxx(): - pass +def test_loop_with_const_and_var_swap(): + meta_interp = FakeMetaInterp() + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.set_meta_interp(meta_interp) + x = BoxInt(0) + y = BoxInt(0) + z = BoxInt(0) + i = BoxInt(0) + i0 = BoxInt(0) + v0 = BoxInt(0) + operations = [ + MergePoint('merge_point', [x, y, z, i], []), + ResOperation('int_sub', [i, ConstInt(1)], [i0]), + ResOperation('int_gt', [i0, ConstInt(0)], [v0]), + GuardOp('guard_true', [v0], []), + ResOperation('jump', [x, z, y, i0], []), + ] + operations[-1].jump_target = operations[0] + operations[3].liveboxes = [v0, x, y, z, i0] + + cpu.compile_operations(operations) + + res = cpu.execute_operations_in_new_frame('foo', operations[0], + [BoxInt(1), BoxInt(2), + BoxInt(3), BoxInt(10)], + 'int') + assert res.value == 42 + assert meta_interp.recordedvalues == [0, 1, 3, 2, 0] + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Sun Mar 1 11:14:13 2009 @@ -2,8 +2,11 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.jit.metainterp.history import ResOperation, MergePoint, Jump from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - GuardOp) + GuardOp, Box) from pypy.jit.backend.x86.runner import CPU, GuardFailed +from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86 import symbolic +import ctypes class FakeStats(object): pass @@ -31,16 +34,44 @@ # ____________________________________________________________ -def test_execute_int_operation(): - cpu = CPU(rtyper=None, stats=FakeStats()) - assert (cpu.execute_operation('int_sub', [BoxInt(45), BoxInt(3)], 'int') - .value == 42) - assert cpu.execute_operation('int_neg', [BoxInt(45)], 'int').value == -45 - class TestX86(object): def setup_class(cls): cls.cpu = CPU(rtyper=None, stats=FakeStats()) + def execute_operation(self, opname, valueboxes, result_type): + key = [opname, result_type] + mp = self.get_compiled_single_operation(opname, result_type, valueboxes) + boxes = [box for box in valueboxes if isinstance(box, Box)] + res = self.cpu.execute_operations_in_new_frame(opname, mp, boxes, + result_type) + return res + + def get_compiled_single_operation(self, opname, result_type, valueboxes): + livevarlist = [] + for box in valueboxes: + if isinstance(box, Box): + box = box.clonebox() + livevarlist.append(box) + mp = MergePoint('merge_point', + [box for box in livevarlist if isinstance(box, Box)], + []) + if result_type == 'void': + results = [] + elif result_type == 'int': + results = [BoxInt()] + elif result_type == 'ptr': + results = [BoxPtr()] + else: + raise ValueError(result_type) + operations = [mp, + ResOperation(opname, livevarlist, results), + ResOperation('return', results, [])] + if opname.startswith('guard_'): + operations[1].liveboxes = [] + self.cpu.compile_operations(operations, verbose=False) + return mp + + def test_int_binary_ops(self): for op, args, res in [ ('int_sub', [BoxInt(42), BoxInt(40)], 2), @@ -48,36 +79,34 @@ ('int_sub', [ConstInt(42), BoxInt(40)], 2), ('int_add', [ConstInt(-3), ConstInt(-5)], -8), ]: - assert self.cpu.execute_operation(op, args, 'int').value == res + assert self.execute_operation(op, args, 'int').value == res def test_int_unary_ops(self): for op, args, res in [ ('int_neg', [BoxInt(42)], -42), - ('int_neg', [ConstInt(-42)], 42), ]: - assert self.cpu.execute_operation(op, args, 'int').value == res + assert self.execute_operation(op, args, 'int').value == res def test_int_comp_ops(self): for op, args, res in [ ('int_lt', [BoxInt(40), BoxInt(39)], 0), ('int_lt', [BoxInt(40), ConstInt(41)], 1), ('int_lt', [ConstInt(41), BoxInt(40)], 0), - ('int_lt', [ConstInt(40), ConstInt(141)], 1), ('int_le', [ConstInt(42), BoxInt(42)], 1), ('int_gt', [BoxInt(40), ConstInt(-100)], 1), ]: - assert self.cpu.execute_operation(op, args, 'int').value == res + assert self.execute_operation(op, args, 'int').value == res def test_execute_ptr_operation(self): cpu = self.cpu u = lltype.malloc(U) u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) ofs_box = ConstInt(cpu.fielddescrof(S, 'value')) - assert cpu.execute_operation('setfield_gc', [u_box, ofs_box, BoxInt(3)], + assert self.execute_operation('setfield_gc', [u_box, ofs_box, BoxInt(3)], 'void') == None assert u.parent.parent.value == 3 u.parent.parent.value += 100 - assert (cpu.execute_operation('getfield_gc', [u_box, ofs_box], 'int') + assert (self.execute_operation('getfield_gc', [u_box, ofs_box], 'int') .value == 103) def test_execute_operations_in_env(self): @@ -100,9 +129,9 @@ operations[-1].jump_target = startmp operations[-2].liveboxes = [t, u, z] cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', startmp, - [BoxInt(0), BoxInt(10)], - 'int') + res = self.cpu.execute_operations_in_new_frame('foo', startmp, + [BoxInt(0), BoxInt(10)], + 'int') assert res.value == 42 gf = cpu.metainterp.gf assert cpu.metainterp.recordedvalues == [0, True, 55] @@ -115,13 +144,13 @@ for (opname, args) in [('guard_true', [BoxInt(1)]), ('guard_false', [BoxInt(0)]), ('guard_value', [BoxInt(42), BoxInt(42)])]: - assert cpu.execute_operation(opname, args, 'void') == None + assert self.execute_operation(opname, args, 'void') == None t = lltype.malloc(T) t.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) T_box = ConstInt(rffi.cast(lltype.Signed, vtable_for_T)) null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) - assert cpu.execute_operation('guard_class', [t_box, T_box], 'void') == None + assert self.execute_operation('guard_class', [t_box, T_box], 'void') == None def test_failing_guards(self): vtable_for_T = lltype.malloc(MY_VTABLE, immortal=True) @@ -145,7 +174,7 @@ ('guard_class', [u_box, T_box]), ]: cpu.metainterp.gf = None - assert cpu.execute_operation(opname, args, 'void') == None + assert self.execute_operation(opname, args, 'void') == None assert cpu.metainterp.gf is not None def test_misc_int_ops(self): @@ -155,15 +184,15 @@ ('int_mod', [BoxInt(13), ConstInt(5)], 3), ('int_mod', [ConstInt(33), ConstInt(10)], 3), ('int_floordiv', [BoxInt(13), BoxInt(3)], 4), - ('int_floordiv', [ConstInt(10), ConstInt(10)], 1), ('int_floordiv', [BoxInt(42), ConstInt(10)], 4), ('int_floordiv', [ConstInt(42), BoxInt(10)], 4), ('int_rshift', [ConstInt(3), BoxInt(4)], 3>>4), ('int_rshift', [BoxInt(3), ConstInt(10)], 3>>10), ]: - assert self.cpu.execute_operation(op, args, 'int').value == res + assert self.execute_operation(op, args, 'int').value == res def test_same_as(self): + py.test.skip("I think no longer needed") u = lltype.malloc(U) uadr = lltype.cast_opaque_ptr(llmemory.GCREF, u) for op, args, tp, res in [ @@ -172,6 +201,137 @@ ('same_as', [BoxPtr(uadr)], 'ptr', uadr), ('same_as', [ConstPtr(uadr)], 'ptr', uadr), ]: - assert self.cpu.execute_operation(op, args, tp).value == res - + assert self.execute_operation(op, args, tp).value == res + def test_allocations(self): + from pypy.rpython.lltypesystem import rstr + + allocs = [None] + all = [] + def f(size): + allocs.insert(0, size) + buf = ctypes.create_string_buffer(size) + all.append(buf) + return ctypes.cast(buf, ctypes.c_void_p).value + func = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)(f) + addr = ctypes.cast(func, ctypes.c_void_p).value + + try: + saved_addr = self.cpu.assembler.malloc_func_addr + self.cpu.assembler.malloc_func_addr = addr + ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] + + res = self.execute_operation('newstr', [ConstInt(7)], 'ptr') + assert allocs[0] == 7 + ofs + WORD + resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) + assert resbuf[ofs/WORD] == 7 + + # ------------------------------------------------------------ + + res = self.execute_operation('newstr', [BoxInt(7)], 'ptr') + assert allocs[0] == 7 + ofs + WORD + resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) + assert resbuf[ofs/WORD] == 7 + + # ------------------------------------------------------------ + + TP = lltype.GcArray(lltype.Signed) + ofs = symbolic.get_field_token(TP, 'length')[0] + descr = ConstInt(self.cpu.arraydescrof(TP)) + + res = self.execute_operation('new_array', [descr, ConstInt(10)], + 'ptr') + assert allocs[0] == 10*WORD + ofs + WORD + resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) + assert resbuf[ofs/WORD] == 10 + + # ------------------------------------------------------------ + + res = self.execute_operation('new_array', [descr, BoxInt(10)], + 'ptr') + assert allocs[0] == 10*WORD + ofs + WORD + resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) + assert resbuf[ofs/WORD] == 10 + + finally: + self.cpu.assembler.malloc_func_addr = saved_addr + + def test_stringitems(self): + from pypy.rpython.lltypesystem.rstr import STR + ofs = symbolic.get_field_token(STR, 'chars')[0] + ofs_items = symbolic.get_field_token(STR.chars, 'items')[0] + + res = self.execute_operation('newstr', [ConstInt(10)], 'ptr') + self.execute_operation('strsetitem', [res, ConstInt(2), ConstInt(ord('d'))], 'void') + resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_char)) + assert resbuf[ofs + ofs_items + 2] == 'd' + self.execute_operation('strsetitem', [res, BoxInt(2), ConstInt(ord('z'))], 'void') + assert resbuf[ofs + ofs_items + 2] == 'z' + r = self.execute_operation('strgetitem', [res, BoxInt(2)], 'int') + assert r.value == ord('z') + + def test_arrayitems(self): + TP = lltype.GcArray(lltype.Signed) + ofs = symbolic.get_field_token(TP, 'length')[0] + itemsofs = symbolic.get_field_token(TP, 'items')[0] + descr = ConstInt(self.cpu.arraydescrof(TP)) + res = self.execute_operation('new_array', [descr, ConstInt(10)], + 'ptr') + resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) + assert resbuf[ofs/WORD] == 10 + self.execute_operation('setarrayitem_gc', [res, descr, + ConstInt(2), BoxInt(38)], + 'void') + assert resbuf[itemsofs/WORD + 2] == 38 + + self.execute_operation('setarrayitem_gc', [res, descr, + BoxInt(3), BoxInt(42)], + 'void') + assert resbuf[itemsofs/WORD + 3] == 42 + + r = self.execute_operation('getarrayitem_gc', [res, descr, + ConstInt(2)], 'int') + assert r.value == 38 + r = self.execute_operation('getarrayitem_gc', [res, descr, + BoxInt(3)], 'int') + assert r.value == 42 + + def test_getfield_setfield(self): + TP = lltype.GcStruct('x', ('s', lltype.Signed), + ('f', lltype.Float), + ('u', rffi.USHORT), + ('c1', lltype.Char), + ('c2', lltype.Char), + ('c3', lltype.Char)) + res = self.execute_operation('new', [ConstInt(self.cpu.sizeof(TP))], + 'ptr') + ofs_s = ConstInt(self.cpu.fielddescrof(TP, 's')) + ofs_f = ConstInt(self.cpu.fielddescrof(TP, 'f')) + ofs_u = ConstInt(self.cpu.fielddescrof(TP, 'u')) + ofsc1 = ConstInt(self.cpu.fielddescrof(TP, 'c1')) + ofsc2 = ConstInt(self.cpu.fielddescrof(TP, 'c2')) + ofsc3 = ConstInt(self.cpu.fielddescrof(TP, 'c3')) + self.execute_operation('setfield_gc', [res, ofs_s, ConstInt(3)], 'void') + # XXX ConstFloat + #self.execute_operation('setfield_gc', [res, ofs_f, 1e100], 'void') + # XXX we don't support shorts (at all) + #self.execute_operation('setfield_gc', [res, ofs_u, ConstInt(5)], 'void') + s = self.execute_operation('getfield_gc', [res, ofs_s], 'int') + assert s.value == 3 + self.execute_operation('setfield_gc', [res, ofs_s, BoxInt(3)], 'void') + s = self.execute_operation('getfield_gc', [res, ofs_s], 'int') + assert s.value == 3 + #u = self.execute_operation('getfield_gc', [res, ofs_u], 'int') + #assert u.value == 5 + self.execute_operation('setfield_gc', [res, ofsc1, ConstInt(1)], 'void') + self.execute_operation('setfield_gc', [res, ofsc2, ConstInt(2)], 'void') + self.execute_operation('setfield_gc', [res, ofsc3, ConstInt(3)], 'void') + c = self.execute_operation('getfield_gc', [res, ofsc1], 'int') + assert c.value == 1 + c = self.execute_operation('getfield_gc', [res, ofsc2], 'int') + assert c.value == 2 + c = self.execute_operation('getfield_gc', [res, ofsc3], 'int') + assert c.value == 3 + + def test_ovf_ops(self): + xxx Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py Sun Mar 1 11:14:13 2009 @@ -1,8 +1,7 @@ import py -py.test.skip("XXX") -from codegen386.test.test_basic import Jit386Mixin -from test.test_tlc import TLCTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test.test_tlc import TLCTests from pypy.jit.tl import tlc class TestTL(Jit386Mixin, TLCTests): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py Sun Mar 1 11:14:13 2009 @@ -1,7 +1,7 @@ import py -from test.test_tl import ToyLanguageTests -from codegen386.test.test_zrpy_slist import Jit386Mixin +from pypy.jit.metainterp.test.test_tl import ToyLanguageTests +from pypy.jit.backend.x86.test.test_zrpy_slist import Jit386Mixin from pypy.jit.tl import tlc class TestTL(Jit386Mixin, ToyLanguageTests): From fijal at codespeak.net Sun Mar 1 11:15:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 11:15:28 +0100 (CET) Subject: [pypy-svn] r62286 - in pypy/branch/pyjitpl5/pypy/rpython/lltypesystem: . test Message-ID: <20090301101528.A6CCF1684D3@codespeak.net> Author: fijal Date: Sun Mar 1 11:15:28 2009 New Revision: 62286 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: void args. also a hack for exceptions in x86 backend, not tested yet Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Sun Mar 1 11:15:28 2009 @@ -15,7 +15,7 @@ from pypy.tool.tls import tlsobject from pypy.rlib.rarithmetic import r_uint, r_singlefloat from pypy.annotation import model as annmodel -from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.rpython.lltypesystem.rclass import OBJECT from pypy.rpython.annlowlevel import base_ptr_lltype from pypy.rpython import raddress @@ -23,7 +23,6 @@ def uaddressof(obj): return fixid(ctypes.addressof(obj)) - _ctypes_cache = {} _eci_cache = {} @@ -553,7 +552,11 @@ if LLInterpreter.current_interpreter is None: raise AssertionError llinterp = LLInterpreter.current_interpreter - llres = llinterp.eval_graph(container.graph, llargs) + try: + llres = llinterp.eval_graph(container.graph, llargs) + except LLException, lle: + llinterp._store_exception(lle) + return 0 else: llres = container._callable(*llargs) assert lltype.typeOf(llres) == T.TO.RESULT @@ -651,6 +654,8 @@ """Convert the ctypes object 'cobj' to its lltype equivalent. 'T' is the expected lltype type. """ + if T is lltype.Void: + return None if isinstance(T, lltype.Ptr): if not cobj: # NULL pointer return lltype.nullptr(T.TO) Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sun Mar 1 11:15:28 2009 @@ -978,3 +978,4 @@ assert v v2 = ctypes2lltype(llmemory.GCREF, ctypes.c_void_p(1235)) assert v2 != v + From afa at codespeak.net Sun Mar 1 14:29:35 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 1 Mar 2009 14:29:35 +0100 (CET) Subject: [pypy-svn] r62289 - in pypy/trunk/pypy: doc/config objspace/std Message-ID: <20090301132935.4B7CF1684D1@codespeak.net> Author: afa Date: Sun Mar 1 14:29:34 2009 New Revision: 62289 Added: pypy/trunk/pypy/doc/config/objspace.std.immutable_builtintypes.txt Modified: pypy/trunk/pypy/objspace/std/typeobject.py Log: Fix translation, broken since r62139. Also add a minimal description of the new option. Added: pypy/trunk/pypy/doc/config/objspace.std.immutable_builtintypes.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/config/objspace.std.immutable_builtintypes.txt Sun Mar 1 14:29:34 2009 @@ -0,0 +1 @@ +Disallow modification of builtin types. Enabled by default. Modified: pypy/trunk/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/pypy/objspace/std/typeobject.py Sun Mar 1 14:29:34 2009 @@ -650,6 +650,7 @@ return if (space.config.objspace.std.immutable_builtintypes and not w_type.is_heaptype()): + msg = "can't delete attributes on type object '%s'" %(w_type.name,) raise OperationError(space.w_TypeError, space.wrap(msg)) try: del w_type.dict_w[name] From afa at codespeak.net Sun Mar 1 14:49:14 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 1 Mar 2009 14:49:14 +0100 (CET) Subject: [pypy-svn] r62291 - pypy/trunk/pypy/config/test Message-ID: <20090301134914.72BF016856A@codespeak.net> Author: afa Date: Sun Mar 1 14:49:14 2009 New Revision: 62291 Modified: pypy/trunk/pypy/config/test/test_makerestdoc.py Log: Fix this module. There is a similar statement in the py lib test suite. Modified: pypy/trunk/pypy/config/test/test_makerestdoc.py ============================================================================== --- pypy/trunk/pypy/config/test/test_makerestdoc.py (original) +++ pypy/trunk/pypy/config/test/test_makerestdoc.py Sun Mar 1 14:49:14 2009 @@ -1,7 +1,7 @@ from pypy.config.config import * from pypy.config.makerestdoc import make_cmdline_overview -from py.__.doc.conftest import restcheck +from py.__.misc.rest import process as restcheck tempdir = py.test.ensuretemp('config') From arigo at codespeak.net Sun Mar 1 15:08:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 1 Mar 2009 15:08:13 +0100 (CET) Subject: [pypy-svn] r62293 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/llgraph/test metainterp metainterp/test Message-ID: <20090301140813.2A55B16855C@codespeak.net> Author: arigo Date: Sun Mar 1 15:08:09 2009 New Revision: 62293 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Rename the field ResOperations.results into ResOperation.result, holding a single result or None instead of a list of results. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sun Mar 1 15:08:09 2009 @@ -134,17 +134,16 @@ def __init__(self, opname): self.opname = opname self.args = [] - self.results = [] + self.result = None self.livevars = [] # for guards only def __repr__(self): - results = self.results - if len(results) == 1: - sres = repr0(results[0]) - else: - sres = repr0(results) - return '{%s = %s(%s)}' % (sres, self.opname, - ', '.join(map(repr0, self.args))) + if self.result is not None: + sres = repr0(self.result) + ' = ' + else: + sres = '' + return '{%s%s(%s)}' % (sres, self.opname, + ', '.join(map(repr0, self.args))) def repr0(x): if isinstance(x, list): @@ -270,7 +269,7 @@ v = Variable() v.concretetype = lltype.Signed op = loop.operations[-1] - op.results.append(v) + op.result = v r = len(_variables) _variables.append(v) return r @@ -280,7 +279,7 @@ v = Variable() v.concretetype = llmemory.GCREF op = loop.operations[-1] - op.results.append(v) + op.result = v r = len(_variables) _variables.append(v) return r @@ -361,20 +360,19 @@ _stats.exec_jumps += 1 continue try: - results = self.execute_operation(op.opname, args, verbose) + result = self.execute_operation(op.opname, args, verbose) #verbose = self.verbose - assert len(results) == len(op.results) - assert len(op.results) <= 1 - if len(op.results) > 0: - RESTYPE = op.results[0].concretetype + assert (result is None) == (op.result is None) + if op.result is not None: + RESTYPE = op.result.concretetype if RESTYPE is lltype.Signed: - x = self.as_int(results[0]) + x = self.as_int(result) elif RESTYPE is llmemory.GCREF: - x = self.as_ptr(results[0]) + x = self.as_ptr(result) else: - raise Exception("op.results[0].concretetype is %r" + raise Exception("op.result.concretetype is %r" % (RESTYPE,)) - self.env[op.results[0]] = x + self.env[op.result] = x except GuardFailed: assert self.llframe.last_exception_handled if hasattr(op, 'jump_target'): @@ -428,12 +426,7 @@ # fish the types log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, self.memocast), resdata)) - if res is None: - return [] - elif isinstance(res, list): - return res - else: - return [res] + return res def as_int(self, x): TP = lltype.typeOf(x) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sun Mar 1 15:08:09 2009 @@ -72,7 +72,8 @@ llimpl.compile_add_int_const(c, x.getint()) else: raise Exception("%s args contain: %r" % (op.opname, x)) - for x in op.results: + x = op.result + if x is not None: if isinstance(x, history.BoxInt): var2index[x] = llimpl.compile_add_int_result(c) elif isinstance(x, history.BoxPtr): @@ -164,17 +165,20 @@ else: raise AssertionError('valuebox type=%s' % (type,)) if result_type == 'void': - resboxes = [] + resbox = None elif result_type == 'int': - resboxes = [history.BoxInt()] + resbox = history.BoxInt() elif result_type == 'ptr': - resboxes = [history.BoxPtr()] + resbox = history.BoxPtr() else: raise AssertionError(result_type) + resboxes = [] + if resbox is not None: + resboxes.append(resbox) operations = [ - history.MergePoint('merge_point', valueboxes, []), - history.ResOperation(opname, valueboxes, resboxes), - history.ResOperation('return', resboxes, []), + history.MergePoint('merge_point', valueboxes, None), + history.ResOperation(opname, valueboxes, resbox), + history.ResOperation('return', resboxes, None), ] self.compile_operations(operations) impl = operations[0]._compiled Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Sun Mar 1 15:08:09 2009 @@ -75,12 +75,12 @@ t = BoxInt(455) u = BoxInt(0) operations = [ - MergePoint('merge_point', [x, y], []), - ResOperation('int_add', [x, y], [z]), - ResOperation('int_sub', [y, ConstInt(1)], [t]), - ResOperation('int_eq', [t, ConstInt(0)], [u]), - ResOperation('guard_false', [u], []), - Jump('jump', [z, t], []), + MergePoint('merge_point', [x, y], None), + ResOperation('int_add', [x, y], z), + ResOperation('int_sub', [y, ConstInt(1)], t), + ResOperation('int_eq', [t, ConstInt(0)], u), + ResOperation('guard_false', [u], None), + Jump('jump', [z, t], None), ] operations[-2].liveboxes = [t, z] startmp = operations[0] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Sun Mar 1 15:08:09 2009 @@ -4,7 +4,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.conftest import option -from pypy.jit.metainterp.history import Graph, Jump, log, Box +from pypy.jit.metainterp.history import Graph, ResOperation, log, Box from pypy.jit.metainterp import optimize @@ -136,7 +136,7 @@ def close_loop(loop, targetmp, endliveboxes): assert targetmp.opname == 'merge_point' - op = Jump('jump', endliveboxes, []) + op = ResOperation('jump', endliveboxes, None) op.jump_target = targetmp loop.operations.append(op) @@ -160,7 +160,7 @@ assert guard_op.opname.startswith('guard_') # operations = bridge.operations = history.operations - op = Jump('jump', endliveboxes, []) + op = ResOperation('jump', endliveboxes, None) operations.append(op) # old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Sun Mar 1 15:08:09 2009 @@ -178,7 +178,7 @@ def getlinks(self): boxes = {} for op in self.all_operations: - for box in op.args + op.results: + for box in op.args + [op.result]: if isinstance(box, Box): boxes[box] = True links = {} Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Sun Mar 1 15:08:09 2009 @@ -101,7 +101,6 @@ for guard in ['guard_no_exception', 'guard_true', 'guard_false', 'guard_value', 'guard_class']: - always_pure_operations[guard] = None operation_never_raises[guard] = None setup() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 15:08:09 2009 @@ -277,70 +277,51 @@ # ____________________________________________________________ -# The central ResOperation class, representing one operation. -# It's a bit unoptimized; it could be improved, but on the other hand it -# is unclear how much would really be gained by doing this as they are -# mostly temporaries. - class ResOperation(object): - jump_target = None - - def __init__(self, opname, args, results): - self.opname = opname - self.args = list(args) - self.results = list(results) - - def __repr__(self): - results = self.results - if len(results) == 1: - sres = repr(results[0]) - else: - sres = repr(results) - return '%s = %s(%s)' % (sres, self.opname, - ', '.join(map(repr, self.args))) - - def clone(self): - return ResOperation(self.opname, self.args, self.results) - + """The central ResOperation class, representing one operation.""" -class MergePoint(ResOperation): + # for 'merge_point' specnodes = None key = None - def __new__(cls, opname, args, results): - assert len(dict.fromkeys(args)) == len(args) - return ResOperation.__new__(cls, opname, args, results) - - def clone(self): - mp = MergePoint(self.opname, self.args, self.results) - mp.specnodes = self.specnodes - mp.key = self.key - return mp - - -class Jump(ResOperation): - target_mp = None - - def clone(self): - return Jump(self.opname, self.args, self.results) - + # for 'jump' and 'guard_*' + jump_target = None -class GuardOp(ResOperation): - key = None + # for 'guard_*' counter = 0 storage_info = None + liveboxes = None - def clone(self): - op = GuardOp(self.opname, self.args, self.results) - op.key = self.key - return op + def __init__(self, opname, args, result): + if not we_are_translated(): + assert result is None or isinstance(result, Box) + if opname == 'merge_point': + assert len(dict.fromkeys(args)) == len(args) + self.opname = opname + self.args = list(args) + self.result = result def __repr__(self): - result = ResOperation.__repr__(self) - if hasattr(self, 'liveboxes'): + if self.result is not None: + sres = repr(self.result) + ' = ' + else: + sres = '' + result = '%s%s(%s)' % (sres, self.opname, + ', '.join(map(repr, self.args))) + if self.liveboxes is not None: result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) return result + def clone(self): + op = ResOperation(self.opname, self.args, self.result) + op.specnodes = self.specnodes + op.key = self.key + return op + +# compatibility +MergePoint = ResOperation +Jump = ResOperation + # ____________________________________________________________ # The Graph class is to store a loop or a bridge. @@ -394,16 +375,14 @@ elif isinstance(box, Const): assert op.opname not in ('merge_point', 'catch'), ( "no Constant arguments allowed in: %s" % (op,)) - for box in op.results: + box = op.result + if box is not None: + assert isinstance(box, Box) assert box not in seen seen[box] = True assert operations[-1].opname == 'jump' assert operations[-1].jump_target.opname == 'merge_point' - def get_final_target_mp(self): - op = self.operations[-1] - return op.jump_target - def __repr__(self): return '<%s>' % (self.name,) @@ -432,28 +411,18 @@ # really run this operation resbox = self.cpu.execute_operation(step, argboxes, result_type) # collect the result(s) - if resbox is None: - resboxes = [] - elif canfold: - resboxes = [resbox.constbox()] + if canfold: + resbox = resbox.constbox() else: - resboxes = [resbox] - if not canfold: - self.record(step, argboxes, resboxes) - return resboxes + self.record(step, argboxes, resbox) + return resbox execute_and_record._annspecialcase_ = 'specialize:arg(4)' - def record(self, opname, argboxes, resboxes, opcls=ResOperation): - # xxx the indirection from record to _record is to work - # around a limitation of the annotator (normalizecalls.py) - return self._record(opname, argboxes, resboxes, opcls) - record._annspecialcase_ = 'specialize:arg(4)' - - def _record(self, opname, argboxes, resboxes, opcls): - op = opcls(opname, argboxes, resboxes) + def record(self, opname, argboxes, resbox): + op = ResOperation(opname, argboxes, resbox) self.operations.append(op) return op - _record._annspecialcase_ = 'specialize:arg(4)' + record._annspecialcase_ = 'specialize:arg(4)' def generate_anything_since(self, old_index): return len(self.operations) > old_index @@ -462,9 +431,9 @@ pass class BlackHole(RunningMatcher): - def _record(self, step, argboxes, resboxes, opcls): + def record(self, step, argboxes, resbox): return None - _record._annspecialcase_ = 'specialize:arg(4)' + record._annspecialcase_ = 'specialize:arg(4)' def generate_anything_since(self, old_index): return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Mar 1 15:08:09 2009 @@ -1,5 +1,5 @@ from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, - MergePoint, ResOperation, Jump) + ResOperation) from pypy.jit.metainterp.history import Options from pypy.jit.metainterp.heaptracker import (always_pure_operations, operations_without_side_effects, @@ -304,7 +304,7 @@ opname == 'jump'): continue elif opname == 'new_with_vtable': - box = op.results[0] + box = op.result instnode = InstanceNode(box, escaped=False) instnode.cls = InstanceNode(op.args[1], const=True) self.nodes[box] = instnode @@ -349,7 +349,7 @@ fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) field = fieldbox.getint() - box = op.results[0] + box = op.result self.find_nodes_getfield(instnode, field, box) continue ## elif opname == 'getitem': @@ -452,10 +452,11 @@ if not self.getnode(arg).const: break else: - for box in op.results: - self.nodes[box] = InstanceNode(box.constbox(), - escaped=True, - const=True) + box = op.result + assert box is not None + self.nodes[box] = InstanceNode(box.constbox(), + escaped=True, + const=True) continue elif opname not in operations_without_side_effects: # default case @@ -463,7 +464,8 @@ for box in op.args: if isinstance(box, Box): self.nodes[box].escaped = True - for box in op.results: + box = op.result + if box is not None: self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): @@ -628,7 +630,7 @@ opname = op.opname if opname == 'merge_point': args = self.expanded_version_of(op.args, None) - op = MergePoint('merge_point', args, []) + op = ResOperation('merge_point', args, None) newoperations.append(op) #for arg in op.args: # self.ready_results[arg] = None @@ -639,7 +641,7 @@ elif opname == 'jump': args = self.expanded_version_of(op.args, newoperations) self.cleanup_field_caches(newoperations) - op = Jump('jump', args, []) + op = ResOperation('jump', args, None) newoperations.append(op) continue ## elif opname == 'guard_builtin': @@ -687,7 +689,7 @@ elif opname == 'getfield_gc': instnode = self.nodes[op.args[0]] ofs = op.args[1].getint() - if self.optimize_getfield(instnode, ofs, op.results[0]): + if self.optimize_getfield(instnode, ofs, op.result): continue # otherwise we need this getfield, but it does not # invalidate caches @@ -700,7 +702,7 @@ ## continue elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) - instnode = self.nodes[op.results[0]] + instnode = self.nodes[op.result] if not instnode.escaped: instnode.virtual = True assert instnode.cls is not None @@ -764,7 +766,7 @@ # we know the result is constant if instnode is a virtual, # or if we already checked the class of the object before if instnode.virtual or instnode.cls is not None: - box = op.results[0] + box = op.result instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue @@ -782,7 +784,7 @@ (instnode_y.cls is not None and # we checked cls y and instnode_x.const and # x is the const NULL not instnode_x.source.getptr_base())): - box = op.results[0] + box = op.result instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue @@ -794,9 +796,10 @@ break else: # all constant arguments: constant-fold away - for box in op.results: - instnode = InstanceNode(box.constbox(), const=True) - self.nodes[box] = instnode + box = op.result + assert box is not None + instnode = InstanceNode(box.constbox(), const=True) + self.nodes[box] = instnode continue elif opname not in operations_without_side_effects: if opname not in ('getfield_gc', 'getitem', @@ -804,9 +807,10 @@ # those operations does not clean up caches, although # they have side effects (at least set ones) self.cleanup_field_caches(newoperations) - if opname not in operation_never_raises: + if opname not in operation_never_raises: # XXX do me right exception_might_have_happened = True - for box in op.results: + box = op.result + if box is not None: instnode = InstanceNode(box) self.nodes[box] = instnode newoperations.append(op) @@ -827,7 +831,7 @@ ## else: if 1: newoperations.append(ResOperation('setfield_gc', - [node.source, ConstInt(ofs), valuenode.source], [])) + [node.source, ConstInt(ofs), valuenode.source], None)) node.dirtyfields = {} node.cleanfields = {} @@ -880,9 +884,9 @@ for vtable in storage.allocations: sizebox = ConstInt(metainterp.class_sizes[vtable]) vtablebox = ConstInt(vtable) - [instbox] = history.execute_and_record('new_with_vtable', - [sizebox, vtablebox], - 'ptr', False) + instbox = history.execute_and_record('new_with_vtable', + [sizebox, vtablebox], + 'ptr', False) allocated_boxes.append(instbox) ## for malloc_func, lgt in storage.list_allocations: ## sizebox = ConstInt(lgt) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Mar 1 15:08:09 2009 @@ -9,7 +9,7 @@ from pypy.jit.metainterp import history, support from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr, Box, - BoxInt, BoxPtr, GuardOp, Options) + BoxInt, BoxPtr, Options) from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) @@ -627,8 +627,7 @@ liveboxes.append(const_if_fail) if box is not None: extraargs = [box] + extraargs - guard_op = self.metainterp.history.record(opname, extraargs, [], - opcls=GuardOp) + guard_op = self.metainterp.history.record(opname, extraargs, None) guard_op.liveboxes = liveboxes saved_pc = self.pc self.pc = pc @@ -654,13 +653,11 @@ self.pc = self.load_3byte() def execute(self, step, argboxes, result_type, pure=False): - resboxes = self.metainterp.history.execute_and_record(step, argboxes, - result_type, - pure) - assert len(resboxes) <= 1 - if len(resboxes) == 1: - resultbox = resboxes[0] - self.make_result_box(resultbox) + resbox = self.metainterp.history.execute_and_record(step, argboxes, + result_type, + pure) + if resbox is not None: + self.make_result_box(resbox) execute._annspecialcase_ = 'specialize:arg(4)' def execute_with_exc(self, step, argboxes, result_type, pure=False): @@ -676,15 +673,14 @@ evalue = cast_instance_to_base_ptr(e) etype = evalue.typeptr if result_type == 'void': - resultboxes = [] + resultbox = None else: if result_type == 'ptr': resultbox = BoxPtr() else: resultbox = BoxInt() self.make_result_box(resultbox) - resultboxes = [resultbox] - self.metainterp.history.record(step, argboxes, resultboxes) + self.metainterp.history.record(step, argboxes, resultbox) else: if not self.metainterp.history.generate_anything_since(old_index): assert pure @@ -745,13 +741,6 @@ self.framestack[-1].make_result_box(resultbox) return True else: - if resultbox is None: - resultboxes = [] - else: - resultboxes = [resultbox] - #self.history.record('return', resultboxes, []) - #self.guard_failure.make_ready_for_return(resultbox) - #raise DoneMetaInterpreting raise self.DoneWithThisFrame(resultbox) def finishframe_exception(self, exceptionbox, excvaluebox): @@ -840,8 +829,8 @@ if not box1.equals(box2): # not a valid loop raise self.ContinueRunningNormally(live_arg_boxes) - mp = history.MergePoint('merge_point', - original_boxes[num_green_args:], []) + mp = history.ResOperation('merge_point', + original_boxes[num_green_args:], None) mp.greenkey = original_boxes[:num_green_args] self.history.operations.insert(0, mp) old_loops = self.compiled_merge_points.setdefault(mp.greenkey, []) @@ -853,7 +842,7 @@ def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes): num_green_args = self.num_green_args - mp = history.ResOperation('catch', original_boxes, []) + mp = history.ResOperation('catch', original_boxes, None) mp.coming_from = guard_failure.guard_op self.history.operations.insert(0, mp) try: @@ -950,23 +939,12 @@ op = frame.generate_guard(frame.pc, 'guard_exception', None, [exception_box]) if op: - op.results = [exc_value_box] + op.result = exc_value_box return self.finishframe_exception(exception_box, exc_value_box) else: frame.generate_guard(frame.pc, 'guard_no_exception', None, []) return False -## def forced_vars_after_guard_failure(self, guard_failure): -## # for a 'guard_true' or 'guard_false' failure, the purpose of this is -## # to avoid a new 'guard' operation just to check for the other case -## forced_vars = {} -## guard_op = guard_failure.guard_op -## assert guard_op.opname.startswith('guard_') -## if guard_op.opname in ('guard_true', 'guard_false'): -## guardbox = guard_op.args[0] -## forced_vars[guardbox] = None -## return forced_vars - def rebuild_state_after_failure(self, key, newboxes): self.framestack = [] nbindex = 0 @@ -989,39 +967,6 @@ frame.exception_target)) return key -## def generate_mp_and_continue(self): -## if self.most_recent_mp is not None: -## return self.most_recent_mp -## greenkey = [] -## liveboxes = [] -## memo = {} -## for frame in self.framestack: -## frame.record_state(greenkey, liveboxes, memo) -## # try to loop back to a previous merge point with the same green key -## mplist = self.history.get_merge_points_from_current_branch(greenkey) -## for oldmp in mplist: -## newloop = compile_new_loop(self, oldmp, liveboxes) -## if newloop is not None: -## self.execute_new_loop(newloop, liveboxes) -## # ^^^ raised DoneMetaInterpreting -## # else try to jump to some older already-compiled merge point -## mplist = self.compiled_merge_points.get(greenkey, []) -## for oldmp in mplist: -## newbridge = compile_new_bridge(self, oldmp, liveboxes) -## if newbridge is not None: -## self.execute_new_loop(newbridge, liveboxes) -## # ^^^ raised DoneMetaInterpreting -## # else continue -## mp = self.history.record_merge_point(greenkey, liveboxes) -## self.most_recent_mp = mp -## return mp - -## def execute_new_loop(self, loop, liveboxes): -## mp = loop.get_final_target_mp() -## specnode.copy_data_into_cpu_frame(self.cpu, self.guard_failure, -## mp, liveboxes) -## raise DoneMetaInterpreting - def make_builtin_dictionary(self): # In case this is translated, the following runs at run-time. # It's not possible to make a dictionary with keys that are function Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sun Mar 1 15:08:09 2009 @@ -167,7 +167,7 @@ else: box = subspecnode.box.clonebox() oplist.append(ResOperation('getfield_gc', - [instnode.source, ConstInt(ofs)], [box])) + [instnode.source, ConstInt(ofs)], box)) newboxlist.append(box) ##class DelayedListSpecNode(DelayedSpecNode): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Sun Mar 1 15:08:09 2009 @@ -6,8 +6,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - ConstAddr, ResOperation, MergePoint, - Jump, GuardOp) + ConstAddr, ResOperation) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, rebuild_boxes_from_guard_failure, AllocationStorage, @@ -61,7 +60,7 @@ assert len(op1.args) == len(op2.args) for x, y in zip(op1.args, op2.args): assert x == y or y == x # for ANY object :-( - assert op1.results == op2.results + assert op1.result == op2.result assert len(oplist1) == len(oplist2) print '-'*57 #finally: @@ -88,16 +87,16 @@ v2 = BoxInt(startnode.value-1) sum2 = BoxInt(0 + startnode.value) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [sizebox, - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - Jump('jump', [sum2, n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('jump', [sum2, n2], None), ] def test_A_find_nodes(): @@ -128,10 +127,10 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [A.sum, A.v], []), - ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), - ResOperation('int_add', [A.sum, A.v], [A.sum2]), - Jump('jump', [A.sum2, A.v2], []), + ResOperation('merge_point', [A.sum, A.v], None), + ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), + ResOperation('int_add', [A.sum, A.v], A.sum2), + ResOperation('jump', [A.sum2, A.v2], None), ]) # ____________________________________________________________ @@ -139,18 +138,18 @@ class B: locals().update(A.__dict__) # :-) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('escape', [n1], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + sizebox], None), + ResOperation('escape', [n1], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - ResOperation('some_escaping_operation', [n2], []), # <== escaping - Jump('jump', [sum2, n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('some_escaping_operation', [n2], None), # <== escaping + ResOperation('jump', [sum2, n2], None), ] def test_B_find_nodes(): @@ -177,18 +176,18 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [B.sum, B.n1], []), + ResOperation('merge_point', [B.sum, B.n1], None), # guard_class is gone - ResOperation('escape', [B.n1], []), - ResOperation('getfield_gc', [B.n1, ConstInt(B.ofs_value)], [B.v]), - ResOperation('int_sub', [B.v, ConstInt(1)], [B.v2]), - ResOperation('int_add', [B.sum, B.v], [B.sum2]), + ResOperation('escape', [B.n1], None), + ResOperation('getfield_gc', [B.n1, ConstInt(B.ofs_value)], B.v), + ResOperation('int_sub', [B.v, ConstInt(1)], B.v2), + ResOperation('int_add', [B.sum, B.v], B.sum2), ResOperation('new_with_vtable', [ConstInt(B.size_of_node), - ConstAddr(node_vtable, cpu)], [B.n2]), + ConstAddr(node_vtable, cpu)], B.n2), ResOperation('setfield_gc', [B.n2, ConstInt(B.ofs_value), B.v2], - []), - ResOperation('some_escaping_operation', [B.n2], []), # <== escaping - Jump('jump', [B.sum2, B.n2], []), + None), + ResOperation('some_escaping_operation', [B.n2], None), # <== escaping + ResOperation('jump', [B.sum2, B.n2], None), ]) # ____________________________________________________________ @@ -196,18 +195,18 @@ class C: locals().update(A.__dict__) # :-) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('some_escaping_operation', [n1], []), # <== escaping - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('some_escaping_operation', [n1], []), # <== escaping + sizebox], None), + ResOperation('some_escaping_operation', [n1], None), # <== escaping + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('some_escaping_operation', [n1], None), # <== escaping ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - Jump('jump', [sum2, n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('jump', [sum2, n2], None), ] def test_C_find_nodes(): @@ -234,18 +233,18 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [C.sum, C.n1], []), + ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone - ResOperation('some_escaping_operation', [C.n1], []), # <== escaping - ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], [C.v]), - ResOperation('int_sub', [C.v, ConstInt(1)], [C.v2]), - ResOperation('int_add', [C.sum, C.v], [C.sum2]), - ResOperation('some_escaping_operation', [C.n1], []), # <== escaping + ResOperation('some_escaping_operation', [C.n1], None), # <== escaping + ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], C.v), + ResOperation('int_sub', [C.v, ConstInt(1)], C.v2), + ResOperation('int_add', [C.sum, C.v], C.sum2), + ResOperation('some_escaping_operation', [C.n1], None), # <== escaping ResOperation('new_with_vtable', [ConstInt(C.size_of_node), - ConstAddr(node_vtable, cpu)], [C.n2]), + ConstAddr(node_vtable, cpu)], C.n2), ResOperation('setfield_gc', [C.n2, ConstInt(C.ofs_value), C.v2], - []), - Jump('jump', [C.sum2, C.n2], []), + None), + ResOperation('jump', [C.sum2, C.n2], None), ]) # ____________________________________________________________ @@ -253,17 +252,17 @@ class D: locals().update(A.__dict__) # :-) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu), - sizebox], []), + sizebox], None), # the only difference is different vtable ^^^^^^^^^^^^ - ResOperation('getfield', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + ResOperation('getfield', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - Jump('jump', [sum2, n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('jump', [sum2, n2], None), ] def test_D_intersect_input_and_output(): @@ -276,17 +275,17 @@ class E: locals().update(A.__dict__) # :-) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - ResOperation('guard_true', [v2], []), - Jump('jump', [sum2, n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('guard_true', [v2], None), + ResOperation('jump', [sum2, n2], None), ] ops[-2].liveboxes = [sum2, n2] @@ -296,12 +295,12 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [E.sum, E.v], []), + ResOperation('merge_point', [E.sum, E.v], None), # guard_class is gone - ResOperation('int_sub', [E.v, ConstInt(1)], [E.v2]), - ResOperation('int_add', [E.sum, E.v], [E.sum2]), - ResOperation('guard_true', [E.v2], []), - Jump('jump', [E.sum2, E.v2], []), + ResOperation('int_sub', [E.v, ConstInt(1)], E.v2), + ResOperation('int_add', [E.sum, E.v], E.sum2), + ResOperation('guard_true', [E.v2], None), + ResOperation('jump', [E.sum2, E.v2], None), ]) guard_op = spec.loop.operations[-2] assert guard_op.opname == 'guard_true' @@ -318,9 +317,9 @@ def execute_and_record(self, opname, args, res_type, pure): self.ops.append((opname, args)) if res_type != 'void': - return ['allocated'] + return 'allocated' else: - return [] + return None class FakeMetaInterp(object): def __init__(self): @@ -357,22 +356,22 @@ vbool2 = BoxInt(0) vbool3 = BoxInt(1) ops = [ - MergePoint('merge_point', [sum, n1, n3], []), + ResOperation('merge_point', [sum, n1, n3], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - ResOperation('ooisnot', [n2, n3], [vbool1]), - GuardOp('guard_true', [vbool1], []), - ResOperation('ooisnull', [n2], [vbool2]), - GuardOp('guard_false', [vbool2], []), - ResOperation('oononnull', [n3], [vbool3]), - GuardOp('guard_true', [vbool3], []), - Jump('jump', [sum2, n2, n3], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('ooisnot', [n2, n3], vbool1), + ResOperation('guard_true', [vbool1], None), + ResOperation('ooisnull', [n2], vbool2), + ResOperation('guard_false', [vbool2], None), + ResOperation('oononnull', [n3], vbool3), + ResOperation('guard_true', [vbool3], None), + ResOperation('jump', [sum2, n2, n3], None), ] liveboxes = [sum2, n2, n3] ops[-2].liveboxes = liveboxes[:] @@ -392,12 +391,12 @@ assert spec.nodes[F.n3].escaped spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [F.sum, F.v, F.n3], []), - ResOperation('int_sub', [F.v, ConstInt(1)], [F.v2]), - ResOperation('int_add', [F.sum, F.v], [F.sum2]), - ResOperation('oononnull', [F.n3], [F.vbool3]), - GuardOp('guard_true', [F.vbool3], []), - Jump('jump', [F.sum2, F.v2, F.n3], []), + ResOperation('merge_point', [F.sum, F.v, F.n3], None), + ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), + ResOperation('int_add', [F.sum, F.v], F.sum2), + ResOperation('oononnull', [F.n3], F.vbool3), + ResOperation('guard_true', [F.vbool3], None), + ResOperation('jump', [F.sum2, F.v2, F.n3], None), ]) class F2: @@ -410,11 +409,11 @@ n4 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node4)) vbool1 = BoxInt(0) ops = [ - MergePoint('merge_point', [n2, n3], []), - ResOperation('oois', [n2, n3], [vbool1]), - GuardOp('guard_true', [vbool1], []), - ResOperation('external', [], [n4]), - Jump('jump', [n2, n4], []), + ResOperation('merge_point', [n2, n3], None), + ResOperation('oois', [n2, n3], vbool1), + ResOperation('guard_true', [vbool1], None), + ResOperation('external', [], n4), + ResOperation('jump', [n2, n4], None), ] ops[2].liveboxes = [n2] @@ -432,21 +431,21 @@ v3 = BoxInt(123) v4 = BoxInt(124) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), + ConstAddr(node_vtable, cpu)], n2), ResOperation('setfield_gc', [n2, ConstInt(ofs_value), - ConstInt(123)], []), - ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], [v3]), - ResOperation('int_add', [v3, ConstInt(1)], [v4]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v4], []), - ResOperation('guard_true', [v2], []), - Jump('jump', [sum2, n2], []), + ConstInt(123)], None), + ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], v3), + ResOperation('int_add', [v3, ConstInt(1)], v4), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v4], None), + ResOperation('guard_true', [v2], None), + ResOperation('jump', [sum2, n2], None), ] ops[-2].liveboxes = [sum2, n2] @@ -456,12 +455,12 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [G.sum, G.v], []), + ResOperation('merge_point', [G.sum, G.v], None), # guard_class is gone - ResOperation('int_sub', [G.v, ConstInt(1)], [G.v2]), - ResOperation('int_add', [G.sum, G.v], [G.sum2]), - ResOperation('guard_true', [G.v2], []), - Jump('jump', [G.sum2, ConstInt(124)], []), + ResOperation('int_sub', [G.v, ConstInt(1)], G.v2), + ResOperation('int_add', [G.sum, G.v], G.sum2), + ResOperation('guard_true', [G.v2], None), + ResOperation('jump', [G.sum2, ConstInt(124)], None), ]) guard_op = spec.loop.operations[-2] assert guard_op.opname == 'guard_true' @@ -486,15 +485,15 @@ v = BoxInt(containernode.next.value) v2 = BoxInt(nextnode.value) ops = [ - MergePoint('merge_point', [n0], []), - ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], [n1]), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('merge_point', [n0], None), + ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], n1), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - ResOperation('setfield_gc', [n0, ConstInt(ofs_next), n2], []), - Jump('jump', [n0], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('setfield_gc', [n0, ConstInt(ofs_next), n2], None), + ResOperation('jump', [n0], None), ] def test_H_intersect_input_and_output(): @@ -518,11 +517,11 @@ nextnode.value = 19 n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) ops = [ - MergePoint('merge_point', [n0], []), + ResOperation('merge_point', [n0], None), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n0], []), - Jump('jump', [n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n0], None), + ResOperation('jump', [n2], None), ] def test_I_intersect_input_and_output(): @@ -532,7 +531,6 @@ assert spec.nodes[I.n0].escaped assert spec.nodes[I.n2].escaped - # ____________________________________________________________ class J: @@ -547,12 +545,12 @@ n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) ops = [ - MergePoint('merge_point', [n0], []), - ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], [n1]), + ResOperation('merge_point', [n0], None), + ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], n1), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n1], []), - Jump('jump', [n2], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n1], None), + ResOperation('jump', [n2], None), ] def test_J_intersect_input_and_output(): @@ -570,16 +568,16 @@ sum3 = BoxInt(3) v3 = BoxInt(4) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), - ResOperation('int_add', [sum2, v3], [sum3]), - ResOperation('escape', [n1], []), - Jump('jump', [sum3, n1], []), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('int_add', [sum2, v3], sum3), + ResOperation('escape', [n1], None), + ResOperation('jump', [sum3, n1], None), ] def test_K0_optimize_loop(): @@ -587,14 +585,15 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [K0.sum, K0.n1, K0.v], []), - ResOperation('int_sub', [K0.v, ConstInt(1)], [K0.v2]), - ResOperation('int_add', [K0.sum, K0.v], [K0.sum2]), - ResOperation('int_add', [K0.sum2, K0.v], [K0.sum3]), - ResOperation('escape', [K0.n1], []), - ResOperation('getfield_gc', [K0.n1, ConstInt(K0.ofs_value)], [ANY]), - Jump('jump', [K0.sum3, K0.n1, ANY], []), + ResOperation('merge_point', [K0.sum, K0.n1, K0.v], None), + ResOperation('int_sub', [K0.v, ConstInt(1)], K0.v2), + ResOperation('int_add', [K0.sum, K0.v], K0.sum2), + ResOperation('int_add', [K0.sum2, K0.v], K0.sum3), + ResOperation('escape', [K0.n1], None), + ResOperation('getfield_gc', [K0.n1, ConstInt(K0.ofs_value)], v4), + ResOperation('jump', [K0.sum3, K0.n1, v4], None), ]) @@ -603,17 +602,17 @@ sum3 = BoxInt(3) v3 = BoxInt(4) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('setfield_gc', [n1, ConstInt(ofs_value), sum], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), - ResOperation('int_add', [sum2, v3], [sum3]), - ResOperation('escape', [n1], []), - Jump('jump', [sum3, n1], []), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('setfield_gc', [n1, ConstInt(ofs_value), sum], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('int_add', [sum2, v3], sum3), + ResOperation('escape', [n1], None), + ResOperation('jump', [sum3, n1], None), ] def test_K1_optimize_loop(): @@ -621,16 +620,17 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [K1.sum, K1.n1, K1.v], []), - ResOperation('int_sub', [K1.v, ConstInt(1)], [K1.v2]), - ResOperation('int_add', [K1.sum, K1.v], [K1.sum2]), - ResOperation('int_add', [K1.sum2, K1.sum], [K1.sum3]), + ResOperation('merge_point', [K1.sum, K1.n1, K1.v], None), + ResOperation('int_sub', [K1.v, ConstInt(1)], K1.v2), + ResOperation('int_add', [K1.sum, K1.v], K1.sum2), + ResOperation('int_add', [K1.sum2, K1.sum], K1.sum3), ResOperation('setfield_gc', [K1.n1, ConstInt(K1.ofs_value), K1.sum], - []), - ResOperation('escape', [K1.n1], []), - ResOperation('getfield_gc', [K1.n1, ConstInt(K1.ofs_value)], [ANY]), - Jump('jump', [K1.sum3, K1.n1, ANY], []), + None), + ResOperation('escape', [K1.n1], None), + ResOperation('getfield_gc', [K1.n1, ConstInt(K1.ofs_value)], v4), + ResOperation('jump', [K1.sum3, K1.n1, v4], None), ]) @@ -639,15 +639,15 @@ sum3 = BoxInt(3) v3 = BoxInt(4) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), - ResOperation('int_add', [sum2, v3], [sum3]), - Jump('jump', [sum3, n1], []), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('int_add', [sum2, v3], sum3), + ResOperation('jump', [sum3, n1], None), ] def test_K_optimize_loop(): @@ -656,11 +656,11 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [K.sum, K.n1, K.v], []), - ResOperation('int_sub', [K.v, ConstInt(1)], [K.v2]), - ResOperation('int_add', [K.sum, K.v], [K.sum2]), - ResOperation('int_add', [K.sum2, K.v], [K.sum3]), - Jump('jump', [K.sum3, K.n1, K.v], []), + ResOperation('merge_point', [K.sum, K.n1, K.v], None), + ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), + ResOperation('int_add', [K.sum, K.v], K.sum2), + ResOperation('int_add', [K.sum2, K.v], K.sum3), + ResOperation('jump', [K.sum3, K.n1, K.v], None), ]) # ____________________________________________________________ @@ -670,16 +670,16 @@ sum3 = BoxInt(3) v3 = BoxInt(4) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('escape', [n1], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), - ResOperation('int_add', [sum2, v3], [sum3]), - Jump('jump', [sum3, n1], []), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('escape', [n1], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('int_add', [sum2, v3], sum3), + ResOperation('jump', [sum3, n1], None), ] def test_L_optimize_loop(): @@ -688,13 +688,13 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [L.sum, L.n1, L.v], []), - ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), - ResOperation('int_add', [L.sum, L.v], [L.sum2]), - ResOperation('escape', [L.n1], []), - ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [L.v3]), - ResOperation('int_add', [L.sum2, L.v3], [L.sum3]), - Jump('jump', [L.sum3, L.n1, L.v3], []), + ResOperation('merge_point', [L.sum, L.n1, L.v], None), + ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), + ResOperation('int_add', [L.sum, L.v], L.sum2), + ResOperation('escape', [L.n1], None), + ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], L.v3), + ResOperation('int_add', [L.sum2, L.v3], L.sum3), + ResOperation('jump', [L.sum3, L.n1, L.v3], None), ]) # ____________________________________________________________ @@ -704,14 +704,14 @@ sum3 = BoxInt(3) v3 = BoxInt(4) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('escape', [n1], []), - Jump('jump', [sum2, n1], []), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('escape', [n1], None), + ResOperation('jump', [sum2, n1], None), ] def test_M_optimize_loop(): @@ -719,16 +719,16 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [M.sum, M.n1, M.v], []), - ResOperation('int_sub', [M.v, ConstInt(1)], [M.v2]), - ResOperation('int_add', [M.sum, M.v], [M.sum2]), - ResOperation('escape', [M.n1], []), - ResOperation('getfield_gc', [M.n1, ConstInt(M.ofs_value)], [ANY]), - Jump('jump', [M.sum2, M.n1, ANY], []), + ResOperation('merge_point', [M.sum, M.n1, M.v], None), + ResOperation('int_sub', [M.v, ConstInt(1)], M.v2), + ResOperation('int_add', [M.sum, M.v], M.sum2), + ResOperation('escape', [M.n1], None), + ResOperation('getfield_gc', [M.n1, ConstInt(M.ofs_value)], v4), + ResOperation('jump', [M.sum2, M.n1, v4], None), ]) - # ____________________________________________________________ class N: @@ -736,14 +736,14 @@ sum3 = BoxInt(3) v3 = BoxInt(4) ops = [ - MergePoint('merge_point', [sum, n1], []), + ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), - ResOperation('escape', [n1], []), - Jump('jump', [sum2, n1], []), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), + ResOperation('escape', [n1], None), + ResOperation('jump', [sum2, n1], None), ] def test_N_optimize_loop(): @@ -751,13 +751,14 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [N.sum, N.n1, N.v], []), - ResOperation('int_sub', [N.v, ConstInt(1)], [N.v2]), - ResOperation('int_add', [N.sum, N.v], [N.sum2]), - ResOperation('escape', [N.n1], []), - ResOperation('getfield_gc', [N.n1, ConstInt(N.ofs_value)], [ANY]), - Jump('jump', [N.sum2, N.n1, ANY], []), + ResOperation('merge_point', [N.sum, N.n1, N.v], None), + ResOperation('int_sub', [N.v, ConstInt(1)], N.v2), + ResOperation('int_add', [N.sum, N.v], N.sum2), + ResOperation('escape', [N.n1], None), + ResOperation('getfield_gc', [N.n1, ConstInt(N.ofs_value)], v4), + ResOperation('jump', [N.sum2, N.n1, v4], None), ]) # ____________________________________________________________ @@ -765,13 +766,13 @@ class O1: locals().update(A.__dict__) # :-) ops = [ - MergePoint('merge_point', [], []), - ResOperation('produce_somehow_n1', [], [n1]), + ResOperation('merge_point', [], None), + ResOperation('produce_somehow_n1', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), + sizebox], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - Jump('jump', [], []), + sizebox], None), + ResOperation('jump', [], None), ] ops[-3].liveboxes = [] ops[-2].liveboxes = [] @@ -782,12 +783,12 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [], []), - ResOperation('produce_somehow_n1', [], [O1.n1]), + ResOperation('merge_point', [], None), + ResOperation('produce_somehow_n1', [], O1.n1), # only the first guard_class is left ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu), - O1.sizebox], []), - Jump('jump', [], []), + O1.sizebox], None), + ResOperation('jump', [], None), ]) # ____________________________________________________________ @@ -796,13 +797,13 @@ locals().update(A.__dict__) # :-) v1 = BoxInt(1) ops = [ - MergePoint('merge_point', [], []), - ResOperation('produce_somehow_n1', [], [n1]), + ResOperation('merge_point', [], None), + ResOperation('produce_somehow_n1', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('oononnull', [n1], [v1]), - ResOperation('guard_true', [v1], []), - Jump('jump', [], []), + sizebox], None), + ResOperation('oononnull', [n1], v1), + ResOperation('guard_true', [v1], None), + ResOperation('jump', [], None), ] ops[-4].liveboxes = [] ops[-2].liveboxes = [] @@ -813,13 +814,13 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [], []), - ResOperation('produce_somehow_n1', [], [O2.n1]), + ResOperation('merge_point', [], None), + ResOperation('produce_somehow_n1', [], O2.n1), ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu), - O2.sizebox], []), + O2.sizebox], None), # the oononnull and guard_true are gone, because we know they # return True -- as there was already a guard_class done on n1 - Jump('jump', [], []), + ResOperation('jump', [], None), ]) # ____________________________________________________________ @@ -828,14 +829,14 @@ locals().update(A.__dict__) # :-) v1 = BoxInt(1) ops = [ - MergePoint('merge_point', [], []), - ResOperation('produce_somehow_n1', [], [n1]), + ResOperation('merge_point', [], None), + ResOperation('produce_somehow_n1', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), + sizebox], None), ResOperation('oois', [n1, ConstPtr(lltype.nullptr(llmemory.GCREF.TO))], - [v1]), - ResOperation('guard_false', [v1], []), - Jump('jump', [], []), + v1), + ResOperation('guard_false', [v1], None), + ResOperation('jump', [], None), ] ops[-4].liveboxes = [] ops[-2].liveboxes = [] @@ -846,11 +847,11 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [], []), - ResOperation('produce_somehow_n1', [], [O3.n1]), + ResOperation('merge_point', [], None), + ResOperation('produce_somehow_n1', [], O3.n1), ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu), - O3.sizebox], []), + O3.sizebox], None), # the oois and guard_false are gone, because we know they # return False -- as there was already a guard_class done on n1 - Jump('jump', [], []), + ResOperation('jump', [], None), ]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sun Mar 1 15:08:09 2009 @@ -82,18 +82,18 @@ v2 = BoxInt(nextnode.value) sum2 = BoxInt(0 + frame.node.value) ops = [ - MergePoint('merge_point', [sum, fr], []), + MergePoint('merge_point', [sum, fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], []), - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - ResOperation('int_sub', [v, ConstInt(1)], [v2]), - ResOperation('int_add', [sum, v], [sum2]), + ConstInt(ofs_node)], None), + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('int_sub', [v, ConstInt(1)], v2), + ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), - ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], []), - Jump('jump', [sum2, fr], []), + ConstAddr(node_vtable, cpu)], n2), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], None), + Jump('jump', [sum2, fr], None), ] ops[1].vdesc = xy_desc @@ -118,10 +118,10 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [A.sum, A.fr, A.v], []), - ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), - ResOperation('int_add', [A.sum, A.v], [A.sum2]), - Jump('jump', [A.sum2, A.fr, A.v2], []), + MergePoint('merge_point', [A.sum, A.fr, A.v], None), + ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), + ResOperation('int_add', [A.sum, A.v], A.sum2), + Jump('jump', [A.sum2, A.fr, A.v2], None), ]) # ____________________________________________________________ @@ -139,12 +139,12 @@ n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v = BoxInt(13) ops = [ - MergePoint('merge_point', [fr], []), + MergePoint('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], []), - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), - Jump('jump', [fr], []), + ConstInt(ofs_node)], None), + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + Jump('jump', [fr], None), ] ops[1].vdesc = xy_desc @@ -168,20 +168,20 @@ v2 = BoxInt(13) sizebox = ConstInt(cpu.sizeof(NODE)) ops = [ - MergePoint('merge_point', [fr], []), + MergePoint('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], []), + ConstInt(ofs_node)], None), # - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + sizebox], None), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), # - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n2]), - ResOperation('guard_class', [n2, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], [v2]), + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n2), + ResOperation('guard_class', [n2, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], v2), # - Jump('jump', [fr], []), + Jump('jump', [fr], None), ] ops[1].vdesc = xy_desc @@ -212,15 +212,15 @@ v2 = BoxInt(13) l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) ops = [ - MergePoint('merge_point', [fr], []), + MergePoint('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], []), + ConstInt(ofs_node)], None), # - ResOperation('getfield_gc', [fr, ConstInt(ofs_l)], [l]), - ResOperation('guard_builtin', [l, SomeDescr()], []), - ResOperation('getitem', [None, l, ConstInt(0)], [v2]), - ResOperation('setitem', [None, l, ConstInt(0), v2], []), - Jump('jump', [fr], []), + ResOperation('getfield_gc', [fr, ConstInt(ofs_l)], l), + ResOperation('guard_builtin', [l, SomeDescr()], None), + ResOperation('getitem', [None, l, ConstInt(0)], v2), + ResOperation('setitem', [None, l, ConstInt(0), v2], None), + Jump('jump', [fr], None), ] ops[1].vdesc = xy_desc From arigo at codespeak.net Sun Mar 1 15:11:42 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 1 Mar 2009 15:11:42 +0100 (CET) Subject: [pypy-svn] r62294 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test tl Message-ID: <20090301141142.76EE116855C@codespeak.net> Author: arigo Date: Sun Mar 1 15:11:41 2009 New Revision: 62294 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: - add the "switch_dict" operation - fixes to optimize.py - move the ResOperation class to its own file Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sun Mar 1 15:11:41 2009 @@ -176,7 +176,7 @@ if resbox is not None: resboxes.append(resbox) operations = [ - history.MergePoint('merge_point', valueboxes, None), + history.ResOperation('merge_point', valueboxes, None), history.ResOperation(opname, valueboxes, resbox), history.ResOperation('return', resboxes, None), ] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Mar 1 15:11:41 2009 @@ -80,6 +80,10 @@ self.bytecode_for_address = bytecode_for_address self.dict = None + +class SwitchDict(history.AbstractValue): + "Get a 'dict' attribute mapping integer values to bytecode positions." + # ____________________________________________________________ @@ -233,6 +237,7 @@ labelpos = {} code = assemble(labelpos, self.codewriter.metainterp, self.assembler) + self.resolve_switch_targets(labelpos) self.bytecode.setup(code, self.constants) self.bytecode._source = self.assembler @@ -335,13 +340,24 @@ self.minimize_variables() switches = [link for link in block.exits if link.exitcase != 'default'] + if len(switches) >= 6 and isinstance(block.exitswitch.concretetype, + lltype.Primitive): + switchdict = SwitchDict() + switchdict._maps = {} + for link in switches: + key = lltype.cast_primitive(lltype.Signed, link.llexitcase) + switchdict._maps[key] = link + self.emit("switch_dict", + self.var_position(block.exitswitch), + self.get_position(switchdict)) + else: + self.emit("switch", + self.var_position(block.exitswitch)) + self.emit_list([self.const_position(link.llexitcase) + for link in switches]) + self.emit_list([tlabel(link) for link in switches]) renamings = [self.insert_renaming(link.args) for link in switches] - self.emit("switch", - self.var_position(block.exitswitch)) - self.emit_list([self.const_position(link.llexitcase) - for link in switches]) - self.emit_list([tlabel(link) for link in switches]) if block.exits[-1].exitcase == 'default': link = block.exits[-1] self.emit(*self.insert_renaming(link.args)) @@ -356,11 +372,18 @@ self.dont_minimize_variables += 1 handler = object() renamings = [] - for link in exception_exits: + for i, link in enumerate(exception_exits): args_without_last_exc = [v for v in link.args if (v is not link.last_exception and v is not link.last_exc_value)] - renamings.append(self.insert_renaming(args_without_last_exc)) + if (link.exitcase is Exception and + not args_without_last_exc and link.target.operations == () and + len(link.target.inputargs) == 2): + # stop at the catch-and-reraise-every-exception branch, if any + exception_exits = exception_exits[:i] + break + renamings.append(self.insert_renaming(args_without_last_exc, + force=True)) self.pending_exception_handlers.append((handler, exception_exits, renamings)) self.emit("setup_exception_block", @@ -394,7 +417,7 @@ self.emit("put_last_exc_value", i) self.make_bytecode_block(link.target) - def insert_renaming(self, args): + def insert_renaming(self, args, force=False): args = [v for v in args if v.concretetype is not lltype.Void] if len(args) >= MAX_MAKE_NEW_VARS: code = ["make_new_vars", len(args)] @@ -402,18 +425,33 @@ code = ["make_new_vars_%d" % len(args)] for v in args: code.append(self.var_position(v)) + if (not force and len(args) == self.free_vars and + code[len(code)-len(args):] == range(0, self.free_vars*2, 2)): + return [] # no-op return code def minimize_variables(self): if self.dont_minimize_variables: return block, index = self.current_position - vars = self.vars_alive_through_op(block, index) + allvars = self.vars_alive_through_op(block, index) + seen = {} # {position: unique Variable} without Voids + unique = {} # {Variable: unique Variable} without Voids + for v in allvars: + if v.concretetype is not lltype.Void: + pos = self.var_position(v) + seen.setdefault(pos, v) + unique[v] = seen[pos] + vars = seen.items() + vars.sort() + vars = [v1 for pos, v1 in vars] self.emit(*self.insert_renaming(vars)) self.free_vars = 0 self.var_positions.clear() - for v in vars: - self.register_var(v, verbose=False) + for v1 in vars: + self.register_var(v1, verbose=False) + for v, v1 in unique.items(): + self.var_positions[v] = self.var_positions[v1] def vars_alive_through_op(self, block, index): """Returns the list of variables that are really used by or after @@ -790,6 +828,13 @@ self.emit(len(l)) self.emit(*l) + def resolve_switch_targets(self, labelpos): + for sd in self.constants: + if isinstance(sd, SwitchDict): + sd.dict = {} + for key, link in sd._maps.items(): + sd.dict[key] = labelpos[link] + # ____________________________________________________________ class label(object): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 15:11:41 2009 @@ -5,6 +5,9 @@ from pypy.tool.uid import uid from pypy.conftest import option +from pypy.jit.metainterp import resoperation as rop +from pypy.jit.metainterp.resoperation import ResOperation + import py from pypy.tool.ansi_print import ansi_log log = py.log.Producer('compiler') Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Mar 1 15:11:41 2009 @@ -99,6 +99,7 @@ self.virtual = False self.virtualized = False self.const = const + self.nonzero = False # NB. never set to True so far self.cls = None self.origfields = {} self.curfields = {} @@ -108,6 +109,12 @@ #self.origsize = -1 #self.cursize = -1 + def is_nonzero(self): + return self.cls is not None or self.nonzero + + def is_zero(self): + return self.const and not self.source.getptr_base() + def escape_if_startbox(self, memo): if self in memo: return @@ -764,26 +771,25 @@ elif opname == 'ooisnull' or opname == 'oononnull': instnode = self.getnode(op.args[0]) # we know the result is constant if instnode is a virtual, - # or if we already checked the class of the object before - if instnode.virtual or instnode.cls is not None: + # a constant, or known to be non-zero. + if instnode.virtual or instnode.const or instnode.is_nonzero(): box = op.result instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue - # XXX we could also do a bit better by marking on the - # InstanceNode that we compared it with NULL already elif opname == 'oois' or opname == 'ooisnot': instnode_x = self.getnode(op.args[0]) instnode_y = self.getnode(op.args[1]) - # we know the result is constant in one of these 4 cases: + # we know the result is constant in one of these 5 cases: if (instnode_x.virtual or # x is a virtual (even if y isn't) instnode_y.virtual or # y is a virtual (even if x isn't) - (instnode_x.cls is not None and # we checked cls x and - instnode_y.const and # y is the const NULL - not instnode_y.source.getptr_base()) or - (instnode_y.cls is not None and # we checked cls y and - instnode_x.const and # x is the const NULL - not instnode_x.source.getptr_base())): + # x != NULL and y == NULL + (instnode_x.is_nonzero() and instnode_y.is_zero()) or + # x == NULL and y != NULL + (instnode_x.is_zero() and instnode_y.is_nonzero()) or + # x == NULL and y == NULL + (instnode_x.is_zero() and instnode_y.is_zero())): + # box = op.result instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Mar 1 15:11:41 2009 @@ -296,13 +296,22 @@ @arguments("orgpc", "box", "constargs", "jumptargets") def opimpl_switch(self, pc, valuebox, constargs, jumptargets): box = self.implement_guard_value(pc, valuebox) - # XXX implement dictionary for speedups at some point for i in range(len(constargs)): casebox = constargs[i] if box.equals(casebox): self.pc = jumptargets[i] break + @arguments("orgpc", "box", "constbox") + def opimpl_switch_dict(self, pc, valuebox, switchdict): + box = self.implement_guard_value(pc, valuebox) + search_value = box.getint() + assert isinstance(switchdict, codewriter.SwitchDict) + try: + self.pc = switchdict.dict[search_value] + except KeyError: + pass + @arguments("constbox") def opimpl_new(self, sizebox): self.execute('new', [sizebox], 'ptr') @@ -574,7 +583,8 @@ @arguments() def opimpl_reraise(self): - xxx + return self.metainterp.finishframe_exception(self.exception_box, + self.exc_value_box) # ------------------------------ Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sun Mar 1 15:11:41 2009 @@ -0,0 +1,40 @@ + +class ResOperation(object): + """The central ResOperation class, representing one operation.""" + + # for 'merge_point' + specnodes = None + key = None + + # for 'jump' and 'guard_*' + jump_target = None + + # for 'guard_*' + counter = 0 + storage_info = None + liveboxes = None + + def __init__(self, opname, args, result): + self.opname = opname + self.args = list(args) + self.result = result + + def __repr__(self): + if self.result is not None: + sres = repr(self.result) + ' = ' + else: + sres = '' + result = '%s%s(%s)' % (sres, self.opname, + ', '.join(map(repr, self.args))) + if self.liveboxes is not None: + result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) + return result + + def clone(self): + op = ResOperation(self.opname, self.args, self.result) + op.specnodes = self.specnodes + op.key = self.key + return op + +# ____________________________________________________________ + Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Sun Mar 1 15:11:41 2009 @@ -282,6 +282,21 @@ assert res == 210 self.check_history_(getfield_gc=0) + def test_switch_dict(self): + def f(x): + if x == 1: return 61 + elif x == 2: return 511 + elif x == 3: return -22 + elif x == 4: return 81 + elif x == 5: return 17 + elif x == 6: return 54 + elif x == 7: return 987 + elif x == 8: return -12 + elif x == 9: return 321 + return -1 + res = self.interp_operations(f, [5]) + assert res == 17 + class TestOOtype(BasicTests, OOJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sun Mar 1 15:11:41 2009 @@ -5,7 +5,7 @@ from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp import heaptracker -from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump, +from pypy.jit.metainterp.history import (ResOperation, ConstInt, ConstAddr, BoxInt, BoxPtr) from pypy.jit.metainterp.optimize import (PerfectSpecializer, VirtualizableSpecNode, @@ -82,7 +82,7 @@ v2 = BoxInt(nextnode.value) sum2 = BoxInt(0 + frame.node.value) ops = [ - MergePoint('merge_point', [sum, fr], None), + ResOperation('merge_point', [sum, fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), ConstInt(ofs_node)], None), ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), @@ -93,7 +93,7 @@ ConstAddr(node_vtable, cpu)], n2), ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], None), - Jump('jump', [sum2, fr], None), + ResOperation('jump', [sum2, fr], None), ] ops[1].vdesc = xy_desc @@ -118,10 +118,10 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [A.sum, A.fr, A.v], None), + ResOperation('merge_point', [A.sum, A.fr, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), - Jump('jump', [A.sum2, A.fr, A.v2], None), + ResOperation('jump', [A.sum2, A.fr, A.v2], None), ]) # ____________________________________________________________ @@ -139,12 +139,12 @@ n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v = BoxInt(13) ops = [ - MergePoint('merge_point', [fr], None), + ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), ConstInt(ofs_node)], None), ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), - Jump('jump', [fr], None), + ResOperation('jump', [fr], None), ] ops[1].vdesc = xy_desc @@ -168,7 +168,7 @@ v2 = BoxInt(13) sizebox = ConstInt(cpu.sizeof(NODE)) ops = [ - MergePoint('merge_point', [fr], None), + ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), ConstInt(ofs_node)], None), # @@ -181,7 +181,7 @@ ResOperation('guard_class', [n2, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], v2), # - Jump('jump', [fr], None), + ResOperation('jump', [fr], None), ] ops[1].vdesc = xy_desc @@ -212,7 +212,7 @@ v2 = BoxInt(13) l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) ops = [ - MergePoint('merge_point', [fr], None), + ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), ConstInt(ofs_node)], None), # @@ -220,7 +220,7 @@ ResOperation('guard_builtin', [l, SomeDescr()], None), ResOperation('getitem', [None, l, ConstInt(0)], v2), ResOperation('setitem', [None, l, ConstInt(0), v2], None), - Jump('jump', [fr], None), + ResOperation('jump', [fr], None), ] ops[1].vdesc = xy_desc Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Sun Mar 1 15:11:41 2009 @@ -17,8 +17,8 @@ config.objspace.allworkingmodules = False config.objspace.usemodules.pypyjit = True set_pypy_opt_level(config, level='0') -config.objspace.std.multimethods = 'doubledispatch' -multimethod.Installer = multimethod.InstallerVersion1 +config.objspace.std.multimethods = 'mrd' +multimethod.Installer = multimethod.InstallerVersion2 print config Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Sun Mar 1 15:11:41 2009 @@ -23,7 +23,7 @@ # Consts -- make sure that these Consts are not stored, or else # remove them entirely # -# - dead operation removal: e.g. line 158 +# - dead operation removal: e.g. unused 'getfield_gc' (line 158) def run_child(glob, loc): From arigo at codespeak.net Sun Mar 1 15:19:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 1 Mar 2009 15:19:07 +0100 (CET) Subject: [pypy-svn] r62295 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/llgraph/test metainterp metainterp/test Message-ID: <20090301141907.DC55816855C@codespeak.net> Author: arigo Date: Sun Mar 1 15:19:06 2009 New Revision: 62295 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Replace ResOperation.opname with ResOperation.opnum. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sun Mar 1 15:19:06 2009 @@ -15,7 +15,8 @@ from pypy.rpython.llinterp import LLInterpreter, LLFrame, LLException from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.jit.metainterp import heaptracker +from pypy.jit.metainterp import heaptracker, resoperation +from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llgraph import symbolic from pypy.rlib.objectmodel import ComputedIntSymbolic @@ -131,8 +132,8 @@ return '\n'.join(lines) class Operation(object): - def __init__(self, opname): - self.opname = opname + def __init__(self, opnum): + self.opnum = opnum self.args = [] self.result = None self.livevars = [] # for guards only @@ -142,9 +143,15 @@ sres = repr0(self.result) + ' = ' else: sres = '' - return '{%s%s(%s)}' % (sres, self.opname, + return '{%s%s(%s)}' % (sres, self.getopname(), ', '.join(map(repr0, self.args))) + def getopname(self): + try: + return resoperation.opname[self.opnum] + except KeyError: + return '<%d>' % self.opnum + def repr0(x): if isinstance(x, list): return '[' + ', '.join(repr0(y) for y in x) + ']' @@ -240,10 +247,9 @@ _variables.append(v) return r -def compile_add(loop, opname): +def compile_add(loop, opnum): loop = _from_opaque(loop) - opname = from_opaque_string(opname) - loop.operations.append(Operation(opname)) + loop.operations.append(Operation(opnum)) def compile_add_var(loop, intvar): loop = _from_opaque(loop) @@ -290,7 +296,7 @@ op = loop.operations[-1] op.jump_target = loop_target op.jump_target_index = loop_target_index - if op.opname == 'jump': + if op.opnum == rop.JUMP: if loop_target == loop and loop_target_index == 0: log.info("compiling new loop") else: @@ -310,7 +316,7 @@ loop = _from_opaque(loop) guard_loop = _from_opaque(guard_loop) op = guard_loop.operations[guard_opindex] - assert op.opname.startswith('guard_') + assert rop._GUARD_FIRST <= op.opnum <= rop._GUARD_LAST op.jump_target = loop op.jump_target_index = 0 @@ -350,17 +356,18 @@ self.opindex += 1 op = self.loop.operations[self.opindex] args = [self.getenv(v) for v in op.args] - if op.opname == 'merge_point': + if op.opnum == rop.MERGE_POINT: self.go_to_merge_point(self.loop, self.opindex, args) continue - if op.opname == 'jump': + if op.opnum == rop.JUMP: self.go_to_merge_point(op.jump_target, op.jump_target_index, args) _stats.exec_jumps += 1 continue + opname = resoperation.opname[op.opnum].lower() try: - result = self.execute_operation(op.opname, args, verbose) + result = self.execute_operation(opname, args, verbose) #verbose = self.verbose assert (result is None) == (op.result is None) if op.result is not None: @@ -379,7 +386,7 @@ # the guard already failed once, go to the # already-generated code catch_op = op.jump_target.operations[0] - assert catch_op.opname == 'catch' + assert catch_op.opnum == rop.CATCH args = [] it = iter(op.livevars) for v in catch_op.args: @@ -394,7 +401,7 @@ else: if self.verbose: log.trace('failed: %s(%s)' % ( - op.opname, ', '.join(map(str, args)))) + opname, ', '.join(map(str, args)))) self.failed_guard_op = op return op.failnum Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sun Mar 1 15:19:06 2009 @@ -4,6 +4,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.metainterp import history +from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.backend.llgraph import llimpl, symbolic @@ -54,12 +55,12 @@ j = 0 for i in range(len(operations)): op = operations[i] - if op.opname[0] == '#': - continue + #if op.opname[0] == '#': + # continue op._compiled = c op._opindex = j j += 1 - llimpl.compile_add(c, op.opname) + llimpl.compile_add(c, op.opnum) for x in op.args: if isinstance(x, history.Box): llimpl.compile_add_var(c, var2index[x]) @@ -71,7 +72,8 @@ isinstance(x, history.ConstAddr)): llimpl.compile_add_int_const(c, x.getint()) else: - raise Exception("%s args contain: %r" % (op.opname, x)) + raise Exception("%s args contain: %r" % (op.getopname(), + x)) x = op.result if x is not None: if isinstance(x, history.BoxInt): @@ -79,19 +81,20 @@ elif isinstance(x, history.BoxPtr): var2index[x] = llimpl.compile_add_ptr_result(c) else: - raise Exception("%s.results contain: %r" % (op.opname, x)) + raise Exception("%s.result contain: %r" % (op.getopname(), + x)) if op.jump_target is not None: loop_target, loop_target_index = \ self.jumptarget2loop[op.jump_target] llimpl.compile_add_jump_target(c, loop_target, loop_target_index) - if op.opname.startswith('guard_'): + if op.is_guard(): llimpl.compile_add_failnum(c, len(self.guard_ops)) self.guard_ops.append(op) for box in op.liveboxes: if isinstance(box, history.Box): llimpl.compile_add_livebox(c, var2index[box]) - if op.opname == 'merge_point': + if op.opnum == rop.MERGE_POINT: self.jumptarget2loop[op] = c, i if from_guard is not None: llimpl.compile_from_guard(c, from_guard._compiled, @@ -119,14 +122,14 @@ raise Exception("bad box in valueboxes: %r" % (box,)) return self.loop(frame) - def execute_operation(self, opname, valueboxes, result_type): + def execute_operation(self, opnum, valueboxes, result_type): """Execute a single operation, returning the result. Mostly a hack: falls back to interpreting a complete bridge containing the operation. """ - if opname[0] == '#': - return None - c = self.get_compiled_single_op(opname, valueboxes, result_type) + #if opname[0] == '#': + # return None + c = self.get_compiled_single_op(opnum, valueboxes, result_type) frame = llimpl.new_frame(self.memo_cast) llimpl.frame_clear(frame, c, 0) for box in valueboxes: @@ -145,8 +148,9 @@ else: return None - def get_compiled_single_op(self, opname, valueboxes, result_type): - keylist = self.compiled_single_ops.setdefault((opname, result_type), + def get_compiled_single_op(self, opnum, valueboxes, result_type): + assert isinstance(opnum, int) + keylist = self.compiled_single_ops.setdefault((opnum, result_type), []) types = [valuebox.type for valuebox in valueboxes] for key, impl in keylist: @@ -176,9 +180,9 @@ if resbox is not None: resboxes.append(resbox) operations = [ - history.ResOperation('merge_point', valueboxes, None), - history.ResOperation(opname, valueboxes, resbox), - history.ResOperation('return', resboxes, None), + ResOperation(rop.MERGE_POINT, valueboxes, None), + ResOperation(opnum, valueboxes, resbox), + ResOperation(rop.RETURN, resboxes, None), ] self.compile_operations(operations) impl = operations[0]._compiled Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Sun Mar 1 15:19:06 2009 @@ -4,7 +4,7 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.jit.metainterp.history import BoxInt, BoxPtr, Const, ConstInt -from pypy.jit.metainterp.history import ResOperation, MergePoint, Jump +from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.backend.llgraph.runner import CPU, GuardFailed @@ -45,7 +45,8 @@ def test_simple(self): cpu = CPU(None) - box = cpu.execute_operation("int_sub", [BoxInt(10), BoxInt(2)], "int") + box = cpu.execute_operation(rop.INT_SUB, [BoxInt(10), BoxInt(2)], + "int") assert isinstance(box, BoxInt) assert box.value == 8 @@ -54,15 +55,15 @@ node = lltype.malloc(NODE) node_value = cpu.fielddescrof(NODE, 'value') nodeadr = lltype.cast_opaque_ptr(llmemory.GCREF, node) - box = cpu.execute_operation('setfield_gc', [BoxPtr(nodeadr), - ConstInt(node_value), - BoxInt(3)], + box = cpu.execute_operation(rop.SETFIELD_GC, [BoxPtr(nodeadr), + ConstInt(node_value), + BoxInt(3)], 'void') assert box is None assert node.value == 3 - box = cpu.execute_operation('getfield_gc', [BoxPtr(nodeadr), - ConstInt(node_value)], + box = cpu.execute_operation(rop.GETFIELD_GC, [BoxPtr(nodeadr), + ConstInt(node_value)], 'int') assert box.value == 3 @@ -75,12 +76,12 @@ t = BoxInt(455) u = BoxInt(0) operations = [ - MergePoint('merge_point', [x, y], None), - ResOperation('int_add', [x, y], z), - ResOperation('int_sub', [y, ConstInt(1)], t), - ResOperation('int_eq', [t, ConstInt(0)], u), - ResOperation('guard_false', [u], None), - Jump('jump', [z, t], None), + ResOperation(rop.MERGE_POINT, [x, y], None), + ResOperation(rop.INT_ADD, [x, y], z), + ResOperation(rop.INT_SUB, [y, ConstInt(1)], t), + ResOperation(rop.INT_EQ, [t, ConstInt(0)], u), + ResOperation(rop.GUARD_FALSE, [u], None), + ResOperation(rop.JUMP, [z, t], None), ] operations[-2].liveboxes = [t, z] startmp = operations[0] @@ -98,10 +99,12 @@ def test_passing_guards(self): py.test.skip("rewrite me") cpu = CPU(None) - assert cpu.execute_operation('guard_true', [BoxInt(1)], 'void') == None - assert cpu.execute_operation('guard_false',[BoxInt(0)], 'void') == None - assert cpu.execute_operation('guard_value',[BoxInt(42), - BoxInt(42)],'void') == None + assert cpu.execute_operation(rop.GUARD_TRUE, [BoxInt(1)], + 'void') == None + assert cpu.execute_operation(rop.GUARD_FALSE,[BoxInt(0)], + 'void') == None + assert cpu.execute_operation(rop.GUARD_VALUE,[BoxInt(42), BoxInt(42)], + 'void') == None #subnode = lltype.malloc(SUBNODE) #assert cpu.execute_operation('guard_class', [subnode, SUBNODE]) == [] #assert cpu.stats.exec_counters == {'guard_true': 1, 'guard_false': 1, @@ -114,16 +117,16 @@ cpu.set_meta_interp(FakeMetaInterp(cpu)) #node = ootype.new(NODE) #subnode = ootype.new(SUBNODE) - for opname, args in [('guard_true', [BoxInt(0)]), - ('guard_false', [BoxInt(1)]), - ('guard_value', [BoxInt(42), BoxInt(41)]), - #('guard_class', [node, SUBNODE]), - #('guard_class', [subnode, NODE]), - ]: + for opnum, args in [(rop.GUARD_TRUE, [BoxInt(0)]), + (rop.GUARD_FALSE, [BoxInt(1)]), + (rop.GUARD_VALUE, [BoxInt(42), BoxInt(41)]), + #('guard_class', [node, SUBNODE]), + #('guard_class', [subnode, NODE]), + ]: operations = [ - MergePoint('merge_point', args, []), - ResOperation(opname, args, []), - ResOperation('void_return', [], []), + ResOperation(rop.MERGE_POINT, args, []), + ResOperation(opnum, args, []), + ResOperation(rop.VOID_RETURN, [], []), ] startmp = operations[0] cpu.compile_operations(operations) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Sun Mar 1 15:19:06 2009 @@ -4,7 +4,8 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.conftest import option -from pypy.jit.metainterp.history import Graph, ResOperation, log, Box +from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.metainterp.history import Graph, log, Box from pypy.jit.metainterp import optimize @@ -135,14 +136,14 @@ return loop def close_loop(loop, targetmp, endliveboxes): - assert targetmp.opname == 'merge_point' - op = ResOperation('jump', endliveboxes, None) + assert targetmp.opnum == rop.MERGE_POINT + op = ResOperation(rop.JUMP, endliveboxes, None) op.jump_target = targetmp loop.operations.append(op) def finish_loop_or_bridge(metainterp, loop, targetmp, guard_op=None): - assert targetmp.opname == 'merge_point' - assert loop.operations[-1].opname == 'jump' + assert targetmp.opnum == rop.MERGE_POINT + assert loop.operations[-1].opnum == rop.JUMP loop.operations[-1].jump_target = targetmp metainterp.cpu.compile_operations(loop.operations, guard_op) metainterp.stats.loops.append(loop) @@ -155,12 +156,12 @@ def compile_fresh_bridge(metainterp, bridge, old_loops, endliveboxes): history = metainterp.history catch_op = history.operations[0] - assert catch_op.opname == 'catch' + assert catch_op.opnum == rop.CATCH guard_op = catch_op.coming_from - assert guard_op.opname.startswith('guard_') + assert guard_op.is_guard() # operations = bridge.operations = history.operations - op = ResOperation('jump', endliveboxes, None) + op = ResOperation(rop.JUMP, endliveboxes, None) operations.append(op) # old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Sun Mar 1 15:19:06 2009 @@ -137,10 +137,10 @@ if tgt is not None and tgt in self.all_operations: tgt_g, tgt_i = self.all_operations[tgt] kwds = {} - if op.opname == 'jump': - #kwds['constraint'] = 'false' - #kwds['headport'] = ':n' - pass + #if op.opname == 'jump': + # #kwds['constraint'] = 'false' + # #kwds['headport'] = ':n' + # pass self.genedge((graphindex, opstartindex), (tgt_g, tgt_i+delta), color='red', @@ -150,8 +150,8 @@ break if opindex in block_starters: kwds = {} - if op.opname == 'jump': - kwds['color'] = '#d0d0ff' + #if op.opname == 'jump': + # kwds['color'] = '#d0d0ff' self.genedge((graphindex, opstartindex), (graphindex, opindex), **kwds) break Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Sun Mar 1 15:19:06 2009 @@ -79,28 +79,3 @@ return cache testing_gcstruct2vtable = {} - -# ____________________________________________________________ -# helpers - -def setup(): - for _opname, _opdesc in lloperation.LL_OPERATIONS.iteritems(): - if _opdesc.canfold: - always_pure_operations[_opname] = None - if not _opdesc.sideeffects: - operations_without_side_effects[_opname] = None - if not _opdesc.canraise: - operation_never_raises[_opname] = None - - # XXX fish fish fish - operations_without_side_effects['getfield_gc'] = None - -operations_without_side_effects = {} -always_pure_operations = {} -operation_never_raises = {} - -for guard in ['guard_no_exception', 'guard_true', - 'guard_false', 'guard_value', 'guard_class']: - operation_never_raises[guard] = None - -setup() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 15:19:06 2009 @@ -5,8 +5,7 @@ from pypy.tool.uid import uid from pypy.conftest import option -from pypy.jit.metainterp import resoperation as rop -from pypy.jit.metainterp.resoperation import ResOperation +from pypy.jit.metainterp.resoperation import ResOperation, rop import py from pypy.tool.ansi_print import ansi_log @@ -280,53 +279,6 @@ # ____________________________________________________________ -class ResOperation(object): - """The central ResOperation class, representing one operation.""" - - # for 'merge_point' - specnodes = None - key = None - - # for 'jump' and 'guard_*' - jump_target = None - - # for 'guard_*' - counter = 0 - storage_info = None - liveboxes = None - - def __init__(self, opname, args, result): - if not we_are_translated(): - assert result is None or isinstance(result, Box) - if opname == 'merge_point': - assert len(dict.fromkeys(args)) == len(args) - self.opname = opname - self.args = list(args) - self.result = result - - def __repr__(self): - if self.result is not None: - sres = repr(self.result) + ' = ' - else: - sres = '' - result = '%s%s(%s)' % (sres, self.opname, - ', '.join(map(repr, self.args))) - if self.liveboxes is not None: - result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) - return result - - def clone(self): - op = ResOperation(self.opname, self.args, self.result) - op.specnodes = self.specnodes - op.key = self.key - return op - -# compatibility -MergePoint = ResOperation -Jump = ResOperation - -# ____________________________________________________________ - # The Graph class is to store a loop or a bridge. # Unclear if it's really useful any more; just the list of operations # is enough in most cases. @@ -344,7 +296,8 @@ def summary(self, adding_insns={}): # for debugging insns = adding_insns.copy() for op in self.operations: - insns[op.opname] = insns.get(op.opname, 0) + 1 + opname = op.getopname() + insns[opname] = insns.get(opname, 0) + 1 return insns def get_display_text(self): # for graphpage.py @@ -369,22 +322,22 @@ "NOT_RPYTHON" operations = self.operations op = operations[0] - assert op.opname in ('merge_point', 'catch') + assert op.opnum in (rop.MERGE_POINT, rop.CATCH) seen = dict.fromkeys(op.args) for op in operations[1:]: for box in op.args: if isinstance(box, Box): assert box in seen elif isinstance(box, Const): - assert op.opname not in ('merge_point', 'catch'), ( + assert op.opnum not in (rop.MERGE_POINT, rop.CATCH), ( "no Constant arguments allowed in: %s" % (op,)) box = op.result if box is not None: assert isinstance(box, Box) assert box not in seen seen[box] = True - assert operations[-1].opname == 'jump' - assert operations[-1].jump_target.opname == 'merge_point' + assert operations[-1].opnum == rop.JUMP + assert operations[-1].jump_target.opnum == rop.MERGE_POINT def __repr__(self): return '<%s>' % (self.name,) @@ -402,7 +355,7 @@ self.cpu = cpu self.operations = [] - def execute_and_record(self, step, argboxes, result_type, pure): + def execute_and_record(self, opnum, argboxes, result_type, pure): # collect arguments canfold = False if pure: @@ -412,17 +365,17 @@ else: canfold = True # really run this operation - resbox = self.cpu.execute_operation(step, argboxes, result_type) + resbox = self.cpu.execute_operation(opnum, argboxes, result_type) # collect the result(s) if canfold: resbox = resbox.constbox() else: - self.record(step, argboxes, resbox) + self.record(opnum, argboxes, resbox) return resbox execute_and_record._annspecialcase_ = 'specialize:arg(4)' - def record(self, opname, argboxes, resbox): - op = ResOperation(opname, argboxes, resbox) + def record(self, opnum, argboxes, resbox): + op = ResOperation(opnum, argboxes, resbox) self.operations.append(op) return op record._annspecialcase_ = 'specialize:arg(4)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Mar 1 15:19:06 2009 @@ -1,9 +1,7 @@ +from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, ResOperation) from pypy.jit.metainterp.history import Options -from pypy.jit.metainterp.heaptracker import (always_pure_operations, - operations_without_side_effects, - operation_never_raises) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, #FixedListSpecNode, VirtualInstanceSpecNode, @@ -305,12 +303,12 @@ self.nodes[box] = InstanceNode(box, escaped=False, startbox=True, const=isinstance(box, Const)) for op in self.loop.operations: - opname = op.opname - if (opname == 'merge_point' or - opname == 'catch' or - opname == 'jump'): + opnum = op.opnum + if (opnum == rop.MERGE_POINT or + opnum == rop.CATCH or + opnum == rop.JUMP): continue - elif opname == 'new_with_vtable': + elif opnum == rop.NEW_WITH_VTABLE: box = op.result instnode = InstanceNode(box, escaped=False) instnode.cls = InstanceNode(op.args[1], const=True) @@ -343,7 +341,7 @@ ## instnode.cursize = size ## instnode.origsize = size ## continue - elif opname == 'setfield_gc': + elif opnum == rop.SETFIELD_GC: instnode = self.getnode(op.args[0]) fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) @@ -351,7 +349,7 @@ self.find_nodes_setfield(instnode, field, self.getnode(op.args[2])) continue - elif opname == 'getfield_gc': + elif opnum == rop.GETFIELD_GC: instnode = self.getnode(op.args[0]) fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) @@ -434,12 +432,12 @@ ## self.dependency_graph.append((instnode, ## self.getnode(op.args[3]))) ## instnode.escaped = True - elif opname == 'guard_class': + elif opnum == rop.GUARD_CLASS: instnode = self.getnode(op.args[0]) if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) continue - elif opname == 'guard_value': + elif opnum == rop.GUARD_VALUE: instnode = self.getnode(op.args[0]) assert isinstance(op.args[1], Const) # XXX need to think more about the 'const' attribute @@ -447,14 +445,14 @@ #self.nodes[instnode.source] = InstanceNode(op.args[1], # const=True) continue - elif opname == 'guard_nonvirtualized': + elif opnum == rop.GUARD_NONVIRTUALIZED: instnode = self.getnode(op.args[0]) if instnode.startbox: instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) continue - elif opname in always_pure_operations: + elif op.is_always_pure(): for arg in op.args: if not self.getnode(arg).const: break @@ -465,7 +463,7 @@ escaped=True, const=True) continue - elif opname not in operations_without_side_effects: + elif not op.has_no_side_effect(): # default case self.first_escaping_op = False for box in op.args: @@ -476,7 +474,7 @@ self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): - assert self.loop.operations[0].opname == 'merge_point' + assert self.loop.operations[0].opnum == rop.MERGE_POINT end_args = self.loop.operations[-1].args memo = {} for i in range(len(end_args)): @@ -504,8 +502,8 @@ self.recursively_find_escaping_values() mp = self.loop.operations[0] jump = self.loop.operations[-1] - assert mp.opname == 'merge_point' - assert jump.opname == 'jump' + assert mp.opnum == rop.MERGE_POINT + assert jump.opnum == rop.JUMP specnodes = [] for i in range(len(mp.args)): enternode = self.nodes[mp.args[i]] @@ -618,13 +616,13 @@ exception_might_have_happened = False #ops_so_far = [] mp = self.loop.operations[0] - if mp.opname == 'merge_point': + if mp.opnum == rop.MERGE_POINT: assert len(mp.args) == len(self.specnodes) for i in range(len(self.specnodes)): box = mp.args[i] self.specnodes[i].mutate_nodes(self.nodes[box]) else: - assert mp.opname == 'catch' + assert mp.opnum == rop.CATCH for box in mp.args: self.nodes[box].cls = None assert not self.nodes[box].virtual @@ -634,10 +632,10 @@ #if newoperations and newoperations[-1].results: # self.ready_results[newoperations[-1].results[0]] = None - opname = op.opname - if opname == 'merge_point': + opnum = op.opnum + if opnum == rop.MERGE_POINT: args = self.expanded_version_of(op.args, None) - op = ResOperation('merge_point', args, None) + op = ResOperation(rop.MERGE_POINT, args, None) newoperations.append(op) #for arg in op.args: # self.ready_results[arg] = None @@ -645,10 +643,10 @@ #elif opname == 'catch': # for arg in op.args: # self.ready_results[arg] = None - elif opname == 'jump': + elif opnum == rop.JUMP: args = self.expanded_version_of(op.args, newoperations) self.cleanup_field_caches(newoperations) - op = ResOperation('jump', args, None) + op = ResOperation(rop.JUMP, args, None) newoperations.append(op) continue ## elif opname == 'guard_builtin': @@ -664,36 +662,43 @@ ## instnode = self.nodes[op.args[0]] ## instnode.cursize = op.args[1].getint() ## continue - elif (opname == 'guard_no_exception' or - opname == 'guard_exception'): + elif (opnum == rop.GUARD_NO_EXCEPTION or + opnum == rop.GUARD_EXCEPTION): if not exception_might_have_happened: continue exception_might_have_happened = False - op = self.optimize_guard(op) - newoperations.append(op) + newoperations.append(self.optimize_guard(op)) continue - elif opname.startswith('guard_'): + elif (opnum == rop.GUARD_TRUE or + opnum == rop.GUARD_FALSE): instnode = self.nodes[op.args[0]] - if opname == 'guard_true' or opname == 'guard_false': - if instnode.const: - continue - elif opname == 'guard_class': - if instnode.cls is not None: - assert op.args[1].equals(instnode.cls.source) - continue - instnode.cls = InstanceNode(op.args[1], const=True) - elif opname == 'guard_value': - assert isinstance(op.args[1], Const) - if instnode.const: - continue - instnode.const = True - elif opname == 'guard_nonvirtualized': - if instnode.virtualized or instnode.virtual: - continue - op = self.optimize_guard(op) - newoperations.append(op) + if instnode.const: + continue + newoperations.append(self.optimize_guard(op)) + continue + elif opnum == rop.GUARD_CLASS: + instnode = self.nodes[op.args[0]] + if instnode.cls is not None: + assert op.args[1].equals(instnode.cls.source) + continue + instnode.cls = InstanceNode(op.args[1], const=True) + newoperations.append(self.optimize_guard(op)) continue - elif opname == 'getfield_gc': + elif opnum == rop.GUARD_VALUE: + instnode = self.nodes[op.args[0]] + assert isinstance(op.args[1], Const) + if instnode.const: + continue + instnode.const = True + newoperations.append(self.optimize_guard(op)) + continue + elif opnum == rop.GUARD_NONVIRTUALIZED: + instnode = self.nodes[op.args[0]] + if instnode.virtualized or instnode.virtual: + continue + newoperations.append(self.optimize_guard(op)) + continue + elif opnum == rop.GETFIELD_GC: instnode = self.nodes[op.args[0]] ofs = op.args[1].getint() if self.optimize_getfield(instnode, ofs, op.result): @@ -707,7 +712,7 @@ ## ofs = ofsbox.getint() ## if self.optimize_getfield(instnode, ofs, op.results[0]): ## continue - elif opname == 'new_with_vtable': + elif opnum == rop.NEW_WITH_VTABLE: # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.result] if not instnode.escaped: @@ -754,7 +759,7 @@ ## instnode = self.nodes[op.args[1]] ## if instnode.virtual: ## continue - elif opname == 'setfield_gc': + elif opnum == rop.SETFIELD_GC: instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] ofs = op.args[1].getint() @@ -768,7 +773,8 @@ ## ofs = ofsbox.getint() ## self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) ## continue - elif opname == 'ooisnull' or opname == 'oononnull': + elif (opnum == rop.OOISNULL or + opnum == rop.OONONNULL): instnode = self.getnode(op.args[0]) # we know the result is constant if instnode is a virtual, # a constant, or known to be non-zero. @@ -777,7 +783,8 @@ instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue - elif opname == 'oois' or opname == 'ooisnot': + elif (opnum == rop.OOIS or + opnum == rop.OOISNOT): instnode_x = self.getnode(op.args[0]) instnode_y = self.getnode(op.args[1]) # we know the result is constant in one of these 5 cases: @@ -794,9 +801,9 @@ instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue - # default handling of arguments and return value(s) + # default handling of arguments and return value op = self.replace_arguments(op) - if opname in always_pure_operations: + if op.is_always_pure(): for box in op.args: if isinstance(box, Box): break @@ -807,13 +814,12 @@ instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue - elif opname not in operations_without_side_effects: - if opname not in ('getfield_gc', 'getitem', - 'setfield_gc', 'setitem'): - # those operations does not clean up caches, although - # they have side effects (at least set ones) - self.cleanup_field_caches(newoperations) - if opname not in operation_never_raises: # XXX do me right + elif (not op.has_no_side_effect() + and opnum != rop.SETFIELD_GC): + # the setfield operations do not clean up caches, although + # they have side effects + self.cleanup_field_caches(newoperations) + if op.can_raise(): exception_might_have_happened = True box = op.result if box is not None: @@ -836,7 +842,7 @@ ## ConstInt(ofs), valuenode.source], [])) ## else: if 1: - newoperations.append(ResOperation('setfield_gc', + newoperations.append(ResOperation(rop.SETFIELD_GC, [node.source, ConstInt(ofs), valuenode.source], None)) node.dirtyfields = {} node.cleanfields = {} @@ -855,7 +861,7 @@ def match(self, old_operations): old_mp = old_operations[0] jump_op = self.loop.operations[-1] - assert jump_op.opname == 'jump' + assert jump_op.opnum == rop.JUMP assert len(old_mp.specnodes) == len(jump_op.args) for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] @@ -890,7 +896,7 @@ for vtable in storage.allocations: sizebox = ConstInt(metainterp.class_sizes[vtable]) vtablebox = ConstInt(vtable) - instbox = history.execute_and_record('new_with_vtable', + instbox = history.execute_and_record(rop.NEW_WITH_VTABLE, [sizebox, vtablebox], 'ptr', False) allocated_boxes.append(instbox) @@ -906,7 +912,7 @@ box = box_from_index(allocated_boxes, ## allocated_lists, boxes_from_frame, index_in_alloc) - history.execute_and_record('setfield_gc', + history.execute_and_record(rop.SETFIELD_GC, [box, ConstInt(ofs), fieldbox], 'void', False) ## for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Mar 1 15:19:06 2009 @@ -10,6 +10,7 @@ from pypy.jit.metainterp import history, support from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr, Box, BoxInt, BoxPtr, Options) +from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) @@ -235,32 +236,32 @@ exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(%r, [b1, b2], "int", True) - ''' % (_opimpl, _opimpl)).compile() + self.execute(rop.%s, [b1, b2], "int", True) + ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', ]: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - return self.execute_with_exc(%r, [b1, b2], "int", True) - ''' % (_opimpl, _opimpl)).compile() + return self.execute_with_exc(rop.%s, [b1, b2], "int", True) + ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', ]: exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(%r, [b], "int", True) - ''' % (_opimpl, _opimpl)).compile() + self.execute(rop.%s, [b], "int", True) + ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_neg_ovf', ]: exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - return self.execute_with_exc(%r, [b], "int", True) - ''' % (_opimpl, _opimpl)).compile() + return self.execute_with_exc(rop.%s, [b], "int", True) + ''' % (_opimpl, _opimpl.upper())).compile() @arguments() def opimpl_return(self): @@ -282,15 +283,15 @@ if switchcase: currentpc = self.pc targetpc = target - opname = "guard_true" + opnum = rop.GUARD_TRUE const_if_fail = history.CONST_FALSE else: currentpc = target targetpc = self.pc - opname = "guard_false" + opnum = rop.GUARD_FALSE const_if_fail = history.CONST_TRUE - self.generate_guard(targetpc, opname, box, ignore_box=box, - const_if_fail=const_if_fail) + self.generate_guard(targetpc, opnum, box, ignore_box=box, + const_if_fail=const_if_fail) self.pc = currentpc @arguments("orgpc", "box", "constargs", "jumptargets") @@ -314,67 +315,67 @@ @arguments("constbox") def opimpl_new(self, sizebox): - self.execute('new', [sizebox], 'ptr') + self.execute(rop.NEW, [sizebox], 'ptr') @arguments("constbox", "constbox") def opimpl_new_with_vtable(self, sizebox, vtablebox): - self.execute('new_with_vtable', [sizebox, vtablebox], 'ptr') + self.execute(rop.NEW_WITH_VTABLE, [sizebox, vtablebox], 'ptr') @arguments("constbox", "box") def opimpl_new_array(self, itemsizebox, countbox): - self.execute('new_array', [itemsizebox, countbox], 'ptr') + self.execute(rop.NEW_ARRAY, [itemsizebox, countbox], 'ptr') @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): tp = self.metainterp.cpu.typefor(arraydesc.getint()) - self.execute('getarrayitem_gc', [arraybox, arraydesc, indexbox], tp) + self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox], tp) @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): - self.execute('setarrayitem_gc', [arraybox, arraydesc, - indexbox, itembox], 'void') + self.execute(rop.SETARRAYITEM_GC, [arraybox, arraydesc, + indexbox, itembox], 'void') @arguments("box") def opimpl_ptr_nonzero(self, box): - self.execute('oononnull', [box], 'int', True) + self.execute(rop.OONONNULL, [box], 'int', True) @arguments("box") def opimpl_ptr_iszero(self, box): - self.execute('ooisnull', [box], 'int', True) + self.execute(rop.OOISNULL, [box], 'int', True) @arguments("box", "box") def opimpl_ptr_eq(self, box1, box2): - self.execute('oois', [box1, box2], 'int', True) + self.execute(rop.OOIS, [box1, box2], 'int', True) @arguments("box", "box") def opimpl_ptr_ne(self, box1, box2): - self.execute('ooisnot', [box1, box2], 'int', True) + self.execute(rop.OOISNOT, [box1, box2], 'int', True) @arguments("box", "constbox") def opimpl_getfield_gc(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute('getfield_gc', [box, fielddesc], tp) + self.execute(rop.GETFIELD_GC, [box, fielddesc], tp) @arguments("box", "constbox") def opimpl_getfield_pure_gc(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute('getfield_gc', [box, fielddesc], tp, True) + self.execute(rop.GETFIELD_GC, [box, fielddesc], tp, True) @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute('setfield_gc', [box, fielddesc, valuebox], + self.execute(rop.SETFIELD_GC, [box, fielddesc, valuebox], 'void') @arguments("box", "constbox") def opimpl_getfield_raw(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute('getfield_raw', [box, fielddesc], tp) + self.execute(rop.GETFIELD_RAW, [box, fielddesc], tp) @arguments("box", "constbox") def opimpl_getfield_pure_raw(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute('getfield_raw', [box, fielddesc], tp, True) + self.execute(rop.GETFIELD_RAW, [box, fielddesc], tp, True) @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute('setfield_raw', [box, fielddesc, valuebox], + self.execute(rop.SETFIELD_RAW, [box, fielddesc, valuebox], 'void') @arguments("bytecode", "varargs") @@ -385,41 +386,41 @@ @arguments("varargs") def opimpl_green_call__1(self, varargs): - return self.execute_with_exc('call__1', varargs, 'int', True) + return self.execute_with_exc(rop.CALL__1, varargs, 'int', True) @arguments("varargs") def opimpl_green_call__2(self, varargs): - return self.execute_with_exc('call__2', varargs, 'int', True) + return self.execute_with_exc(rop.CALL__2, varargs, 'int', True) @arguments("varargs") def opimpl_green_call__4(self, varargs): - return self.execute_with_exc('call__4', varargs, 'int', True) + return self.execute_with_exc(rop.CALL__4, varargs, 'int', True) @arguments("varargs") def opimpl_green_call__8(self, varargs): - return self.execute_with_exc('call__8', varargs, 'int', True) + return self.execute_with_exc(rop.CALL__8, varargs, 'int', True) @arguments("varargs") def opimpl_green_call_ptr(self, varargs): - return self.execute_with_exc('call_ptr', varargs, 'ptr', True) + return self.execute_with_exc(rop.CALL_PTR, varargs, 'ptr', True) @arguments("varargs") def opimpl_residual_call__1(self, varargs): - return self.execute_with_exc('call__1', varargs, 'int') + return self.execute_with_exc(rop.CALL__1, varargs, 'int') @arguments("varargs") def opimpl_residual_call__2(self, varargs): - return self.execute_with_exc('call__2', varargs, 'int') + return self.execute_with_exc(rop.CALL__2, varargs, 'int') @arguments("varargs") def opimpl_residual_call__4(self, varargs): - return self.execute_with_exc('call__4', varargs, 'int') + return self.execute_with_exc(rop.CALL__4, varargs, 'int') @arguments("varargs") def opimpl_residual_call__8(self, varargs): - return self.execute_with_exc('call__8', varargs, 'int') + return self.execute_with_exc(rop.CALL__8, varargs, 'int') @arguments("varargs") def opimpl_residual_call_ptr(self, varargs): - return self.execute_with_exc('call_ptr', varargs, 'ptr') + return self.execute_with_exc(rop.CALL_PTR, varargs, 'ptr') @arguments("varargs") def opimpl_residual_call_void(self, varargs): - return self.execute_with_exc('call_void', varargs, 'void') + return self.execute_with_exc(rop.CALL_VOID, varargs, 'void') @arguments("builtin", "varargs") @@ -487,19 +488,19 @@ @arguments("box") def opimpl_strlen(self, str): - self.execute('strlen', [str], 'int', True) + self.execute(rop.STRLEN, [str], 'int', True) @arguments("box", "box") def opimpl_strgetitem(self, str, index): - self.execute('strgetitem', [str, index], 'int', True) + self.execute(rop.STRGETITEM, [str, index], 'int', True) @arguments("box", "box", "box") def opimpl_strsetitem(self, str, index, newchar): - self.execute('strsetitem', [str, index, newchar], 'void') + self.execute(rop.STRSETITEM, [str, index, newchar], 'void') @arguments("box") def opimpl_newstr(self, length): - self.execute('newstr', [length], 'ptr') + self.execute(rop.NEWSTR, [length], 'ptr') @arguments("orgpc", "box", returns="box") def opimpl_guard_value(self, pc, box): @@ -509,7 +510,7 @@ def opimpl_guard_class(self, pc, box): clsbox = self.cls_of_box(box) if isinstance(box, Box): - self.generate_guard(pc, 'guard_class', box, [clsbox]) + self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox]) return clsbox @arguments("orgpc", "box", "builtin") @@ -525,7 +526,7 @@ @arguments("orgpc", "box", "virtualizabledesc", "constbox") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) - op = self.generate_guard(pc, 'guard_nonvirtualized', box, + op = self.generate_guard(pc, rop.GUARD_NONVIRTUALIZED, box, [clsbox, guard_field]) if op: op.desc = vdesc @@ -620,7 +621,7 @@ if stop: break - def generate_guard(self, pc, opname, box, extraargs=[], ignore_box=None, + def generate_guard(self, pc, opnum, box, extraargs=[], ignore_box=None, const_if_fail=None): if isinstance(box, Const): # no need for a guard return @@ -637,7 +638,7 @@ liveboxes.append(const_if_fail) if box is not None: extraargs = [box] + extraargs - guard_op = self.metainterp.history.record(opname, extraargs, None) + guard_op = self.metainterp.history.record(opnum, extraargs, None) guard_op.liveboxes = liveboxes saved_pc = self.pc self.pc = pc @@ -648,7 +649,7 @@ def implement_guard_value(self, pc, box): if isinstance(box, Box): promoted_box = box.constbox() - self.generate_guard(pc, 'guard_value', box, [promoted_box]) + self.generate_guard(pc, rop.GUARD_VALUE, box, [promoted_box]) return promoted_box else: return box # no promotion needed, already a Const @@ -662,18 +663,18 @@ self.pc -= 3 self.pc = self.load_3byte() - def execute(self, step, argboxes, result_type, pure=False): - resbox = self.metainterp.history.execute_and_record(step, argboxes, + def execute(self, opnum, argboxes, result_type, pure=False): + resbox = self.metainterp.history.execute_and_record(opnum, argboxes, result_type, pure) if resbox is not None: self.make_result_box(resbox) execute._annspecialcase_ = 'specialize:arg(4)' - def execute_with_exc(self, step, argboxes, result_type, pure=False): + def execute_with_exc(self, opnum, argboxes, result_type, pure=False): old_index = len(self.metainterp.history.operations) try: - self.execute(step, argboxes, result_type, pure) + self.execute(opnum, argboxes, result_type, pure) except Exception, e: if not we_are_translated(): if not isinstance(e, LLException): @@ -690,7 +691,7 @@ else: resultbox = BoxInt() self.make_result_box(resultbox) - self.metainterp.history.record(step, argboxes, resultbox) + self.metainterp.history.record(opnum, argboxes, resultbox) else: if not self.metainterp.history.generate_anything_since(old_index): assert pure @@ -807,8 +808,8 @@ def handle_guard_failure(self, guard_failure): orig_boxes = self.initialize_state_from_guard_failure(guard_failure) try: - if guard_failure.guard_op.opname in ['guard_exception', - 'guard_no_exception']: + if guard_failure.guard_op.opnum in (rop.GUARD_EXCEPTION, + rop.GUARD_NO_EXCEPTION): self.raise_exception_upon_guard_failure(guard_failure) self.interpret() assert False, "should always raise" @@ -839,7 +840,7 @@ if not box1.equals(box2): # not a valid loop raise self.ContinueRunningNormally(live_arg_boxes) - mp = history.ResOperation('merge_point', + mp = history.ResOperation(rop.MERGE_POINT, original_boxes[num_green_args:], None) mp.greenkey = original_boxes[:num_green_args] self.history.operations.insert(0, mp) @@ -852,7 +853,7 @@ def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes): num_green_args = self.num_green_args - mp = history.ResOperation('catch', original_boxes, None) + mp = history.ResOperation(rop.CATCH, original_boxes, None) mp.coming_from = guard_failure.guard_op self.history.operations.insert(0, mp) try: @@ -946,13 +947,13 @@ if etype: exception_box = ConstInt(etype) exc_value_box = BoxPtr(evalue) - op = frame.generate_guard(frame.pc, 'guard_exception', + op = frame.generate_guard(frame.pc, rop.GUARD_EXCEPTION, None, [exception_box]) if op: op.result = exc_value_box return self.finishframe_exception(exception_box, exc_value_box) else: - frame.generate_guard(frame.pc, 'guard_no_exception', None, []) + frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, []) return False def rebuild_state_after_failure(self, key, newboxes): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sun Mar 1 15:19:06 2009 @@ -14,8 +14,9 @@ storage_info = None liveboxes = None - def __init__(self, opname, args, result): - self.opname = opname + def __init__(self, opnum, args, result): + assert isinstance(opnum, int) + self.opnum = opnum self.args = list(args) self.result = result @@ -24,17 +25,143 @@ sres = repr(self.result) + ' = ' else: sres = '' - result = '%s%s(%s)' % (sres, self.opname, + result = '%s%s(%s)' % (sres, self.getopname(), ', '.join(map(repr, self.args))) if self.liveboxes is not None: result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) return result def clone(self): - op = ResOperation(self.opname, self.args, self.result) + op = ResOperation(self.opnum, self.args, self.result) op.specnodes = self.specnodes op.key = self.key return op + def getopname(self): + try: + return opname[self.opnum].lower() + except KeyError: + return '<%d>' % self.opnum + + def is_guard(self): + return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST + + def is_always_pure(self): + return rop._ALWAYS_PURE_FIRST <= self.opnum <= rop._ALWAYS_PURE_LAST + + def has_no_side_effect(self): + return rop._NOSIDEEFFECT_FIRST <= self.opnum <= rop._NOSIDEEFFECT_LAST + + def can_raise(self): + return rop._CANRAISE_FIRST <= self.opnum <= rop._CANRAISE_LAST + # ____________________________________________________________ + +class typ(object): + INT = 0 # a register-sized, non-GC-aware value (int or addr) + PTR = 1 # a pointer to a GC object + VOID = 2 # a void + + INT1 = 3 # when we need more precision about the size of the int, + INT2 = 4 # use these instead of INT + INT4 = 5 # (e.g. for reading or writing fields) + INT8 = 6 + + +class rop(object): + """The possible names of the ResOperations.""" + + MERGE_POINT = 1 + CATCH = 2 + JUMP = 3 + RETURN = 4 + + _GUARD_FIRST = 10 # ----- start of guard operations ----- + GUARD_TRUE = 10 + GUARD_FALSE = 11 + GUARD_VALUE = 12 + GUARD_CLASS = 13 + GUARD_NONVIRTUALIZED = 14 + GUARD_NO_EXCEPTION = 15 + GUARD_EXCEPTION = 16 + _GUARD_LAST = 19 # ----- end of guard operations ----- + + _NOSIDEEFFECT_FIRST = 30 # ----- start of no_side_effect operations ----- + _ALWAYS_PURE_FIRST = 30 # ----- start of always_pure operations ----- + INT_ADD = 30 + INT_SUB = 31 + INT_MUL = 32 + INT_FLOORDIV = 33 + INT_MOD = 34 + INT_LT = 35 + INT_LE = 36 + INT_EQ = 37 + INT_NE = 38 + INT_GT = 39 + INT_GE = 40 + INT_AND = 41 + INT_OR = 42 + INT_XOR = 43 + INT_RSHIFT = 44 + INT_LSHIFT = 45 + UINT_ADD = 46 + UINT_SUB = 47 + UINT_MUL = 48 + UINT_LT = 49 + UINT_LE = 50 + UINT_EQ = 51 + UINT_NE = 52 + UINT_GT = 53 + UINT_GE = 54 + # + INT_IS_TRUE = 60 + INT_NEG = 61 + INT_INVERT = 62 + BOOL_NOT = 63 + # + OONONNULL = 70 + OOISNULL = 71 + OOIS = 72 + OOISNOT = 73 + # + STRLEN = 78 + STRGETITEM = 79 + _ALWAYS_PURE_LAST = 79 # ----- end of always_pure operations ----- + + GETARRAYITEM_GC = 80 + GETFIELD_GC = 81 + GETFIELD_RAW = 82 + _NOSIDEEFFECT_LAST = 89 # ----- end of no_side_effect operations ----- + + NEW = 90 + NEW_WITH_VTABLE = 91 + NEW_ARRAY = 92 + SETARRAYITEM_GC = 93 + SETFIELD_GC = 94 + SETFIELD_RAW = 95 + NEWSTR = 96 + STRSETITEM = 97 + + _CANRAISE_FIRST = 100 # ----- start of can_raise operations ----- + _CALL = 100 + CALL__1 = _CALL + typ.INT1 + CALL__2 = _CALL + typ.INT2 + CALL__4 = _CALL + typ.INT4 + CALL__8 = _CALL + typ.INT8 + CALL_PTR = _CALL + typ.PTR + CALL_VOID = _CALL + typ.VOID + # + INT_ADD_OVF = 110 + INT_SUB_OVF = 111 + INT_MUL_OVF = 112 + INT_NEG_OVF = 113 + _CANRAISE_LAST = 119 # ----- end of can_raise operations ----- + + +opname = {} # mapping numbers to the original names, for debugging +for _key, _value in rop.__dict__.items(): + if type(_value) is int and _key.isupper() and not _key.startswith('_'): + assert _value not in opname, "collision! %s and %s" % ( + opname[_value], _key) + opname[_value] = _key Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sun Mar 1 15:19:06 2009 @@ -1,4 +1,4 @@ - +from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt class SpecNode(object): @@ -127,7 +127,7 @@ for ofs, subspecnode in self.fields: cls = self.known_class.getint() tp = cpu.typefor(ofs) - fieldbox = cpu.execute_operation('getfield_gc', + fieldbox = cpu.execute_operation(rop.GETFIELD_GC, [valuebox, ConstInt(ofs)], tp) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) @@ -153,8 +153,6 @@ class DelayedSpecNode(VirtualizedSpecNode): def expand_boxlist(self, instnode, newboxlist, oplist): - from pypy.jit.metainterp.history import ResOperation, ConstInt - newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) @@ -166,7 +164,7 @@ newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() - oplist.append(ResOperation('getfield_gc', + oplist.append(ResOperation(rop.GETFIELD_GC, [instnode.source, ConstInt(ofs)], box)) newboxlist.append(box) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Sun Mar 1 15:19:06 2009 @@ -4,6 +4,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp.test.test_basic import LLJitMixin from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.metainterp.resoperation import rop class TestLoop(LLJitMixin): specialize = False @@ -311,8 +312,8 @@ assert res == expected loops = get_stats().loops - assert loops[0].operations[0].opname == 'merge_point' - assert loops[1].operations[0].opname == 'catch' + assert loops[0].operations[0].opnum == rop.MERGE_POINT + assert loops[1].operations[0].opnum == rop.CATCH def test_example(self): myjitdriver = JitDriver(greens = ['i'], Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Sun Mar 1 15:19:06 2009 @@ -5,8 +5,10 @@ from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE from pypy.jit.backend.llgraph import runner +from pypy.jit.metainterp import resoperation +from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - ConstAddr, ResOperation) + ConstAddr) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, rebuild_boxes_from_guard_failure, AllocationStorage, @@ -56,7 +58,7 @@ print '%-39s| %s' % (txt1[:39], txt2[:39]) txt1 = txt1[39:] txt2 = txt2[39:] - assert op1.opname == op2.opname + assert op1.opnum == op2.opnum assert len(op1.args) == len(op2.args) for x, y in zip(op1.args, op2.args): assert x == y or y == x # for ANY object :-( @@ -67,6 +69,13 @@ # Box._extended_display = saved return True +def ResOperation(opname, args, result): + if opname == 'escape': + opnum = -123 # random number not in the list + else: + opnum = getattr(rop, opname.upper()) + return resoperation.ResOperation(opnum, args, result) + # ____________________________________________________________ class A: @@ -148,7 +157,7 @@ ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], n2), ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), - ResOperation('some_escaping_operation', [n2], None), # <== escaping + ResOperation('escape', [n2], None), # <== escaping ResOperation('jump', [sum2, n2], None), ] @@ -186,7 +195,7 @@ ConstAddr(node_vtable, cpu)], B.n2), ResOperation('setfield_gc', [B.n2, ConstInt(B.ofs_value), B.v2], None), - ResOperation('some_escaping_operation', [B.n2], None), # <== escaping + ResOperation('escape', [B.n2], None), # <== escaping ResOperation('jump', [B.sum2, B.n2], None), ]) @@ -198,11 +207,11 @@ ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), sizebox], None), - ResOperation('some_escaping_operation', [n1], None), # <== escaping + ResOperation('escape', [n1], None), # <== escaping ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('some_escaping_operation', [n1], None), # <== escaping + ResOperation('escape', [n1], None), # <== escaping ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], n2), ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), @@ -235,11 +244,11 @@ equaloplists(spec.loop.operations, [ ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone - ResOperation('some_escaping_operation', [C.n1], None), # <== escaping + ResOperation('escape', [C.n1], None), # <== escaping ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], C.v), ResOperation('int_sub', [C.v, ConstInt(1)], C.v2), ResOperation('int_add', [C.sum, C.v], C.sum2), - ResOperation('some_escaping_operation', [C.n1], None), # <== escaping + ResOperation('escape', [C.n1], None), # <== escaping ResOperation('new_with_vtable', [ConstInt(C.size_of_node), ConstAddr(node_vtable, cpu)], C.n2), ResOperation('setfield_gc', [C.n2, ConstInt(C.ofs_value), C.v2], @@ -256,7 +265,7 @@ ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu), sizebox], None), # the only difference is different vtable ^^^^^^^^^^^^ - ResOperation('getfield', [n1, ConstInt(ofs_value)], v), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), ResOperation('new_with_vtable', [ConstInt(size_of_node), @@ -303,7 +312,7 @@ ResOperation('jump', [E.sum2, E.v2], None), ]) guard_op = spec.loop.operations[-2] - assert guard_op.opname == 'guard_true' + assert guard_op.getopname() == 'guard_true' assert guard_op.liveboxes == [E.sum2, E.v2] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] @@ -314,8 +323,8 @@ def __init__(self): self.ops = [] - def execute_and_record(self, opname, args, res_type, pure): - self.ops.append((opname, args)) + def execute_and_record(self, opnum, args, res_type, pure): + self.ops.append((opnum, args)) if res_type != 'void': return 'allocated' else: @@ -339,8 +348,8 @@ newboxes = rebuild_boxes_from_guard_failure(guard_op, fake_metainterp, [v_sum_b, v_v_b]) expected = [ - ('new_with_vtable', [E.sizebox, ConstInt(vt)]), - ('setfield_gc', ['allocated', ConstInt(E.ofs_value), v_v_b]) + (rop.NEW_WITH_VTABLE, [E.sizebox, ConstInt(vt)]), + (rop.SETFIELD_GC, ['allocated', ConstInt(E.ofs_value), v_v_b]) ] assert expected == fake_metainterp.history.ops assert newboxes == [v_sum_b, 'allocated'] @@ -412,7 +421,7 @@ ResOperation('merge_point', [n2, n3], None), ResOperation('oois', [n2, n3], vbool1), ResOperation('guard_true', [vbool1], None), - ResOperation('external', [], n4), + ResOperation('escape', [], n4), ResOperation('jump', [n2, n4], None), ] ops[2].liveboxes = [n2] @@ -463,7 +472,7 @@ ResOperation('jump', [G.sum2, ConstInt(124)], None), ]) guard_op = spec.loop.operations[-2] - assert guard_op.opname == 'guard_true' + assert guard_op.getopname() == 'guard_true' assert guard_op.liveboxes == [G.sum2, ConstInt(124)] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] @@ -767,7 +776,7 @@ locals().update(A.__dict__) # :-) ops = [ ResOperation('merge_point', [], None), - ResOperation('produce_somehow_n1', [], n1), + ResOperation('escape', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), sizebox], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), @@ -784,7 +793,7 @@ spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), - ResOperation('produce_somehow_n1', [], O1.n1), + ResOperation('escape', [], O1.n1), # only the first guard_class is left ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu), O1.sizebox], None), @@ -798,7 +807,7 @@ v1 = BoxInt(1) ops = [ ResOperation('merge_point', [], None), - ResOperation('produce_somehow_n1', [], n1), + ResOperation('escape', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), sizebox], None), ResOperation('oononnull', [n1], v1), @@ -815,7 +824,7 @@ spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), - ResOperation('produce_somehow_n1', [], O2.n1), + ResOperation('escape', [], O2.n1), ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu), O2.sizebox], None), # the oononnull and guard_true are gone, because we know they @@ -830,7 +839,7 @@ v1 = BoxInt(1) ops = [ ResOperation('merge_point', [], None), - ResOperation('produce_somehow_n1', [], n1), + ResOperation('escape', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), sizebox], None), ResOperation('oois', [n1, ConstPtr(lltype.nullptr(llmemory.GCREF.TO))], @@ -848,7 +857,7 @@ spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), - ResOperation('produce_somehow_n1', [], O3.n1), + ResOperation('escape', [], O3.n1), ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu), O3.sizebox], None), # the oois and guard_false are gone, because we know they Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sun Mar 1 15:19:06 2009 @@ -5,15 +5,15 @@ from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp import heaptracker -from pypy.jit.metainterp.history import (ResOperation, - ConstInt, ConstAddr, BoxInt, BoxPtr) +from pypy.jit.metainterp.history import ConstInt, ConstAddr, BoxInt, BoxPtr from pypy.jit.metainterp.optimize import (PerfectSpecializer, VirtualizableSpecNode, VirtualInstanceSpecNode, NotSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, - equaloplists, Loop) + equaloplists, Loop, + ResOperation) #from pypy.jit.metainterp.codewriter import ListDescr # ____________________________________________________________ From fijal at codespeak.net Sun Mar 1 15:22:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 15:22:14 +0100 (CET) Subject: [pypy-svn] r62296 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090301142214.430A1168553@codespeak.net> Author: fijal Date: Sun Mar 1 15:22:13 2009 New Revision: 62296 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: fix translation Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sun Mar 1 15:22:13 2009 @@ -131,9 +131,11 @@ def crash_in_jit(e): print "Crash in JIT!" - print '%s: %s' % (e.__class__, e) if not we_are_translated(): + print '%s: %s' % (e.__class__, e) import sys, pdb; pdb.post_mortem(sys.exc_info()[2]) + else: + print e raise AssertionError("crash in JIT") crash_in_jit._dont_inline_ = True From fijal at codespeak.net Sun Mar 1 15:23:37 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 15:23:37 +0100 (CET) Subject: [pypy-svn] r62297 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090301142337.8516B16855D@codespeak.net> Author: fijal Date: Sun Mar 1 15:23:36 2009 New Revision: 62297 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py Log: Progress with x86 backend. Support more or less all operations by now Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sun Mar 1 15:23:36 2009 @@ -182,6 +182,14 @@ getattr(self.mc, asmop)(arglocs[0], arglocs[1]) return genop_binary + def _binaryop_ovf(asmop, can_swap=False): + def genop_binary_ovf(self, op, arglocs, result_loc): + getattr(self.mc, asmop)(arglocs[0], arglocs[1]) + # XXX think about CMOV instead of SETO, this would avoid + # a mess in detecting an exception + self.mc.SETO(heap8(self._exception_addr)) + return genop_binary_ovf + def _cmpop(cond, rev_cond): def genop_cmp(self, op, arglocs, result_loc): if isinstance(op.args[0], Const): @@ -208,6 +216,15 @@ genop_int_mul = _binaryop("IMUL", True) genop_int_and = _binaryop("AND", True) + genop_uint_add = genop_int_add + genop_uint_sub = genop_int_sub + genop_uint_mul = genop_int_mul + genop_uint_and = genop_int_and + + genop_int_mul_ovf = _binaryop_ovf("IMUL", True) + genop_int_sub_ovf = _binaryop_ovf("SUB") + genop_int_add_ovf = _binaryop_ovf("ADD") + genop_int_lt = _cmpop("L", "G") genop_int_le = _cmpop("LE", "GE") genop_int_eq = _cmpop("E", "NE") @@ -215,6 +232,11 @@ genop_int_gt = _cmpop("G", "L") genop_int_ge = _cmpop("GE", "LE") + genop_uint_gt = _cmpop("A", "B") + genop_uint_lt = _cmpop("B", "A") + genop_uint_le = _cmpop("BE", "AE") + genop_uint_ge = _cmpop("AE", "BE") + # for now all chars are being considered ints, although we should make # a difference at some point genop_char_eq = genop_int_eq Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Sun Mar 1 15:23:36 2009 @@ -500,6 +500,13 @@ consider_guard_true = consider_guard consider_guard_false = consider_guard + def consider_guard_nonvirtualized(self, op): + # XXX implement it + locs = self._locs_from_liveboxes(op) + self.eventually_free_var(op.args[0]) + self.eventually_free_vars(op.liveboxes) + return [] + def consider_guard_no_exception(self, op): box = TempBox() loc, ops = self.force_allocate_reg(box, []) @@ -585,11 +592,18 @@ consider_int_mul = consider_binop consider_int_sub = consider_binop consider_int_and = consider_binop - + consider_uint_add = consider_binop + consider_uint_mul = consider_binop + consider_uint_sub = consider_binop + consider_uint_and = consider_binop + def consider_binop_ovf(self, op): - xxx + return self.consider_binop(op) consider_int_mul_ovf = consider_binop_ovf + consider_int_sub_ovf = consider_binop_ovf + consider_int_add_ovf = consider_binop_ovf + # XXX ovf_neg op def consider_int_neg(self, op): res, ops = self.force_result_in_reg(op.results[0], op.args[0], []) @@ -648,6 +662,7 @@ consider_char_eq = consider_compop consider_int_ne = consider_compop consider_int_eq = consider_compop + consider_uint_gt = consider_compop def sync_var(self, v): ops = [] @@ -745,7 +760,7 @@ def _unpack_fielddescr(self, fielddescr): if fielddescr < 0: - fielddescr = -fielddescr + fielddescr = ~fielddescr ofs_loc = imm(fielddescr & 0xffff) size_loc = imm(fielddescr >> 16) return ofs_loc, size_loc Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 1 15:23:36 2009 @@ -27,7 +27,6 @@ self.stats = stats self.translate_support_code = translate_support_code if translate_support_code: - assert False, "need exception support" self.mixlevelann = MixLevelHelperAnnotator(rtyper) else: self.current_interpreter = LLInterpreter(self.rtyper) @@ -50,6 +49,16 @@ self.caught_exception = None if rtyper is not None: # for tests self.lltype2vtable = rtyper.lltype_to_vtable_mapping() + self._setup_ovf_error() + + def _setup_ovf_error(self): + bk = self.rtyper.annotator.bookkeeper + clsdef = bk.getuniqueclassdef(OverflowError) + ovferror_repr = rclass.getclassrepr(self.rtyper, clsdef) + ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance( + self.rtyper, clsdef) + self._ovf_error_vtable = self.cast_ptr_to_int(ll_inst.typeptr) + self._ovf_error_inst = self.cast_ptr_to_int(ll_inst) def setup(self): self.assembler = Assembler386(self) @@ -112,9 +121,17 @@ def set_meta_interp(self, metainterp): self.metainterp = metainterp + def _get_overflow_error(self): + self.assembler._exception_data[1] = self._ovf_error_inst + return self._ovf_error_vtable + def get_exception(self, frame): res = self.assembler._exception_data[0] self.assembler._exception_data[0] = 0 + if res == 1: + # it's an overflow error, but we need to do all the dance + # to get a correct exception + return self._get_overflow_error() return res def get_exc_value(self, frame): @@ -137,9 +154,9 @@ if self.assembler._exception_data[0] != 0: TP = lltype.Ptr(rclass.OBJECT_VTABLE) TP_V = lltype.Ptr(rclass.OBJECT) - exc_t_a = self.cast_int_to_adr(self.assembler._exception_data[0]) + exc_t_a = self.cast_int_to_adr(self.get_exception(None)) exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) - exc_v_a = self.cast_int_to_gcref(self.assembler._exception_data[1]) + exc_v_a = self.get_exc_value(None) exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) # clean up the exception self.assembler._exception_data[0] = 0 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Sun Mar 1 15:23:36 2009 @@ -2,6 +2,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import we_are_translated +from pypy.translator.c.test.test_genc import compile import ctypes GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) @@ -27,3 +28,20 @@ else: GC_malloc = boehmlib.GC_malloc return cast(GC_malloc, c_void_p).value + +def c_meta_interp(function, args, **kwds): + from pypy.translator.translator import TranslationContext + from pypy.jit.metainterp.warmspot import WarmRunnerDesc + from pypy.jit.backend.x86.runner import CPU386 + + t = TranslationContext() + t.config.translation.gc = 'boehm' + t.buildannotator().build_types(function, [int] * len(args)) + t.buildrtyper().specialize() + warmrunnerdesc = WarmRunnerDesc(t, translate_support_code=True, + CPUClass=CPU386, + **kwds) + warmrunnerdesc.state.set_param_threshold(3) # for tests + warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests + warmrunnerdesc.finish() + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Sun Mar 1 15:23:36 2009 @@ -7,6 +7,7 @@ from pypy.jit.backend.x86.regalloc import WORD from pypy.jit.backend.x86 import symbolic import ctypes +import sys class FakeStats(object): pass @@ -334,4 +335,31 @@ assert c.value == 3 def test_ovf_ops(self): - xxx + arg0 = BoxInt(12) + arg1 = BoxInt(13) + res = self.execute_operation('int_mul_ovf', [arg0, arg1], 'int') + assert res.value == 12*13 + arg0 = BoxInt(sys.maxint/2) + arg1 = BoxInt(2222) + self.execute_operation('int_mul_ovf', [arg0, arg1], 'int') + assert self.cpu.assembler._exception_data[0] == 1 + self.cpu.assembler._exception_data[0] = 0 + + def test_uint_ops(self): + from pypy.rlib.rarithmetic import r_uint, intmask + + arg0 = BoxInt(intmask(r_uint(sys.maxint + 3))) + arg1 = BoxInt(intmask(r_uint(4))) + res = self.execute_operation('uint_add', [arg0, arg1], 'int') + assert res.value == intmask(r_uint(sys.maxint + 3) + r_uint(4)) + + arg0 = BoxInt(intmask(sys.maxint + 10)) + arg1 = BoxInt(10) + res = self.execute_operation('uint_mul', [arg0, arg1], 'int') + assert res.value == intmask((sys.maxint + 10) * 10) + + arg0 = BoxInt(intmask(r_uint(sys.maxint + 3))) + arg1 = BoxInt(intmask(r_uint(4))) + + res = self.execute_operation('uint_gt', [arg0, arg1], 'int') + assert res.value == 1 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Sun Mar 1 15:23:36 2009 @@ -59,7 +59,8 @@ def test_methods_of_cpu(): cpu = CPU386(rtyper=None, stats=FakeStats()) assert cpu.sizeof(S) == get_size(S) - assert cpu.offsetof(S, 'y') == get_field_token(S, 'y')[0] + assert cpu.fielddescrof(S, 'y') & 0xffff == get_field_token(S, 'y')[0] + assert cpu.fielddescrof(S, 'y') >> 16 == get_field_token(S, 'y')[1] A = lltype.GcArray(lltype.Char) assert cpu.itemoffsetof(A) == get_array_token(A)[0] assert cpu.arraylengthoffset(A) == get_array_token(A)[2] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py Sun Mar 1 15:23:36 2009 @@ -1,73 +1,12 @@ import py -from codegen386.runner import CPU386 -from test.test_zrpy_basic import LLInterpJitMixin -from pypy.jit.hintannotator.policy import StopAtXPolicy -from test.test_slist import ListTests -from pypy.rpython.lltypesystem import lltype -from pyjitpl import build_meta_interp -from rpyjitpl import set_ll_helper -from pypy.translator.c.genc import CStandaloneBuilder as CBuilder -from pypy.annotation.listdef import s_list_of_strings -from pypy.annotation import model as annmodel -from history import log +from pypy.jit.metainterp.test.test_slist import ListTests +from pypy.jit.backend.x86.support import c_meta_interp -_cache = (None,) - -def rpython_ll_meta_interp(function, args, loops=None, **kwds): - global _cache - key = (function, tuple([lltype.typeOf(arg) for arg in args])) - lgt = len(args) - - src = py.code.Source(""" - def entry_point(argv): - args = (%s,) - res, num_loops = boot1(*args) - print "%%d,%%d" %% (res, num_loops) - return 0 - """ % (", ".join(['int(argv[%d])' % (i + 1) for i in range(lgt)]),)) - - if key != _cache[0]: - _cache = (None,) - type_system = 'lltype' - kwds['translate_support_code'] = True - metainterp = build_meta_interp(function, args, type_system, **kwds) - boot_graph = set_ll_helper(metainterp, - [lltype.typeOf(arg) for arg in args]) - boot1 = boot_graph.func - exec src.compile() in locals() - mixlevelann = metainterp.cpu.mixlevelann - entry_point_graph = mixlevelann.getgraph(entry_point, - [s_list_of_strings], - annmodel.SomeInteger()) - metainterp.cpu.mixlevelann.finish() - del metainterp.cpu.mixlevelann - _cache = (key, metainterp, boot_graph) - - metainterp = _cache[1] - boot_graph = _cache[2] - t = metainterp.cpu.rtyper.annotator.translator - t.config.translation.gc = 'boehm' - cbuilder = CBuilder(t, entry_point, config=t.config) - cbuilder.generate_source() - exe_name = cbuilder.compile() - log('---------- Test starting ----------') - stdout = cbuilder.cmdexec(" ".join([str(arg) for arg in args])) - stdout.split(',') - res_s, loops_s = stdout.split(',') - res = int(res_s) - actual_loops = int(loops_s) - log('---------- Test done ----------') - if loops is not None: - actual_loops = results.item1 - assert actual_loops == loops - return res - - -class Jit386Mixin(LLInterpJitMixin): +class Jit386Mixin(object): @staticmethod def meta_interp(fn, args, **kwds): - return rpython_ll_meta_interp(fn, args, CPUClass=CPU386, **kwds) + return c_meta_interp(fn, args, **kwds) class TestSList(Jit386Mixin, ListTests): # for the individual tests see From fijal at codespeak.net Sun Mar 1 15:48:05 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 15:48:05 +0100 (CET) Subject: [pypy-svn] r62298 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090301144805.5D4C41684C5@codespeak.net> Author: fijal Date: Sun Mar 1 15:48:04 2009 New Revision: 62298 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: Fix at least imports. More progress needed before we can run any test though (IN-PROGRESS), away to check my luggage in Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sun Mar 1 15:48:04 2009 @@ -1,7 +1,7 @@ import sys import ctypes from pypy.jit.backend.x86 import symbolic -from pypy.jit.metainterp.history import Const, ConstInt, Box, MergePoint +from pypy.jit.metainterp.history import Const, ConstInt, Box from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr from pypy.rpython.lltypesystem.rclass import OBJECT from pypy.annotation import model as annmodel Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Sun Mar 1 15:48:04 2009 @@ -3,13 +3,13 @@ """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, - ResOperation, MergePoint, ConstAddr) + ResOperation, ConstAddr) from pypy.jit.backend.x86.ri386 import * from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.jit.backend.x86 import symbolic -from pypy.jit.metainterp.heaptracker import operations_without_side_effects +from pypy.jit.metainterp.resoperation import rop, opname # esi edi and ebp can be added to this list, provided they're correctly # saved and restored @@ -126,7 +126,7 @@ self.stack_bindings[arg] = stack_pos(stackpos) rev_stack_binds[stackpos] = arg j += 1 - if jump.opname != 'jump': + if jump.opnum != rop.JUMP: return {}, sd for i in range(len(jump.args)): argloc = jump.jump_target.arglocs[i] @@ -150,7 +150,7 @@ def _compute_loop_consts(self, mp, jump): self.jump_reg_candidates = {} - if jump.opname != 'jump': + if jump.opnum != rop.JUMP: loop_consts = {} else: assert jump.jump_target is mp @@ -198,21 +198,14 @@ self.loop_consts = loop_consts for i in range(len(operations)): op = operations[i] - if op.opname.startswith('#'): - continue self.position = i - canfold = True - if op.opname in operations_without_side_effects: - for result in op.results: - if result in self.longevity: - # means it's never used - canfold = False - break + if op.has_no_side_effect() and op.result not in self.longevity: + canfold = True else: canfold = False if not canfold: - new_ops += opdict[op.opname](self, op) - self.eventually_free_vars(op.results) + new_ops += oplist[op.opnum](self, op) + self.eventually_free_var(op.result) self._check_invariants() return new_ops @@ -225,12 +218,12 @@ start_live[v] = 0 for i in range(len(operations)): op = operations[i] - if op.results: - start_live[op.results[0]] = i + if op.result is not None: + start_live[op.result] = i for arg in op.args: if isinstance(arg, Box): longevity[arg] = (start_live[arg], i) - if op.opname.startswith('guard_'): + if op.is_guard(): for arg in op.liveboxes: if isinstance(arg, Box): longevity[arg] = (start_live[arg], i) @@ -490,15 +483,15 @@ self.eventually_free_vars(op.args) return [PerformDiscard(op, [])] - def consider_guard(self, op): + def _consider_guard(self, op): loc, ops = self.make_sure_var_in_reg(op.args[0], []) locs = self._locs_from_liveboxes(op) self.eventually_free_var(op.args[0]) self.eventually_free_vars(op.liveboxes) return ops + [PerformDiscard(op, [loc] + locs)] - consider_guard_true = consider_guard - consider_guard_false = consider_guard + consider_guard_true = _consider_guard + consider_guard_false = _consider_guard def consider_guard_nonvirtualized(self, op): # XXX implement it @@ -519,9 +512,9 @@ loc, ops = self.make_sure_var_in_reg(op.args[0], []) box = TempBox() loc1, ops1 = self.force_allocate_reg(box, op.args) - if op.results[0] in self.longevity: + if op.result in self.longevity: # this means, is it ever used - resloc, ops2 = self.force_allocate_reg(op.results[0], + resloc, ops2 = self.force_allocate_reg(op.result, op.args + [box]) else: resloc, ops2 = None, [] @@ -573,40 +566,40 @@ arglocs = [] return [PerformDiscard(op, arglocs)] - def consider_binop(self, op): + def _consider_binop(self, op): x = op.args[0] ops = [] if isinstance(x, Const): - res, ops = self.force_allocate_reg(op.results[0], []) + res, ops = self.force_allocate_reg(op.result, []) argloc = self.loc(op.args[1]) self.eventually_free_var(op.args[1]) load_op = Load(x, self.loc(x), res) return ops + [load_op, Perform(op, [res, argloc], res)] - loc, ops = self.force_result_in_reg(op.results[0], x, op.args) + loc, ops = self.force_result_in_reg(op.result, x, op.args) argloc = self.loc(op.args[1]) self.eventually_free_var(op.args[1]) return ops + [Perform(op, [loc, argloc], loc)] # otherwise load this variable to some register - consider_int_add = consider_binop - consider_int_mul = consider_binop - consider_int_sub = consider_binop - consider_int_and = consider_binop - consider_uint_add = consider_binop - consider_uint_mul = consider_binop - consider_uint_sub = consider_binop - consider_uint_and = consider_binop + consider_int_add = _consider_binop + consider_int_mul = _consider_binop + consider_int_sub = _consider_binop + consider_int_and = _consider_binop + consider_uint_add = _consider_binop + consider_uint_mul = _consider_binop + consider_uint_sub = _consider_binop + #consider_uint_and = _consider_binop - def consider_binop_ovf(self, op): - return self.consider_binop(op) + def _consider_binop_ovf(self, op): + return self._consider_binop(op) - consider_int_mul_ovf = consider_binop_ovf - consider_int_sub_ovf = consider_binop_ovf - consider_int_add_ovf = consider_binop_ovf + consider_int_mul_ovf = _consider_binop_ovf + consider_int_sub_ovf = _consider_binop_ovf + consider_int_add_ovf = _consider_binop_ovf # XXX ovf_neg op def consider_int_neg(self, op): - res, ops = self.force_result_in_reg(op.results[0], op.args[0], []) + res, ops = self.force_result_in_reg(op.result, op.args[0], []) return ops + [Perform(op, [res], res)] consider_bool_not = consider_int_neg @@ -615,7 +608,7 @@ tmpvar = TempBox() reg, ops = self.force_allocate_reg(tmpvar, [], ecx) y = self.loc(op.args[1]) - x, more_ops = self.force_result_in_reg(op.results[0], op.args[0], + x, more_ops = self.force_result_in_reg(op.result, op.args[0], op.args + [tmpvar]) self.eventually_free_vars(op.args + [tmpvar]) return ops + more_ops + [Perform(op, [x, y, reg], x)] @@ -623,7 +616,7 @@ def consider_int_mod(self, op): l0, ops0 = self.make_sure_var_in_reg(op.args[0], [], eax) l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) - l2, ops2 = self.force_allocate_reg(op.results[0], [], edx) + l2, ops2 = self.force_allocate_reg(op.result, [], edx) # eax is trashed after that operation tmpvar = TempBox() _, ops3 = self.force_allocate_reg(tmpvar, [], eax) @@ -633,7 +626,7 @@ def consider_int_floordiv(self, op): tmpvar = TempBox() - l0, ops0 = self.force_result_in_reg(op.results[0], op.args[0], [], eax) + l0, ops0 = self.force_result_in_reg(op.result, op.args[0], [], eax) l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) # we need to make sure edx is empty, since we're going to use it l2, ops2 = self.force_allocate_reg(tmpvar, [], edx) @@ -641,7 +634,7 @@ self.eventually_free_vars(op.args + [tmpvar]) return ops0 + ops1 + ops2 + [Perform(op, [eax, ecx], eax)] - def consider_compop(self, op): + def _consider_compop(self, op): vx = op.args[0] vy = op.args[1] arglocs = [self.loc(vx), self.loc(vy)] @@ -652,17 +645,17 @@ arglocs[0], ops0 = self.force_allocate_reg(vx, []) self.eventually_free_var(vx) self.eventually_free_var(vy) - loc, ops = self.force_allocate_reg(op.results[0], op.args) + loc, ops = self.force_allocate_reg(op.result, op.args) return ops0 + ops + [Perform(op, arglocs, loc)] - consider_int_lt = consider_compop - consider_int_gt = consider_compop - consider_int_ge = consider_compop - consider_int_le = consider_compop - consider_char_eq = consider_compop - consider_int_ne = consider_compop - consider_int_eq = consider_compop - consider_uint_gt = consider_compop + consider_int_lt = _consider_compop + consider_int_gt = _consider_compop + consider_int_ge = _consider_compop + consider_int_le = _consider_compop + xxx_consider_char_eq = _consider_compop + consider_int_ne = _consider_compop + consider_int_eq = _consider_compop + consider_uint_gt = _consider_compop def sync_var(self, v): ops = [] @@ -688,8 +681,8 @@ if self.longevity[v][1] > self.position or v in force_store: ops += self.sync_var(v) self.reg_bindings = newcheckdict() - if op.results: - self.reg_bindings = {op.results[0]: eax} + if op.result is not None: + self.reg_bindings = {op.result: eax} self.free_regs = [reg for reg in REGS if reg is not eax] return ops + [Perform(op, arglocs, eax)] else: @@ -716,7 +709,7 @@ ofs_items = symbolic.get_field_token(rstr.STR.chars, 'items')[0] ofs_length = symbolic.get_field_token(rstr.STR.chars, 'length')[0] return self._malloc_varsize(ofs, ofs_items, ofs_length, 0, op.args[0], - op.results[0]) + op.result) def _malloc_varsize(self, ofs, ofs_items, ofs_length, size, v, res_v): if isinstance(v, Box): @@ -749,12 +742,12 @@ size_of_field = arraydescr >> 16 ofs = arraydescr & 0xffff return self._malloc_varsize(0, ofs, 0, size_of_field, op.args[1], - op.results[0]) + op.result) def consider_oononnull(self, op): argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) - reg = self.try_allocate_reg(op.results[0]) + reg = self.try_allocate_reg(op.result) assert reg return [Perform(op, [argloc], reg)] @@ -800,7 +793,7 @@ ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) - result_loc, more_ops = self.force_allocate_reg(op.results[0], []) + result_loc, more_ops = self.force_allocate_reg(op.result, []) return (ops0 + more_ops + [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) @@ -814,7 +807,7 @@ base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[2], args) self.eventually_free_vars(op.args) - result_loc, more_ops = self.force_allocate_reg(op.results[0], []) + result_loc, more_ops = self.force_allocate_reg(op.result, []) return (ops0 + ops1 + more_ops + [Perform(op, [base_loc, ofs_loc, imm(scale), imm(ofs)], result_loc)]) @@ -825,65 +818,61 @@ def _consider_listop(self, op): return self._call(op, [self.loc(arg) for arg in op.args]) - consider_getitem = _consider_listop - consider_len = _consider_listop - consider_append = _consider_listop - consider_pop = _consider_listop - consider_setitem = _consider_listop - consider_newlist = _consider_listop - consider_insert = _consider_listop - consider_listnonzero = _consider_listop + xxx_consider_getitem = _consider_listop + xxx_consider_len = _consider_listop + xxx_consider_append = _consider_listop + xxx_consider_pop = _consider_listop + xxx_consider_setitem = _consider_listop + xxx_consider_newlist = _consider_listop + xxx_consider_insert = _consider_listop + xxx_consider_listnonzero = _consider_listop + +# def consider_same_as(self, op): +# x = op.args[0] +# if isinstance(x, Const): +# pos = self.allocate_new_loc(op.result) +# return [Load(op.result, self.loc(x), pos)] +# if self.longevity[x][1] > self.position or x not in self.reg_bindings: +# if x in self.reg_bindings: +# res = self.allocate_new_loc(op.result) +# return [Load(op.result, self.loc(x), res)] +# else: +# res, ops = self.force_allocate_reg(op.result, op.args) +# return ops + [Load(op.result, self.loc(x), res)] +# else: +# self.reallocate_from_to(x, op.result) +# return [] - def consider_zero_gc_pointers_inside(self, op): - self.eventually_free_var(op.args[0]) - return [] - - def consider_same_as(self, op): - x = op.args[0] - if isinstance(x, Const): - pos = self.allocate_new_loc(op.results[0]) - return [Load(op.results[0], self.loc(x), pos)] - if self.longevity[x][1] > self.position or x not in self.reg_bindings: - if x in self.reg_bindings: - res = self.allocate_new_loc(op.results[0]) - return [Load(op.results[0], self.loc(x), res)] - else: - res, ops = self.force_allocate_reg(op.results[0], op.args) - return ops + [Load(op.results[0], self.loc(x), res)] - else: - self.reallocate_from_to(x, op.results[0]) - return [] - - consider_cast_int_to_char = consider_same_as - consider_cast_int_to_ptr = consider_same_as +# consider_cast_int_to_char = consider_same_as +# xxx_consider_cast_int_to_ptr = consider_same_as def consider_int_is_true(self, op): argloc, ops = self.force_allocate_reg(op.args[0], []) self.eventually_free_var(op.args[0]) - resloc, more_ops = self.force_allocate_reg(op.results[0], []) + resloc, more_ops = self.force_allocate_reg(op.result, []) return ops + more_ops + [Perform(op, [argloc], resloc)] - def consider_nullity(self, op): + def _consider_nullity(self, op): # doesn't need a register in arg argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) - resloc, ops = self.force_allocate_reg(op.results[0], []) + resloc, ops = self.force_allocate_reg(op.result, []) return ops + [Perform(op, [argloc], resloc)] - consider_ooisnull = consider_nullity - consider_oononnull = consider_nullity + consider_ooisnull = _consider_nullity + consider_oononnull = _consider_nullity def consider_strlen(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_var(op.args[0]) - result_loc, more_ops = self.force_allocate_reg(op.results[0], []) + result_loc, more_ops = self.force_allocate_reg(op.result, []) return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] def consider_strgetitem(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) - result_loc, more_ops = self.force_allocate_reg(op.results[0], []) + result_loc, more_ops = self.force_allocate_reg(op.result, []) return (ops0 + ops1 + more_ops + [Perform(op, [base_loc, ofs_loc], result_loc)]) @@ -933,17 +922,13 @@ self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] - def consider_debug_assert(self, op): - # ignore - self.eventually_free_var(op.args[0]) - return [] - -opdict = {} +oplist = [None] * rop._CANRAISE_LAST for name, value in RegAlloc.__dict__.iteritems(): if name.startswith('consider_'): - opname = name[len('consider_'):] - opdict[opname] = value + name = name[len('consider_'):] + num = getattr(rop, name.upper()) + oplist[num] = value def arg_pos(i): res = mem(esp, FRAMESIZE + WORD * (i + 1)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 1 15:48:04 2009 @@ -10,7 +10,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import rclass from pypy.jit.metainterp import history -from pypy.jit.metainterp.history import (MergePoint, ResOperation, Box, Const, +from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) from pypy.jit.backend.x86.assembler import Assembler386 from pypy.jit.backend.x86 import symbolic Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Sun Mar 1 15:48:04 2009 @@ -1,11 +1,12 @@ import py from pypy.rpython.lltypesystem import lltype, llmemory, rffi -from pypy.jit.metainterp.history import ResOperation, MergePoint, Jump +from pypy.jit.metainterp.history import ResOperation from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - GuardOp, Box) + Box) from pypy.jit.backend.x86.runner import CPU, GuardFailed from pypy.jit.backend.x86.regalloc import WORD from pypy.jit.backend.x86 import symbolic +from pypy.jit.metainterp.resoperation import rop import ctypes import sys @@ -47,27 +48,27 @@ result_type) return res - def get_compiled_single_operation(self, opname, result_type, valueboxes): + def get_compiled_single_operation(self, opnum, result_type, valueboxes): livevarlist = [] for box in valueboxes: if isinstance(box, Box): box = box.clonebox() livevarlist.append(box) - mp = MergePoint('merge_point', + mp = ResOperation(rop.MERGE_POINT, [box for box in livevarlist if isinstance(box, Box)], - []) + None) if result_type == 'void': - results = [] + result = None elif result_type == 'int': - results = [BoxInt()] + result = BoxInt() elif result_type == 'ptr': - results = [BoxPtr()] + result = BoxPtr() else: raise ValueError(result_type) operations = [mp, - ResOperation(opname, livevarlist, results), - ResOperation('return', results, [])] - if opname.startswith('guard_'): + ResOperation(opnum, livevarlist, result), + ResOperation(rop.RETURN, [result], None)] + if operations[1].is_guard(): operations[1].liveboxes = [] self.cpu.compile_operations(operations, verbose=False) return mp @@ -75,10 +76,10 @@ def test_int_binary_ops(self): for op, args, res in [ - ('int_sub', [BoxInt(42), BoxInt(40)], 2), - ('int_sub', [BoxInt(42), ConstInt(40)], 2), - ('int_sub', [ConstInt(42), BoxInt(40)], 2), - ('int_add', [ConstInt(-3), ConstInt(-5)], -8), + (rop.INT_SUB, [BoxInt(42), BoxInt(40)], 2), + (rop.INT_SUB, [BoxInt(42), ConstInt(40)], 2), + (rop.INT_SUB, [ConstInt(42), BoxInt(40)], 2), + (rop.INT_ADD, [ConstInt(-3), ConstInt(-5)], -8), ]: assert self.execute_operation(op, args, 'int').value == res @@ -119,12 +120,12 @@ t = BoxInt(455) u = BoxInt(0) # False operations = [ - MergePoint('merge_point', [x, y], []), - ResOperation('int_add', [x, y], [z]), - ResOperation('int_sub', [y, ConstInt(1)], [t]), + ResOperation(rop.MERGE_POINT, [x, y], []), + ResOperation(rop.INT_ADD, [x, y], [z]), + ResOperation(rop.INT_SUB, [y, ConstInt(1)], [t]), ResOperation('int_eq', [t, ConstInt(0)], [u]), - GuardOp('guard_false', [u], []), - Jump('jump', [z, t], []), + ResOperation('guard_false', [u], []), + ResOperation('jump', [z, t], []), ] startmp = operations[0] operations[-1].jump_target = startmp From fijal at codespeak.net Sun Mar 1 16:33:44 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 16:33:44 +0100 (CET) Subject: [pypy-svn] r62299 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090301153344.EA6C616853A@codespeak.net> Author: fijal Date: Sun Mar 1 16:33:42 2009 New Revision: 62299 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: progress, be able to run some tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sun Mar 1 16:33:42 2009 @@ -7,11 +7,13 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, - arg_pos, lower_byte, stack_pos, Perform) + arg_pos, lower_byte, stack_pos, Perform, + MALLOC_VARSIZE) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.support import gc_malloc_fnaddr from pypy.jit.backend.x86.ri386 import * +from pypy.jit.metainterp.resoperation import rop # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on stack @@ -164,10 +166,10 @@ def regalloc_perform(self, op): assert isinstance(op, Perform) resloc = op.result_loc - genop_dict[op.op.opname](self, op.op, op.arglocs, resloc) + genop_list[op.op.opnum](self, op.op, op.arglocs, resloc) def regalloc_perform_discard(self, op): - genop_discard_dict[op.op.opname](self, op.op, op.arglocs) + genop_discard_list[op.op.opnum](self, op.op, op.arglocs) def regalloc_store_to_arg(self, op): self.mc.MOV(arg_pos(op.pos), op.from_loc) @@ -219,7 +221,7 @@ genop_uint_add = genop_int_add genop_uint_sub = genop_int_sub genop_uint_mul = genop_int_mul - genop_uint_and = genop_int_and + xxx_genop_uint_and = genop_int_and genop_int_mul_ovf = _binaryop_ovf("IMUL", True) genop_int_sub_ovf = _binaryop_ovf("SUB") @@ -239,7 +241,7 @@ # for now all chars are being considered ints, although we should make # a difference at some point - genop_char_eq = genop_int_eq + xxx_genop_char_eq = genop_int_eq def genop_bool_not(self, op, arglocs, resloc): self.mc.XOR(arglocs[0], imm8(1)) @@ -300,12 +302,12 @@ # xxx ignore NULL returns for now self.mc.POP(mem(eax, 0)) - def genop_new(self, op, arglocs, result_loc): - assert result_loc is eax + def genop_malloc_varsize(self, op, arglocs, result_loc): loc_size = arglocs[0] self.call(self.malloc_func_addr, [loc_size], eax) - def genop_malloc_varsize(self, op, arglocs, result_loc): + def genop_new(self, op, arglocs, result_loc): + assert result_loc is eax loc_size = arglocs[0] self.call(self.malloc_func_addr, [loc_size], eax) @@ -377,7 +379,6 @@ def genop_jump(self, op, locs): targetmp = op.jump_target - assert isinstance(targetmp, MergePoint) self.mc.JMP(rel32(targetmp.position)) def genop_guard_true(self, op, locs): @@ -406,38 +407,6 @@ self.mc.TEST(loc, loc) self.implement_guard(op, self.mc.JNZ, locs[1:]) - genop_guard_nonzero = genop_guard_true - genop_guard_iszero = genop_guard_false - genop_guard_nonnull = genop_guard_true - genop_guard_isnull = genop_guard_false - - def genop_guard_lt(self, op, locs): - self.mc.CMP(locs[0], locs[1]) - self.implement_guard(op, self.mc.JGE, locs[2:]) - - def genop_guard_le(self, op, locs): - self.mc.CMP(locs[0], locs[1]) - self.implement_guard(op, self.mc.JG, locs[2:]) - - def genop_guard_eq(self, op, locs): - self.mc.CMP(locs[0], locs[1]) - self.implement_guard(op, self.mc.JNE, locs[2:]) - - def genop_guard_ne(self, op, locs): - self.mc.CMP(locs[0], locs[1]) - self.implement_guard(op, self.mc.JE, locs[2:]) - - def genop_guard_gt(self, op, locs): - self.mc.CMP(locs[0], locs[1]) - self.implement_guard(op, self.mc.JLE, locs[2:]) - - def genop_guard_ge(self, op, locs): - self.mc.CMP(locs[0], locs[1]) - self.implement_guard(op, self.mc.JL, locs[2:]) - - genop_guard_is = genop_guard_eq - genop_guard_isnot = genop_guard_ne - def genop_guard_value(self, op, locs): arg0 = locs[0] arg1 = locs[1] @@ -449,9 +418,6 @@ self.mc.CMP(mem(locs[0], offset), locs[1]) self.implement_guard(op, self.mc.JNE, locs[2:]) - def genop_guard_pause(self, op, locs): - self.implement_guard(op, self.mc.JMP, locs) - #def genop_guard_nonvirtualized(self, op): # STRUCT = op.args[0].concretetype.TO # offset, size = symbolic.get_field_token(STRUCT, 'vable_rti') @@ -508,11 +474,11 @@ genop_call__4 = _new_gen_call() gen_call = _new_gen_call() genop_call_ptr = gen_call - genop_getitem = _new_gen_call() - genop_len = _new_gen_call() - genop_pop = _new_gen_call() - genop_newlist = _new_gen_call() - genop_listnonzero = _new_gen_call() + xxx_genop_getitem = _new_gen_call() + xxx_genop_len = _new_gen_call() + xxx_genop_pop = _new_gen_call() + xxx_genop_newlist = _new_gen_call() + xxx_genop_listnonzero = _new_gen_call() def genop_call_void(self, op, arglocs): extra_on_stack = 0 @@ -533,9 +499,9 @@ self.mc.CALL(x) self.mc.ADD(esp, imm(WORD * extra_on_stack)) - genop_append = genop_call_void - genop_setitem = genop_call_void - genop_insert = genop_call_void + xxx_genop_append = genop_call_void + xxx_genop_setitem = genop_call_void + xxx_genop_insert = genop_call_void def genop_call__1(self, op, arglocs, resloc): self.gen_call(op, arglocs, resloc) @@ -546,18 +512,22 @@ self.gen_call(op, arglocs, resloc) self.mc.MOVZX(eax, eax) -genop_discard_dict = {} -genop_dict = {} +genop_discard_list = [None] * (MALLOC_VARSIZE + 1) +genop_list = [None] * (MALLOC_VARSIZE + 1) for name, value in Assembler386.__dict__.iteritems(): if name.startswith('genop_'): opname = name[len('genop_'):] + if opname == 'malloc_varsize': + num = MALLOC_VARSIZE + else: + num = getattr(rop, opname.upper()) if value.func_code.co_argcount == 3: - genop_discard_dict[opname] = value + genop_discard_list[num] = value else: - genop_dict[opname] = value + genop_list[num] = value -genop_discard_dict['call_void'] = Assembler386.genop_call_void +genop_discard_list[rop.CALL_VOID] = Assembler386.genop_call_void def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): if isinstance(reg_or_imm1, IMM32): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Sun Mar 1 16:33:42 2009 @@ -11,6 +11,9 @@ from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname + +MALLOC_VARSIZE = rop._CANRAISE_LAST + 1 + # esi edi and ebp can be added to this list, provided they're correctly # saved and restored REGS = [eax, ecx, edx] @@ -656,6 +659,9 @@ consider_int_ne = _consider_compop consider_int_eq = _consider_compop consider_uint_gt = _consider_compop + consider_uint_lt = _consider_compop + consider_uint_le = _consider_compop + consider_uint_ge = _consider_compop def sync_var(self, v): ops = [] @@ -717,21 +723,21 @@ ops0 += self.sync_var(v) if size != 0: # XXX lshift? - ops0.append(Perform(ResOperation('int_mul', [], []), + ops0.append(Perform(ResOperation(rop.INT_MUL, [], None), [loc, imm(1 << size)], loc)) - ops0.append(Perform(ResOperation('int_add', [], []), + ops0.append(Perform(ResOperation(rop.INT_ADD, [], None), [loc, imm(ofs + ofs_items)], loc)) else: ops0 = [] loc = imm(ofs + ofs_items + (v.getint() << size)) - ops = self._call(ResOperation('malloc_varsize', [v], [res_v]) + ops = self._call(ResOperation(MALLOC_VARSIZE, [v], res_v) , [loc], [v]) loc, ops1 = self.make_sure_var_in_reg(v, [res_v]) assert self.loc(res_v) == eax # now we have to reload length to some reasonable place self.eventually_free_var(v) res = (ops0 + ops + ops1 + - [PerformDiscard(ResOperation('setfield_gc', [], []), + [PerformDiscard(ResOperation(rop.SETFIELD_GC, [], None), [eax, imm(ofs + ofs_length), imm(WORD), loc])]) return res @@ -886,7 +892,7 @@ res = mp.arglocs[i] if not (isinstance(arg, Const) or (arg in self.loop_consts and self.loop_consts[arg] == i)): - assert isinstance(mp, MergePoint) + assert mp.opnum == rop.MERGE_POINT if arg in self.reg_bindings: if not isinstance(res, REG): ops.append(Store(arg, self.loc(arg), self.stack_bindings[arg])) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 1 16:33:42 2009 @@ -14,6 +14,7 @@ ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) from pypy.jit.backend.x86.assembler import Assembler386 from pypy.jit.backend.x86 import symbolic +from pypy.jit.metainterp.resoperation import rop, opname class CPU386(object): debug = True @@ -137,19 +138,18 @@ def get_exc_value(self, frame): return self.cast_int_to_gcref(self.assembler._exception_data[1]) - def execute_operation(self, opname, valueboxes, result_type): + def execute_operation(self, opnum, valueboxes, result_type): # mostly a hack: fall back to compiling and executing the single # operation. - if opname.startswith('#'): - return None - key = [opname, result_type] + key = [opnum, result_type] for valuebox in valueboxes: if isinstance(valuebox, Box): key.append(valuebox.type) else: key.append(repr(valuebox)) # XXX not RPython mp = self.get_compiled_single_operation(key, valueboxes) - res = self.execute_operations_in_new_frame(opname, mp, valueboxes, + res = self.execute_operations_in_new_frame(opname[opnum], mp, + valueboxes, result_type) if self.assembler._exception_data[0] != 0: TP = lltype.Ptr(rclass.OBJECT_VTABLE) @@ -168,7 +168,7 @@ try: return self._compiled_ops[real_key] except KeyError: - opname = key[0] + opnum = key[0] result_type = key[1] livevarlist = [] i = 0 @@ -185,19 +185,23 @@ raise ValueError(type) livevarlist.append(box) i += 1 - mp = MergePoint('merge_point', livevarlist, []) + mp = ResOperation(rop.MERGE_POINT, livevarlist, None) if result_type == 'void': - results = [] + result = None elif result_type == 'int': - results = [history.BoxInt()] + result = history.BoxInt() elif result_type == 'ptr': - results = [history.BoxPtr()] + result = history.BoxPtr() else: raise ValueError(result_type) + if result is None: + results = [] + else: + results = [result] operations = [mp, - ResOperation(opname, livevarlist, results), - ResOperation('return', results, [])] - if opname.startswith('guard_'): + ResOperation(opnum, livevarlist, result), + ResOperation(rop.RETURN, results, None)] + if operations[1].is_guard(): operations[1].liveboxes = [] self.compile_operations(operations, verbose=False) self._compiled_ops[real_key] = mp Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Sun Mar 1 16:33:42 2009 @@ -65,9 +65,13 @@ result = BoxPtr() else: raise ValueError(result_type) + if result is None: + results = [] + else: + results = [result] operations = [mp, ResOperation(opnum, livevarlist, result), - ResOperation(rop.RETURN, [result], None)] + ResOperation(rop.RETURN, results, None)] if operations[1].is_guard(): operations[1].liveboxes = [] self.cpu.compile_operations(operations, verbose=False) @@ -85,17 +89,17 @@ def test_int_unary_ops(self): for op, args, res in [ - ('int_neg', [BoxInt(42)], -42), + (rop.INT_NEG, [BoxInt(42)], -42), ]: assert self.execute_operation(op, args, 'int').value == res def test_int_comp_ops(self): for op, args, res in [ - ('int_lt', [BoxInt(40), BoxInt(39)], 0), - ('int_lt', [BoxInt(40), ConstInt(41)], 1), - ('int_lt', [ConstInt(41), BoxInt(40)], 0), - ('int_le', [ConstInt(42), BoxInt(42)], 1), - ('int_gt', [BoxInt(40), ConstInt(-100)], 1), + (rop.INT_LT, [BoxInt(40), BoxInt(39)], 0), + (rop.INT_LT, [BoxInt(40), ConstInt(41)], 1), + (rop.INT_LT, [ConstInt(41), BoxInt(40)], 0), + (rop.INT_LE, [ConstInt(42), BoxInt(42)], 1), + (rop.INT_GT, [BoxInt(40), ConstInt(-100)], 1), ]: assert self.execute_operation(op, args, 'int').value == res @@ -104,11 +108,12 @@ u = lltype.malloc(U) u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) ofs_box = ConstInt(cpu.fielddescrof(S, 'value')) - assert self.execute_operation('setfield_gc', [u_box, ofs_box, BoxInt(3)], + assert self.execute_operation(rop.SETFIELD_GC, + [u_box, ofs_box, BoxInt(3)], 'void') == None assert u.parent.parent.value == 3 u.parent.parent.value += 100 - assert (self.execute_operation('getfield_gc', [u_box, ofs_box], 'int') + assert (self.execute_operation(rop.GETFIELD_GC, [u_box, ofs_box], 'int') .value == 103) def test_execute_operations_in_env(self): @@ -120,12 +125,12 @@ t = BoxInt(455) u = BoxInt(0) # False operations = [ - ResOperation(rop.MERGE_POINT, [x, y], []), - ResOperation(rop.INT_ADD, [x, y], [z]), - ResOperation(rop.INT_SUB, [y, ConstInt(1)], [t]), - ResOperation('int_eq', [t, ConstInt(0)], [u]), - ResOperation('guard_false', [u], []), - ResOperation('jump', [z, t], []), + ResOperation(rop.MERGE_POINT, [x, y], None), + ResOperation(rop.INT_ADD, [x, y], z), + ResOperation(rop.INT_SUB, [y, ConstInt(1)], t), + ResOperation(rop.INT_EQ, [t, ConstInt(0)], u), + ResOperation(rop.GUARD_FALSE, [u], None), + ResOperation(rop.JUMP, [z, t], None), ] startmp = operations[0] operations[-1].jump_target = startmp @@ -143,16 +148,16 @@ vtable_for_T = lltype.malloc(MY_VTABLE, immortal=True) cpu = self.cpu cpu._cache_gcstruct2vtable = {T: vtable_for_T} - for (opname, args) in [('guard_true', [BoxInt(1)]), - ('guard_false', [BoxInt(0)]), - ('guard_value', [BoxInt(42), BoxInt(42)])]: + for (opname, args) in [(rop.GUARD_TRUE, [BoxInt(1)]), + (rop.GUARD_FALSE, [BoxInt(0)]), + (rop.GUARD_VALUE, [BoxInt(42), BoxInt(42)])]: assert self.execute_operation(opname, args, 'void') == None t = lltype.malloc(T) t.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) T_box = ConstInt(rffi.cast(lltype.Signed, vtable_for_T)) null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) - assert self.execute_operation('guard_class', [t_box, T_box], 'void') == None + assert self.execute_operation(rop.GUARD_CLASS, [t_box, T_box], 'void') == None def test_failing_guards(self): vtable_for_T = lltype.malloc(MY_VTABLE, immortal=True) @@ -169,11 +174,11 @@ u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) U_box = ConstInt(rffi.cast(lltype.Signed, vtable_for_U)) null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) - for opname, args in [('guard_true', [BoxInt(0)]), - ('guard_false', [BoxInt(1)]), - ('guard_value', [BoxInt(42), BoxInt(41)]), - ('guard_class', [t_box, U_box]), - ('guard_class', [u_box, T_box]), + for opname, args in [(rop.GUARD_TRUE, [BoxInt(0)]), + (rop.GUARD_FALSE, [BoxInt(1)]), + (rop.GUARD_VALUE, [BoxInt(42), BoxInt(41)]), + (rop.GUARD_CLASS, [t_box, U_box]), + (rop.GUARD_CLASS, [u_box, T_box]), ]: cpu.metainterp.gf = None assert self.execute_operation(opname, args, 'void') == None @@ -181,15 +186,15 @@ def test_misc_int_ops(self): for op, args, res in [ - ('int_mod', [BoxInt(7), BoxInt(3)], 1), - ('int_mod', [ConstInt(0), BoxInt(7)], 0), - ('int_mod', [BoxInt(13), ConstInt(5)], 3), - ('int_mod', [ConstInt(33), ConstInt(10)], 3), - ('int_floordiv', [BoxInt(13), BoxInt(3)], 4), - ('int_floordiv', [BoxInt(42), ConstInt(10)], 4), - ('int_floordiv', [ConstInt(42), BoxInt(10)], 4), - ('int_rshift', [ConstInt(3), BoxInt(4)], 3>>4), - ('int_rshift', [BoxInt(3), ConstInt(10)], 3>>10), + (rop.INT_MOD, [BoxInt(7), BoxInt(3)], 1), + (rop.INT_MOD, [ConstInt(0), BoxInt(7)], 0), + (rop.INT_MOD, [BoxInt(13), ConstInt(5)], 3), + (rop.INT_MOD, [ConstInt(33), ConstInt(10)], 3), + (rop.INT_FLOORDIV, [BoxInt(13), BoxInt(3)], 4), + (rop.INT_FLOORDIV, [BoxInt(42), ConstInt(10)], 4), + (rop.INT_FLOORDIV, [ConstInt(42), BoxInt(10)], 4), + (rop.INT_RSHIFT, [ConstInt(3), BoxInt(4)], 3>>4), + (rop.INT_RSHIFT, [BoxInt(3), ConstInt(10)], 3>>10), ]: assert self.execute_operation(op, args, 'int').value == res @@ -223,14 +228,14 @@ self.cpu.assembler.malloc_func_addr = addr ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] - res = self.execute_operation('newstr', [ConstInt(7)], 'ptr') + res = self.execute_operation(rop.NEWSTR, [ConstInt(7)], 'ptr') assert allocs[0] == 7 + ofs + WORD resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) assert resbuf[ofs/WORD] == 7 # ------------------------------------------------------------ - res = self.execute_operation('newstr', [BoxInt(7)], 'ptr') + res = self.execute_operation(rop.NEWSTR, [BoxInt(7)], 'ptr') assert allocs[0] == 7 + ofs + WORD resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) assert resbuf[ofs/WORD] == 7 @@ -241,7 +246,7 @@ ofs = symbolic.get_field_token(TP, 'length')[0] descr = ConstInt(self.cpu.arraydescrof(TP)) - res = self.execute_operation('new_array', [descr, ConstInt(10)], + res = self.execute_operation(rop.NEW_ARRAY, [descr, ConstInt(10)], 'ptr') assert allocs[0] == 10*WORD + ofs + WORD resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) @@ -249,7 +254,7 @@ # ------------------------------------------------------------ - res = self.execute_operation('new_array', [descr, BoxInt(10)], + res = self.execute_operation(rop.NEW_ARRAY, [descr, BoxInt(10)], 'ptr') assert allocs[0] == 10*WORD + ofs + WORD resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) @@ -263,13 +268,13 @@ ofs = symbolic.get_field_token(STR, 'chars')[0] ofs_items = symbolic.get_field_token(STR.chars, 'items')[0] - res = self.execute_operation('newstr', [ConstInt(10)], 'ptr') - self.execute_operation('strsetitem', [res, ConstInt(2), ConstInt(ord('d'))], 'void') + res = self.execute_operation(rop.NEWSTR, [ConstInt(10)], 'ptr') + self.execute_operation(rop.STRSETITEM, [res, ConstInt(2), ConstInt(ord('d'))], 'void') resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_char)) assert resbuf[ofs + ofs_items + 2] == 'd' - self.execute_operation('strsetitem', [res, BoxInt(2), ConstInt(ord('z'))], 'void') + self.execute_operation(rop.STRSETITEM, [res, BoxInt(2), ConstInt(ord('z'))], 'void') assert resbuf[ofs + ofs_items + 2] == 'z' - r = self.execute_operation('strgetitem', [res, BoxInt(2)], 'int') + r = self.execute_operation(rop.STRGETITEM, [res, BoxInt(2)], 'int') assert r.value == ord('z') def test_arrayitems(self): @@ -277,25 +282,25 @@ ofs = symbolic.get_field_token(TP, 'length')[0] itemsofs = symbolic.get_field_token(TP, 'items')[0] descr = ConstInt(self.cpu.arraydescrof(TP)) - res = self.execute_operation('new_array', [descr, ConstInt(10)], + res = self.execute_operation(rop.NEW_ARRAY, [descr, ConstInt(10)], 'ptr') resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) assert resbuf[ofs/WORD] == 10 - self.execute_operation('setarrayitem_gc', [res, descr, - ConstInt(2), BoxInt(38)], + self.execute_operation(rop.SETARRAYITEM_GC, [res, descr, + ConstInt(2), BoxInt(38)], 'void') assert resbuf[itemsofs/WORD + 2] == 38 - self.execute_operation('setarrayitem_gc', [res, descr, - BoxInt(3), BoxInt(42)], + self.execute_operation(rop.SETARRAYITEM_GC, [res, descr, + BoxInt(3), BoxInt(42)], 'void') assert resbuf[itemsofs/WORD + 3] == 42 - r = self.execute_operation('getarrayitem_gc', [res, descr, - ConstInt(2)], 'int') + r = self.execute_operation(rop.GETARRAYITEM_GC, [res, descr, + ConstInt(2)], 'int') assert r.value == 38 - r = self.execute_operation('getarrayitem_gc', [res, descr, - BoxInt(3)], 'int') + r = self.execute_operation(rop.GETARRAYITEM_GC, [res, descr, + BoxInt(3)], 'int') assert r.value == 42 def test_getfield_setfield(self): @@ -305,7 +310,7 @@ ('c1', lltype.Char), ('c2', lltype.Char), ('c3', lltype.Char)) - res = self.execute_operation('new', [ConstInt(self.cpu.sizeof(TP))], + res = self.execute_operation(rop.NEW, [ConstInt(self.cpu.sizeof(TP))], 'ptr') ofs_s = ConstInt(self.cpu.fielddescrof(TP, 's')) ofs_f = ConstInt(self.cpu.fielddescrof(TP, 'f')) @@ -313,36 +318,36 @@ ofsc1 = ConstInt(self.cpu.fielddescrof(TP, 'c1')) ofsc2 = ConstInt(self.cpu.fielddescrof(TP, 'c2')) ofsc3 = ConstInt(self.cpu.fielddescrof(TP, 'c3')) - self.execute_operation('setfield_gc', [res, ofs_s, ConstInt(3)], 'void') + self.execute_operation(rop.SETFIELD_GC, [res, ofs_s, ConstInt(3)], 'void') # XXX ConstFloat - #self.execute_operation('setfield_gc', [res, ofs_f, 1e100], 'void') + #self.execute_operation(rop.SETFIELD_GC, [res, ofs_f, 1e100], 'void') # XXX we don't support shorts (at all) - #self.execute_operation('setfield_gc', [res, ofs_u, ConstInt(5)], 'void') - s = self.execute_operation('getfield_gc', [res, ofs_s], 'int') + #self.execute_operation(rop.SETFIELD_GC, [res, ofs_u, ConstInt(5)], 'void') + s = self.execute_operation(rop.GETFIELD_GC, [res, ofs_s], 'int') assert s.value == 3 - self.execute_operation('setfield_gc', [res, ofs_s, BoxInt(3)], 'void') - s = self.execute_operation('getfield_gc', [res, ofs_s], 'int') + self.execute_operation(rop.SETFIELD_GC, [res, ofs_s, BoxInt(3)], 'void') + s = self.execute_operation(rop.GETFIELD_GC, [res, ofs_s], 'int') assert s.value == 3 - #u = self.execute_operation('getfield_gc', [res, ofs_u], 'int') + #u = self.execute_operation(rop.GETFIELD_GC, [res, ofs_u], 'int') #assert u.value == 5 - self.execute_operation('setfield_gc', [res, ofsc1, ConstInt(1)], 'void') - self.execute_operation('setfield_gc', [res, ofsc2, ConstInt(2)], 'void') - self.execute_operation('setfield_gc', [res, ofsc3, ConstInt(3)], 'void') - c = self.execute_operation('getfield_gc', [res, ofsc1], 'int') + self.execute_operation(rop.SETFIELD_GC, [res, ofsc1, ConstInt(1)], 'void') + self.execute_operation(rop.SETFIELD_GC, [res, ofsc2, ConstInt(2)], 'void') + self.execute_operation(rop.SETFIELD_GC, [res, ofsc3, ConstInt(3)], 'void') + c = self.execute_operation(rop.GETFIELD_GC, [res, ofsc1], 'int') assert c.value == 1 - c = self.execute_operation('getfield_gc', [res, ofsc2], 'int') + c = self.execute_operation(rop.GETFIELD_GC, [res, ofsc2], 'int') assert c.value == 2 - c = self.execute_operation('getfield_gc', [res, ofsc3], 'int') + c = self.execute_operation(rop.GETFIELD_GC, [res, ofsc3], 'int') assert c.value == 3 def test_ovf_ops(self): arg0 = BoxInt(12) arg1 = BoxInt(13) - res = self.execute_operation('int_mul_ovf', [arg0, arg1], 'int') + res = self.execute_operation(rop.INT_MUL_OVF, [arg0, arg1], 'int') assert res.value == 12*13 arg0 = BoxInt(sys.maxint/2) arg1 = BoxInt(2222) - self.execute_operation('int_mul_ovf', [arg0, arg1], 'int') + self.execute_operation(rop.INT_MUL_OVF, [arg0, arg1], 'int') assert self.cpu.assembler._exception_data[0] == 1 self.cpu.assembler._exception_data[0] = 0 @@ -351,16 +356,16 @@ arg0 = BoxInt(intmask(r_uint(sys.maxint + 3))) arg1 = BoxInt(intmask(r_uint(4))) - res = self.execute_operation('uint_add', [arg0, arg1], 'int') + res = self.execute_operation(rop.UINT_ADD, [arg0, arg1], 'int') assert res.value == intmask(r_uint(sys.maxint + 3) + r_uint(4)) arg0 = BoxInt(intmask(sys.maxint + 10)) arg1 = BoxInt(10) - res = self.execute_operation('uint_mul', [arg0, arg1], 'int') + res = self.execute_operation(rop.UINT_MUL, [arg0, arg1], 'int') assert res.value == intmask((sys.maxint + 10) * 10) arg0 = BoxInt(intmask(r_uint(sys.maxint + 3))) arg1 = BoxInt(intmask(r_uint(4))) - res = self.execute_operation('uint_gt', [arg0, arg1], 'int') + res = self.execute_operation(rop.UINT_GT, [arg0, arg1], 'int') assert res.value == 1 From fijal at codespeak.net Sun Mar 1 16:54:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 16:54:39 +0100 (CET) Subject: [pypy-svn] r62300 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090301155439.CC384168456@codespeak.net> Author: fijal Date: Sun Mar 1 16:54:39 2009 New Revision: 62300 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: A couple of asserts and intmask. Might break translation though, will fix later Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 16:54:39 2009 @@ -237,6 +237,7 @@ type = 'int' def __init__(self, value=0): + assert isinstance(value, int) self.value = value def clonebox(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Mar 1 16:54:39 2009 @@ -15,6 +15,7 @@ from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) from pypy.jit.metainterp import codewriter, optimize +from pypy.rlib.rarithmetic import intmask # ____________________________________________________________ @@ -894,6 +895,7 @@ cls = ConstInt else: cls = BoxInt + value = intmask(value) box = cls(value) original_boxes.append(box) self._initialize_from_start(original_boxes, num_green_args-1, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sun Mar 1 16:54:39 2009 @@ -18,6 +18,7 @@ assert isinstance(opnum, int) self.opnum = opnum self.args = list(args) + assert not isinstance(result, list) self.result = result def __repr__(self): From fijal at codespeak.net Sun Mar 1 17:00:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 17:00:58 +0100 (CET) Subject: [pypy-svn] r62301 - in pypy/branch/pyjitpl5/pypy/jit: backend/x86/test metainterp Message-ID: <20090301160058.B09AD168052@codespeak.net> Author: fijal Date: Sun Mar 1 17:00:57 2009 New Revision: 62301 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: * Fix assertion * Finish fixing tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Sun Mar 1 17:00:57 2009 @@ -3,11 +3,11 @@ """ import py -from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump, - BoxInt, ConstInt, GuardOp) +from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt from pypy.jit.backend.x86.runner import CPU, GuardFailed from pypy.rpython.lltypesystem import lltype from pypy.jit.backend.x86.test.test_runner import FakeMetaInterp, FakeStats +from pypy.jit.metainterp.resoperation import rop def test_simple_loop(): meta_interp = FakeMetaInterp() @@ -22,11 +22,11 @@ # while i < 5: # i += 1 operations = [ - MergePoint('merge_point', [i, flag], []), - GuardOp('guard_true', [flag], []), - ResOperation('int_add', [i, ConstInt(1)], [i_0]), - ResOperation('int_lt', [i_0, ConstInt(5)], [flag_0]), - Jump('jump', [i_0, flag_0], []), + ResOperation(rop.MERGE_POINT, [i, flag], None), + ResOperation(rop.GUARD_TRUE, [flag], None), + ResOperation(rop.INT_ADD, [i, ConstInt(1)], i_0), + ResOperation(rop.INT_LT, [i_0, ConstInt(5)], flag_0), + ResOperation(rop.JUMP, [i_0, flag_0], None), ] startmp = operations[0] operations[-1].jump_target = startmp @@ -74,17 +74,17 @@ i += 1 return [x, y, i, i < 5] operations = [ - MergePoint('merge_point', [x, y, i, flag], []), - GuardOp('guard_true', [flag], []), - ResOperation('int_add', [y, x], [v0]), - ResOperation('int_mul', [v0, i], [v1]), - ResOperation('int_sub', [v1, x], [x0]), - ResOperation('int_mul', [x0, y], [v2]), - ResOperation('int_mul', [i, y], [v3]), - ResOperation('int_sub', [v3, v2], [y0]), - ResOperation('int_add', [i, ConstInt(1)], [i0]), - ResOperation('int_lt', [i0, ConstInt(5)], [flag0]), - Jump('jump', [x0, y0, i0, flag0], []), + ResOperation(rop.MERGE_POINT, [x, y, i, flag], None), + ResOperation(rop.GUARD_TRUE, [flag], None), + ResOperation(rop.INT_ADD, [y, x], v0), + ResOperation(rop.INT_MUL, [v0, i], v1), + ResOperation(rop.INT_SUB, [v1, x], x0), + ResOperation(rop.INT_MUL, [x0, y], v2), + ResOperation(rop.INT_MUL, [i, y], v3), + ResOperation(rop.INT_SUB, [v3, v2], y0), + ResOperation(rop.INT_ADD, [i, ConstInt(1)], i0), + ResOperation(rop.INT_LT, [i0, ConstInt(5)], flag0), + ResOperation(rop.JUMP, [x0, y0, i0, flag0], None), ] startmp = operations[0] operations[-1].jump_target = startmp @@ -110,11 +110,11 @@ i0 = BoxInt(0) v0 = BoxInt(0) operations = [ - MergePoint('merge_point', [x, y, z, i], []), - ResOperation('int_sub', [i, ConstInt(1)], [i0]), - ResOperation('int_gt', [i0, ConstInt(0)], [v0]), - GuardOp('guard_true', [v0], []), - ResOperation('jump', [x, z, y, i0], []), + ResOperation(rop.MERGE_POINT, [x, y, z, i], None), + ResOperation(rop.INT_SUB, [i, ConstInt(1)], i0), + ResOperation(rop.INT_GT, [i0, ConstInt(0)], v0), + ResOperation(rop.GUARD_TRUE, [v0], None), + ResOperation(rop.JUMP, [x, z, y, i0], None), ] operations[-1].jump_target = operations[0] operations[3].liveboxes = [v0, x, y, z, i0] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py Sun Mar 1 17:00:57 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("Widening to trash error") from pypy.jit.metainterp.test.test_tl import ToyLanguageTests from pypy.jit.backend.x86.test.test_basic import Jit386Mixin Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py Sun Mar 1 17:00:57 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("Widening to trash error") from pypy.jit.backend.x86.test.test_basic import Jit386Mixin from pypy.jit.metainterp.test.test_tlc import TLCTests from pypy.jit.tl import tlc Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 17:00:57 2009 @@ -237,7 +237,8 @@ type = 'int' def __init__(self, value=0): - assert isinstance(value, int) + if not we_are_translated(): + assert isinstance(value, (int, ComputedIntSymbolic)) self.value = value def clonebox(self): From arigo at codespeak.net Sun Mar 1 17:39:25 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 1 Mar 2009 17:39:25 +0100 (CET) Subject: [pypy-svn] r62302 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090301163925.BBCDA1684BB@codespeak.net> Author: arigo Date: Sun Mar 1 17:39:23 2009 New Revision: 62302 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Log: Restart implementing list support. For now only fixed-sized lists, implemented directly as array operations. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sun Mar 1 17:39:23 2009 @@ -195,7 +195,7 @@ if tp == 'int': return str(x) elif tp == 'void': - return '' + return '---' elif tp == 'ptr': if not x: return '(* None)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Mar 1 17:39:23 2009 @@ -15,27 +15,6 @@ MAX_MAKE_NEW_VARS = 16 -##class BuiltinDescr(history.AbstractValue): -## pass - -##class ListDescr(BuiltinDescr): -## def __init__(self, getfunc, setfunc, malloc_func, append_func, -## pop_func, insert_func, len_func, nonzero_func, tp): -## self.setfunc = setfunc -## self.getfunc = getfunc -## self.malloc_func = malloc_func -## self.append_func = append_func -## self.insert_func = insert_func -## self.pop_func = pop_func -## self.len_func = len_func -## self.nonzero_func = nonzero_func -## self.tp = tp - -## def equals(self, other): -## if isinstance(other, ListDescr): -## return True -## return False - class JitCode(history.AbstractValue): def __init__(self, name): self.name = name @@ -99,7 +78,6 @@ self.rtyper = metainterp.cpu.rtyper self.cpu = metainterp.cpu self.policy = policy - self.list_cache = {} def make_portal_bytecode(self, graph): log.info("making JitCodes...") @@ -133,81 +111,52 @@ IndirectCallset(self, graphs) return result - def get_list_desc(self, LIST): - try: - return self.all_listdescs[LIST] - except KeyError: - import vlist - listdesc = vlist.ListClassDesc(self, LIST) - self.all_listdescs[LIST] = listdesc - return listdesc - - def register_list_op(self, llfunc, oopspec_name, LIST): - metainterp = self.metainterp - if llfunc._obj not in metainterp.builtins_seen: - metainterp.builtins_seen[llfunc._obj] = True - key = llmemory.cast_ptr_to_adr(llfunc) - value = (oopspec_name.replace('.', '_'), self.get_list_desc(LIST)) - metainterp.builtins_keys.append(key) - metainterp.builtins_values.append(value) - - def list_descr_for_tp(self, TP): + if 0: # disabled + def fixed_list_descr_for_tp(self, TP): try: - return self.list_cache[TP.TO] + return self.fixed_list_cache[TP.TO] except KeyError: - if isinstance(TP.TO, lltype.GcStruct): - OF = TP.TO.items.TO.OF - else: - OF = TP.TO.OF + OF = TP.TO.OF rtyper = self.rtyper - args = [TP, lltype.Signed, OF] setfunc, _ = support.builtin_func_for_spec(rtyper, 'list.setitem', - args, lltype.Void) + [TP, lltype.Signed, OF], + lltype.Void) getfunc, _ = support.builtin_func_for_spec(rtyper, 'list.getitem', - args[:-1], OF) + [TP, lltype.Signed], OF) malloc_func, _ = support.builtin_func_for_spec(rtyper, 'newlist', - [lltype.Signed], TP) + [lltype.Signed, OF], + TP) len_func, _ = support.builtin_func_for_spec(rtyper, 'list.len', [TP], lltype.Signed) - nonzero_func, _ = support.builtin_func_for_spec(rtyper, - 'list.nonzero', - [TP], lltype.Bool) - - if isinstance(TP.TO, lltype.GcStruct): - append_func, _ = support.builtin_func_for_spec(rtyper, - 'list.append', - [TP, OF], lltype.Void) - pop_func, _ = support.builtin_func_for_spec(rtyper, 'list.pop', - [TP], OF) - insert_func, _ = support.builtin_func_for_spec(rtyper, - 'list.insert', [TP, lltype.Signed, OF], lltype.Void) - if isinstance(OF, lltype.Number): - tp = "int" - else: - tp = "ptr" - if isinstance(TP.TO, lltype.GcStruct): - ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), - history.ConstAddr(setfunc.value, self.cpu), - history.ConstAddr(malloc_func.value, self.cpu), - history.ConstAddr(append_func.value, self.cpu), - history.ConstAddr(pop_func.value, self.cpu), - history.ConstAddr(insert_func.value, self.cpu), - history.ConstAddr(len_func.value, self.cpu), - history.ConstAddr(nonzero_func.value, self.cpu), - tp) - else: - ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), - history.ConstAddr(setfunc.value, self.cpu), - history.ConstAddr(malloc_func.value, self.cpu), - None, None, None, - history.ConstAddr(len_func.value, self.cpu), - history.ConstAddr(nonzero_func.value, self.cpu), - tp) - self.list_cache[TP.TO] = ld +## if isinstance(TP.TO, lltype.GcStruct): +## append_func, _ = support.builtin_func_for_spec(rtyper, +## 'list.append', +## [TP, OF], lltype.Void) +## pop_func, _ = support.builtin_func_for_spec(rtyper, 'list.pop', +## [TP], OF) +## insert_func, _ = support.builtin_func_for_spec(rtyper, +## 'list.insert', [TP, lltype.Signed, OF], lltype.Void) + tp = getkind(OF) +## if isinstance(TP.TO, lltype.GcStruct): +## ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), +## history.ConstAddr(setfunc.value, self.cpu), +## history.ConstAddr(malloc_func.value, self.cpu), +## history.ConstAddr(append_func.value, self.cpu), +## history.ConstAddr(pop_func.value, self.cpu), +## history.ConstAddr(insert_func.value, self.cpu), +## history.ConstAddr(len_func.value, self.cpu), +## history.ConstAddr(nonzero_func.value, self.cpu), +## tp) +## else: + ld = FixedListDescr(history.ConstAddr(getfunc.value, self.cpu), + history.ConstAddr(setfunc.value, self.cpu), + history.ConstAddr(malloc_func.value, self.cpu), + history.ConstAddr(len_func.value, self.cpu), + tp) + self.fixed_list_cache[TP.TO] = ld return ld - class BytecodeMaker(object): debug = True @@ -722,7 +671,9 @@ c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, oopspec_name, ll_args, op.result.concretetype) -## if oopspec_name.startswith('list') or oopspec_name == 'newlist': + if self.codewriter.metainterp.options.listops: + if self.handle_list_call(op, oopspec_name, args, TP): + return ## if oopspec_name.startswith('list.getitem'): ## opname = oopspec_name[len('list.'):] ## elif oopspec_name.startswith('list.setitem'): @@ -757,6 +708,57 @@ self.emit_varargs([c_func] + args) self.register_var(op.result) + def handle_list_call(self, op, oopspec_name, args, TP): + if not (oopspec_name.startswith('list.') or oopspec_name == 'newlist'): + return False + if hasattr(TP, '_ll_resize'): + return False + # non-resizable lists: they are just arrays + ARRAY = TP.TO + assert isinstance(ARRAY, lltype.GcArray) + arraydescr = self.cpu.arraydescrof(ARRAY) + # + if oopspec_name == 'newlist': + # normalize number of arguments + if len(args) < 1: + args.append(Constant(0, lltype.Signed)) + if len(args) > 1: + v_default = args[1] + if (not isinstance(v_default, Constant) or + v_default.value != TP.TO.OF._defl()): + return False # variable or non-null initial value + self.emit('new_array') + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(args[0])) + self.register_var(op.result) + return True + # + if (oopspec_name == 'list.getitem' or + oopspec_name == 'list.getitem_foldable'): # <- XXX do better here + # XXX check if index < 0, and check IndexError, both only if needed + self.emit('getarrayitem_gc') + self.emit(self.var_position(args[0])) + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(args[1])) + self.register_var(op.result) + return True + # + if oopspec_name == 'list.setitem': + # XXX check if index < 0, and check IndexError, both only if needed + self.emit('setarrayitem_gc') + self.emit(self.var_position(args[0])) + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(args[1])) + self.emit(self.var_position(args[2])) + self.register_var(op.result) + return True + # + if (oopspec_name == 'list.len' or + oopspec_name == 'list.len_foldable'): + xxx # ... 'arraylen_gc' + # + return False + def serialize_op_indirect_call(self, op): self.minimize_variables() targets = self.codewriter.policy.graphs_from(op) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 17:39:23 2009 @@ -465,7 +465,8 @@ # ---------------------------------------------------------------- class Options: - def __init__(self, specialize=True): + def __init__(self, specialize=True, listops=False): self.specialize = specialize + self.listops = listops def _freeze_(self): return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Mar 1 17:39:23 2009 @@ -76,10 +76,6 @@ assert isinstance(indirectcallset, codewriter.IndirectCallset) args += (indirectcallset, ) - elif argspec == "builtin": - builtin = self.load_const_arg() - assert isinstance(builtin, codewriter.BuiltinDescr) - args += (builtin, ) elif argspec == "virtualizabledesc": from virtualizable import VirtualizableDesc virtualizabledesc = self.load_const_arg() @@ -424,59 +420,56 @@ return self.execute_with_exc(rop.CALL_VOID, varargs, 'void') - @arguments("builtin", "varargs") - def opimpl_getitem(self, descr, varargs): - args = [descr.getfunc] + varargs - return self.execute_with_exc('getitem', args, descr.tp) - - @arguments("builtin", "varargs") - def opimpl_setitem(self, descr, varargs): - args = [descr.setfunc] + varargs - return self.execute_with_exc('setitem', args, 'void') - - @arguments("builtin", "varargs") - def opimpl_getitem_foldable(self, descr, varargs): - args = [descr.getfunc] + varargs - return self.execute_with_exc('getitem', args, descr.tp, True) - - @arguments("builtin", "varargs") - def opimpl_setitem_foldable(self, descr, varargs): - args = [descr.setfunc] + varargs - return self.execute_with_exc('setitem', args, 'void', True) - - @arguments("builtin", "varargs") - def opimpl_newlist(self, descr, varargs): - if len(varargs) == 2: - mf = descr.malloc_3_func - else: - mf = descr.malloc_2_func - args = [mf] + varargs - return self.execute_with_exc('newlist', args, 'ptr') - - @arguments("builtin", "varargs") - def opimpl_append(self, descr, varargs): - args = [descr.append_func] + varargs - return self.execute_with_exc('append', args, 'void') - - @arguments("builtin", "varargs") - def opimpl_insert(self, descr, varargs): - args = [descr.insert_func] + varargs - return self.execute_with_exc('insert', args, 'void') - - @arguments("builtin", "varargs") - def opimpl_pop(self, descr, varargs): - args = [descr.pop_func] + varargs - return self.execute_with_exc('pop', args, descr.tp) - - @arguments("builtin", "varargs") - def opimpl_len(self, descr, varargs): - args = [descr.len_func] + varargs - return self.execute_with_exc('len', args, 'int') - - @arguments("builtin", "varargs") - def opimpl_listnonzero(self, descr, varargs): - args = [descr.nonzero_func] + varargs - return self.execute_with_exc('listnonzero', args, 'int') +## @arguments("fixedlist", "box", "box") +## def opimpl_list_getitem(self, descr, listbox, indexbox): +## args = [descr.getfunc, listbox, indexbox] +## return self.execute_with_exc(rop.LIST_GETITEM, args, descr.tp) + +## @arguments("fixedlist", "box", "box", "box") +## def opimpl_list_setitem(self, descr, listbox, indexbox, newitembox): +## args = [descr.setfunc, listbox, indexbox, newitembox] +## return self.execute_with_exc(rop.LIST_SETITEM, args, 'void') + +## @arguments("builtin", "varargs") +## def opimpl_getitem_foldable(self, descr, varargs): +## args = [descr.getfunc] + varargs +## return self.execute_with_exc('getitem', args, descr.tp, True) + +## @arguments("builtin", "varargs") +## def opimpl_setitem_foldable(self, descr, varargs): +## args = [descr.setfunc] + varargs +## return self.execute_with_exc('setitem', args, 'void', True) + +## @arguments("fixedlist", "box", "box") +## def opimpl_newlist(self, descr, countbox, defaultbox): +## args = [descr.malloc_func, countbox, defaultbox] +## return self.execute_with_exc(rop.NEWLIST, args, 'ptr') + +## @arguments("builtin", "varargs") +## def opimpl_append(self, descr, varargs): +## args = [descr.append_func] + varargs +## return self.execute_with_exc('append', args, 'void') + +## @arguments("builtin", "varargs") +## def opimpl_insert(self, descr, varargs): +## args = [descr.insert_func] + varargs +## return self.execute_with_exc('insert', args, 'void') + +## @arguments("builtin", "varargs") +## def opimpl_pop(self, descr, varargs): +## args = [descr.pop_func] + varargs +## return self.execute_with_exc('pop', args, descr.tp) + +## @arguments("builtin", "varargs") +## def opimpl_len(self, descr, varargs): +## args = [descr.len_func] + varargs +## return self.execute_with_exc('len', args, 'int') + +## @arguments("builtin", "varargs") +## def opimpl_listnonzero(self, descr, varargs): +## args = [descr.nonzero_func] + varargs +## return self.execute_with_exc('listnonzero', args, 'int') + @arguments("orgpc", "indirectcallset", "box", "varargs") def opimpl_indirect_call(self, pc, indirectcallset, box, varargs): @@ -721,12 +714,6 @@ self.opcode_implementations = [] self.opname_to_index = {} - - # helpers to eventually build the dictionary "self.builtins": - self.builtins_keys = [] - self.builtins_values = [] - self.builtins_seen = {} - self.class_sizes = populate_type_cache(graphs, self.cpu) self._virtualizabledescs = {} @@ -980,26 +967,6 @@ frame.exception_target)) return key - def make_builtin_dictionary(self): - # In case this is translated, the following runs at run-time. - # It's not possible to make a dictionary with keys that are function - # pointers at translation-time, as the actual address of each - # function could change from run to run. - if we_are_translated(): - self.builtins = {} - for i in range(len(self.builtins_keys)): - self.builtins[self.builtins_keys[i]] = self.builtins_values[i] - - def builtins_get(self, addr): - assert lltype.typeOf(addr) == llmemory.Address - if we_are_translated(): - return self.builtins.get(addr, (None, None)) - else: - for i in range(len(self.builtins_keys)): - if self.builtins_keys[i] == addr: - return self.builtins_values[i] - return (None, None) - # ____________________________________________________________ # construction-time interface Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sun Mar 1 17:39:23 2009 @@ -126,6 +126,7 @@ OOIS = 72 OOISNOT = 73 # + ARRAYLEN_GC = 77 STRLEN = 78 STRGETITEM = 79 _ALWAYS_PURE_LAST = 79 # ----- end of always_pure operations ----- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Sun Mar 1 17:39:23 2009 @@ -17,7 +17,8 @@ stats = history.Stats() cpu = CPUClass(rtyper, stats, False) graph = rtyper.annotator.translator.graphs[0] - metainterp = pyjitpl.OOMetaInterp(graph, [], cpu, stats, False) + opt = history.Options(specialize=False, listops=False) + metainterp = pyjitpl.OOMetaInterp(graph, [], cpu, stats, opt) metainterp.num_green_args = 0 return metainterp, rtyper Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Sun Mar 1 17:39:23 2009 @@ -46,7 +46,7 @@ lst[0] += 2 n -= 1 return lst[0] - res = self.meta_interp(f, [21]) + res = self.meta_interp(f, [21], listops=True) assert res == 42 # no more list operations in the loop py.test.skip("not a ModifiedList yet") From afa at codespeak.net Sun Mar 1 18:05:52 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 1 Mar 2009 18:05:52 +0100 (CET) Subject: [pypy-svn] r62303 - pypy/trunk/pypy/module/_winreg Message-ID: <20090301170552.E616F1684E4@codespeak.net> Author: afa Date: Sun Mar 1 18:05:50 2009 New Revision: 62303 Modified: pypy/trunk/pypy/module/_winreg/__init__.py Log: Add _winreg.error = exceptions.WindowsError Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Sun Mar 1 18:05:50 2009 @@ -42,6 +42,7 @@ appleveldefs = { } interpleveldefs = { + 'error' : 'space.w_WindowsError', 'HKEYType' : 'interp_winreg.W_HKEY', 'SetValue' : 'interp_winreg.SetValue', 'SetValueEx' : 'interp_winreg.SetValueEx', From afa at codespeak.net Sun Mar 1 21:57:32 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 1 Mar 2009 21:57:32 +0100 (CET) Subject: [pypy-svn] r62305 - pypy/trunk/dotviewer Message-ID: <20090301205732.B43001684E4@codespeak.net> Author: afa Date: Sun Mar 1 21:57:29 2009 New Revision: 62305 Modified: pypy/trunk/dotviewer/graphparse.py Log: correctly call os.popen2. Relevant only on Windows. Modified: pypy/trunk/dotviewer/graphparse.py ============================================================================== --- pypy/trunk/dotviewer/graphparse.py (original) +++ pypy/trunk/dotviewer/graphparse.py Sun Mar 1 21:57:29 2009 @@ -45,7 +45,7 @@ else: cmdline = 'neato -Tplain' #print >> sys.stderr, '* running:', cmdline - child_in, child_out = os.popen2(cmdline, 'r') + child_in, child_out = os.popen2(cmdline, 'b') try: import thread except ImportError: From afa at codespeak.net Sun Mar 1 22:09:24 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 1 Mar 2009 22:09:24 +0100 (CET) Subject: [pypy-svn] r62308 - pypy/trunk/pypy/rpython/module Message-ID: <20090301210924.D97431684B6@codespeak.net> Author: afa Date: Sun Mar 1 22:09:22 2009 New Revision: 62308 Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py Log: Fix import, seen when running bin/py.py Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Sun Mar 1 22:09:22 2009 @@ -266,7 +266,7 @@ # Therefore, we implement our own stat, based on the Win32 API directly. from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo - from rlib import rwin32 + from pypy.rlib import rwin32 assert len(STAT_FIELDS) == 10 # no extra fields on Windows From fijal at codespeak.net Sun Mar 1 22:16:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 22:16:21 +0100 (CET) Subject: [pypy-svn] r62309 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090301211621.6D00A1684B6@codespeak.net> Author: fijal Date: Sun Mar 1 22:16:20 2009 New Revision: 62309 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Fix translation, try to have isstrartblock correct (it's still not though) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Sun Mar 1 22:16:20 2009 @@ -73,9 +73,13 @@ if isinstance(STRUCT, lltype.GcStruct): vtable = get_vtable_for_gcstruct(cpu, STRUCT) if vtable: - vt = cpu.cast_adr_to_int( - llmemory.cast_ptr_to_adr(vtable)) - cache[vt] = cpu.sizeof(STRUCT) + if not cpu.translate_support_code: + vt = cpu.cast_adr_to_int( + llmemory.cast_ptr_to_adr(vtable)) + cache[vt] = cpu.sizeof(STRUCT) + else: + vt = llmemory.cast_ptr_to_adr(vtable) + cache[vt] = cpu.sizeof(STRUCT) return cache testing_gcstruct2vtable = {} Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 22:16:20 2009 @@ -380,7 +380,6 @@ op = ResOperation(opnum, argboxes, resbox) self.operations.append(op) return op - record._annspecialcase_ = 'specialize:arg(4)' def generate_anything_since(self, old_index): return len(self.operations) > old_index @@ -391,7 +390,6 @@ class BlackHole(RunningMatcher): def record(self, step, argboxes, resbox): return None - record._annspecialcase_ = 'specialize:arg(4)' def generate_anything_since(self, old_index): return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Mar 1 22:16:20 2009 @@ -894,7 +894,11 @@ history = metainterp.history for vtable in storage.allocations: - sizebox = ConstInt(metainterp.class_sizes[vtable]) + if metainterp.cpu.translate_support_code: + vtable_addr = metainterp.cpu.cast_int_to_adr(vtable) + sizebox = ConstInt(metainterp.class_sizes[vtable_addr]) + else: + sizebox = ConstInt(metainterp.class_sizes[vtable]) vtablebox = ConstInt(vtable) instbox = history.execute_and_record(rop.NEW_WITH_VTABLE, [sizebox, vtablebox], Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Sun Mar 1 22:16:20 2009 @@ -4,7 +4,7 @@ from pypy.rpython.lltypesystem import rdict, rstr from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.translator.simplify import get_funcobj +from pypy.translator.simplify import get_funcobj, checkgraph, simplify_graph from pypy.translator.unsimplify import split_block from pypy.objspace.flow.model import Constant from pypy import conftest @@ -52,6 +52,7 @@ """Find the block with 'jit_merge_point' and split just before, making sure the input args are in the canonical order. """ + origstartblock = graph.startblock # split the block just before the jit_merge_point() if portalopindex > 0: link = split_block(None, portalblock, portalopindex) @@ -64,6 +65,12 @@ livevars = [v for v in portalop.args[2:] if v.concretetype is not lltype.Void] link = split_block(None, portalblock, 0, livevars) + if origstartblock != portalblock: + portalblock.isstartblock = True + origstartblock.isstartblock = False + graph.startblock = portalblock + simplify_graph(graph) + checkgraph(graph) return link.target def maybe_on_top_of_llinterp(rtyper, fnptr): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sun Mar 1 22:16:20 2009 @@ -6,7 +6,7 @@ from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache from pypy.objspace.flow.model import SpaceOperation, Variable, Constant from pypy.objspace.flow.model import checkgraph, Link, copygraph -from pypy.rlib.objectmodel import we_are_translated, UnboxedValue +from pypy.rlib.objectmodel import we_are_translated, UnboxedValue, specialize from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.jit import PARAMETERS from pypy.rlib.rarithmetic import r_uint @@ -105,11 +105,14 @@ translate_support_code=False, **kwds): opt = Options(**kwds) self.stats = history.Stats() - cpu = CPUClass(self.translator.rtyper, self.stats, - translate_support_code) - self.cpu = cpu if translate_support_code: self.annhelper = MixLevelHelperAnnotator(self.translator.rtyper) + annhelper = self.annhelper + else: + annhelper = None + cpu = CPUClass(self.translator.rtyper, self.stats, + translate_support_code, annhelper) + self.cpu = cpu graphs = self.translator.graphs self.jit_merge_point_pos = find_jit_merge_point(graphs) graph, block, pos = self.jit_merge_point_pos @@ -348,7 +351,8 @@ jitdriver = warmrunnerdesc.jitdriver num_green_args = len(jitdriver.greens) warmrunnerdesc.num_green_args = num_green_args - green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) + green_args_spec = unrolling_iterable( + list(enumerate(warmrunnerdesc.green_args_spec))) green_args_names = unrolling_iterable(jitdriver.greens) if num_green_args: MAX_HASH_TABLE_BITS = 28 @@ -461,17 +465,20 @@ return self.compile(argshash, *args) handle_hash_collision._dont_inline_ = True + @specialize.arg(2) + def _get_hash_part(self, greenargs, i, TYPE, result): + item = greenargs[i] + return result ^ cast_whatever_to_int(TYPE, item) + def getkeyhash(self, *greenargs): result = r_uint(0x345678) i = 0 mult = r_uint(1000003) - for TYPE in green_args_spec: + for i, TYPE in green_args_spec: if i > 0: result = result * mult mult = mult + 82520 + 2*len(greenargs) - item = greenargs[i] - result = result ^ cast_whatever_to_int(TYPE, item) - i += 1 + result = self._get_hash_part(greenargs, i, TYPE, result) return result getkeyhash._always_inline_ = True From fijal at codespeak.net Sun Mar 1 22:17:02 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 22:17:02 +0100 (CET) Subject: [pypy-svn] r62310 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090301211702.57EB41684E4@codespeak.net> Author: fijal Date: Sun Mar 1 22:17:01 2009 New Revision: 62310 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py Log: Make the first zrpy_slist test run, provided that checkgraph is not called Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Sun Mar 1 22:17:01 2009 @@ -1,2 +1,17 @@ -* Kill hack for .position attr of modrm +* Kill hack for .position attr of modrm (there is a method for that as well, + unsure what's saner) + +* SETO vs CMOVO + +* test_zrpy_exceptions, needed + +* fix ll2ctypes for typeptr accesses (test_tl*) + +* measure performance, improve + +* use more registers, eventually + +* optimization of comparison followed by a guard + +* MC_SIZE, FRAMESIZE Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sun Mar 1 22:17:01 2009 @@ -16,26 +16,38 @@ from pypy.jit.metainterp.resoperation import rop # our calling convention - we pass three first args as edx, ecx and eax -# and the rest stays on stack +# and the rest stays on the stack class Assembler386(object): MC_SIZE = 1024*1024 # 1MB, but assumed infinite for now + generic_return_addr = 0 + position = -1 - def __init__(self, cpu): + def __init__(self, cpu, translate_support_code=False): self.cpu = cpu self.verbose = False self.mc = None self.mc2 = None self.rtyper = cpu.rtyper self.malloc_func_addr = 0 - self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, - zero=True, flavor='raw') - self._exception_addr = cpu.cast_ptr_to_int(self._exception_data) + if translate_support_code: + self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) + self._exception_addr = 0 + # patched later, after exc transform + else: + self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, + zero=True, flavor='raw') + self._exception_addr = cpu.cast_ptr_to_int(self._exception_data) def make_sure_mc_exists(self): if self.mc is None: # we generate the loop body in 'mc' # 'mc2' is for guard recovery code + # XXX we should catch the real one, somehow + self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, + zero=True, flavor='raw') + self._exception_addr = self.cpu.cast_ptr_to_int( + self._exception_data) self.mc = codebuf.MachineCodeBlock(self.MC_SIZE) self.mc2 = codebuf.MachineCodeBlock(self.MC_SIZE) self.generic_return_addr = self.assemble_generic_return() @@ -52,9 +64,10 @@ self.make_sure_mc_exists() op0 = operations[0] op0.position = self.mc.tell() - self._regalloc = RegAlloc(operations, guard_op) # for debugging - self.max_stack_depth = self._regalloc.current_stack_depth - computed_ops = self._regalloc.computed_ops + regalloc = RegAlloc(operations, guard_op) + if not we_are_translated(): + self._regalloc = regalloc # for debugging + computed_ops = regalloc.computed_ops if guard_op is not None: new_rel_addr = self.mc.tell() - guard_op._jmp_from TP = rffi.CArrayPtr(lltype.Signed) @@ -313,6 +326,7 @@ def genop_getfield_gc(self, op, arglocs, resloc): base_loc, ofs_loc, size_loc = arglocs + assert isinstance(size_loc, IMM32) size = size_loc.value if size == 1: self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc)) @@ -323,12 +337,15 @@ def genop_getarrayitem_gc(self, op, arglocs, resloc): base_loc, ofs_loc, scale, ofs = arglocs + assert isinstance(ofs, IMM32) + assert isinstance(scale, IMM32) self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, ofs.value, scale.value)) genop_getfield_raw = genop_getfield_gc def genop_setfield_gc(self, op, arglocs): base_loc, ofs_loc, size_loc, value_loc = arglocs + assert isinstance(size_loc, IMM32) size = size_loc.value if size == WORD: self.mc.MOV(addr_add(base_loc, ofs_loc), value_loc) @@ -342,6 +359,8 @@ def genop_setarrayitem_gc(self, op, arglocs): base_loc, ofs_loc, value_loc, scale_loc, baseofs = arglocs + assert isinstance(baseofs, IMM32) + assert isinstance(scale_loc, IMM32) self.mc.MOV(addr_add(base_loc, ofs_loc, baseofs.value, scale_loc.value), value_loc) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 1 22:17:01 2009 @@ -4,7 +4,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory, ll2ctypes, rffi from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize from pypy.rlib.objectmodel import we_are_translated, keepalive_until_here from pypy.annotation import model as annmodel @@ -23,12 +22,14 @@ lltype.Ptr(rffi.CArray(lltype.Signed))], lltype.Signed) - def __init__(self, rtyper, stats, translate_support_code=False): + def __init__(self, rtyper, stats, translate_support_code=False, + mixlevelann=None): self.rtyper = rtyper self.stats = stats self.translate_support_code = translate_support_code if translate_support_code: - self.mixlevelann = MixLevelHelperAnnotator(rtyper) + assert mixlevelann + self.mixlevelann = mixlevelann else: self.current_interpreter = LLInterpreter(self.rtyper) @@ -53,16 +54,21 @@ self._setup_ovf_error() def _setup_ovf_error(self): - bk = self.rtyper.annotator.bookkeeper - clsdef = bk.getuniqueclassdef(OverflowError) - ovferror_repr = rclass.getclassrepr(self.rtyper, clsdef) - ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance( - self.rtyper, clsdef) - self._ovf_error_vtable = self.cast_ptr_to_int(ll_inst.typeptr) - self._ovf_error_inst = self.cast_ptr_to_int(ll_inst) + if self.translate_support_code: + self._ovf_error_vtable = 0 + self._ovf_error_inst = 0 + # do something here + else: + bk = self.rtyper.annotator.bookkeeper + clsdef = bk.getuniqueclassdef(OverflowError) + ovferror_repr = rclass.getclassrepr(self.rtyper, clsdef) + ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance( + self.rtyper, clsdef) + self._ovf_error_vtable = self.cast_ptr_to_int(ll_inst.typeptr) + self._ovf_error_inst = self.cast_ptr_to_int(ll_inst) def setup(self): - self.assembler = Assembler386(self) + self.assembler = Assembler386(self, self.translate_support_code) # the generic assembler stub that just performs a return if self.translate_support_code: mixlevelann = self.mixlevelann @@ -141,35 +147,37 @@ def execute_operation(self, opnum, valueboxes, result_type): # mostly a hack: fall back to compiling and executing the single # operation. - key = [opnum, result_type] + key = [] for valuebox in valueboxes: if isinstance(valuebox, Box): key.append(valuebox.type) else: - key.append(repr(valuebox)) # XXX not RPython - mp = self.get_compiled_single_operation(key, valueboxes) + key.append(str(valuebox.get_())) + mp = self.get_compiled_single_operation(opnum, result_type, + key, valueboxes) res = self.execute_operations_in_new_frame(opname[opnum], mp, valueboxes, result_type) - if self.assembler._exception_data[0] != 0: - TP = lltype.Ptr(rclass.OBJECT_VTABLE) - TP_V = lltype.Ptr(rclass.OBJECT) - exc_t_a = self.cast_int_to_adr(self.get_exception(None)) - exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) - exc_v_a = self.get_exc_value(None) - exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) - # clean up the exception - self.assembler._exception_data[0] = 0 - raise LLException(exc_type, exc_val) + if not self.translate_support_code: + if self.assembler._exception_data[0] != 0: + TP = lltype.Ptr(rclass.OBJECT_VTABLE) + TP_V = lltype.Ptr(rclass.OBJECT) + exc_t_a = self.cast_int_to_adr(self.get_exception(None)) + exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) + exc_v_a = self.get_exc_value(None) + exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) + # clean up the exception + self.assembler._exception_data[0] = 0 + raise LLException(exc_type, exc_val) + # otherwise exception data is set correctly, no problem at all return res - def get_compiled_single_operation(self, key, valueboxes): - real_key = ','.join([str(k) for k in key]) + def get_compiled_single_operation(self, opnum, result_type, key, + valueboxes): + real_key = '%d,%s' % (opnum, result_type) + ','.join(key) try: return self._compiled_ops[real_key] except KeyError: - opnum = key[0] - result_type = key[1] livevarlist = [] i = 0 # clonebox below is necessary, because sometimes we know Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Sun Mar 1 22:17:01 2009 @@ -3,7 +3,10 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import we_are_translated from pypy.translator.c.test.test_genc import compile +from pypy.rpython.annlowlevel import llhelper +from pypy.jit.metainterp.history import log, ConstAddr import ctypes +import py GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) @@ -33,9 +36,26 @@ from pypy.translator.translator import TranslationContext from pypy.jit.metainterp.warmspot import WarmRunnerDesc from pypy.jit.backend.x86.runner import CPU386 + from pypy.translator.c.genc import CStandaloneBuilder as CBuilder + from pypy.annotation.listdef import s_list_of_strings + from pypy.annotation import model as annmodel + for arg in args: + assert isinstance(arg, int) + + ConstAddr.ever_seen = False + t = TranslationContext() t.config.translation.gc = 'boehm' + src = py.code.Source(""" + def entry_point(argv): + args = (%s,) + res = function(*args) + print res + return 0 + """ % (", ".join(['int(argv[%d])' % (i + 1) for i in range(len(args))]),)) + exec src.compile() in locals() + t.buildannotator().build_types(function, [int] * len(args)) t.buildrtyper().specialize() warmrunnerdesc = WarmRunnerDesc(t, translate_support_code=True, @@ -43,5 +63,16 @@ **kwds) warmrunnerdesc.state.set_param_threshold(3) # for tests warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests + mixlevelann = warmrunnerdesc.annhelper + entry_point_graph = mixlevelann.getgraph(entry_point, [s_list_of_strings], + annmodel.SomeInteger()) warmrunnerdesc.finish() - + # XXX patch exceptions + cbuilder = CBuilder(t, entry_point, config=t.config) + cbuilder.generate_source() + exe_name = cbuilder.compile() + log('---------- Test starting ----------') + stdout = cbuilder.cmdexec(" ".join([str(arg) for arg in args])) + res = int(stdout) + log('---------- Test done (%d) ----------' % (res,)) + return res Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py Sun Mar 1 22:17:01 2009 @@ -3,4 +3,6 @@ from pypy.jit.backend.x86.test.test_basic import Jit386Mixin class TestSList(Jit386Mixin, ListTests): + # for the individual tests see + # ====> ../../../metainterp/test/test_slist.py pass From fijal at codespeak.net Sun Mar 1 22:19:16 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Mar 2009 22:19:16 +0100 (CET) Subject: [pypy-svn] r62311 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090301211916.1F5971684E4@codespeak.net> Author: fijal Date: Sun Mar 1 22:19:15 2009 New Revision: 62311 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Log: reuse annmixlevel Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sun Mar 1 22:19:15 2009 @@ -14,7 +14,8 @@ class CPU(object): - def __init__(self, rtyper, stats=None, translate_support_code=False): + def __init__(self, rtyper, stats=None, translate_support_code=False, + annmixlevel=None): self.rtyper = rtyper self.translate_support_code = translate_support_code self.jumptarget2loop = {} @@ -27,8 +28,7 @@ llimpl._stats = self.stats llimpl._rtyper = self.rtyper if translate_support_code: - from pypy.rpython.annlowlevel import MixLevelHelperAnnotator - self.mixlevelann = MixLevelHelperAnnotator(self.rtyper) + self.mixlevelann = annmixlevel def set_meta_interp(self, metainterp): self.metainterp = metainterp # to handle guard failures From afa at codespeak.net Sun Mar 1 22:22:46 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 1 Mar 2009 22:22:46 +0100 (CET) Subject: [pypy-svn] r62312 - in pypy/trunk/pypy: interpreter interpreter/astcompiler objspace/flow/test tool Message-ID: <20090301212246.B41E5168558@codespeak.net> Author: afa Date: Sun Mar 1 22:22:45 2009 New Revision: 62312 Modified: pypy/trunk/pypy/interpreter/astcompiler/pyassem.py pypy/trunk/pypy/interpreter/pyopcode.py pypy/trunk/pypy/objspace/flow/test/test_objspace.py pypy/trunk/pypy/tool/stdlib_opcode.py Log: Some progress towards supporting CPython2.6 for the pypy toolchain: the Flow Object Space is allowed to interpret the new 2.6 bytecodes. I hope I understand the "we_are_translated()" stuff correctly; and what about applevel code? Modified: pypy/trunk/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/pyassem.py Sun Mar 1 22:22:45 2009 @@ -535,6 +535,7 @@ 'DELETE_GLOBAL': 0, 'STORE_DEREF': -1, 'BUILD_MAP': 1, + 'STORE_MAP': -2, 'COMPARE_OP': -1, 'STORE_FAST': -1, 'DELETE_FAST': 0, Modified: pypy/trunk/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/trunk/pypy/interpreter/pyopcode.py (original) +++ pypy/trunk/pypy/interpreter/pyopcode.py Sun Mar 1 22:22:45 2009 @@ -699,12 +699,26 @@ w_list = f.space.newlist(items) f.pushvalue(w_list) - def BUILD_MAP(f, zero, *ignored): - if zero != 0: - raise BytecodeCorruption + def BUILD_MAP(f, itemcount, *ignored): + if not we_are_translated() and sys.version_info >= (2, 6): + # We could pre-allocate a dict here + # but for the moment this code is not translated. + pass + else: + if itemcount != 0: + raise BytecodeCorruption w_dict = f.space.newdict() f.pushvalue(w_dict) + def STORE_MAP(f, zero, *ignored): + if not we_are_translated() and sys.version_info >= (2, 6): + w_key = f.popvalue() + w_value = f.popvalue() + w_dict = f.peekvalue() + f.space.setitem(w_dict, w_key, w_value) + else: + raise BytecodeCorruption + def LOAD_ATTR(f, nameindex, *ignored): "obj.attributename" w_attributename = f.getname_w(nameindex) Modified: pypy/trunk/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/trunk/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/trunk/pypy/objspace/flow/test/test_objspace.py Sun Mar 1 22:22:45 2009 @@ -469,6 +469,14 @@ x = self.codetest(self.globalconstdict) #__________________________________________________________ + def dictliteral(name): + x = {'x': 1} + return x + + def test_dictliteral(self): + x = self.codetest(self.dictliteral) + + #__________________________________________________________ def specialcases(x): operator.lt(x,3) Modified: pypy/trunk/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/trunk/pypy/tool/stdlib_opcode.py (original) +++ pypy/trunk/pypy/tool/stdlib_opcode.py Sun Mar 1 22:22:45 2009 @@ -74,4 +74,10 @@ lst.sort() unrolling_opcode_descs = unrolling_iterable(lst) +# Allow non-translated code to interpret the new 2.6 bytecodes +import sys +if sys.version_info >= (2, 6): + import opcode + opcode_method_names[opcode.opmap['STORE_MAP']] = 'STORE_MAP' + del name, index, desc, lst From afa at codespeak.net Mon Mar 2 01:10:32 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 2 Mar 2009 01:10:32 +0100 (CET) Subject: [pypy-svn] r62314 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090302001032.D673516847A@codespeak.net> Author: afa Date: Mon Mar 2 01:10:29 2009 New Revision: 62314 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: Port most of the _locale module to windows Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Mon Mar 2 01:10:29 2009 @@ -1,4 +1,5 @@ from pypy.interpreter.mixedmodule import MixedModule +from pypy.module._locale import interp_locale class Module(MixedModule): """Support for POSIX locales.""" @@ -9,14 +10,21 @@ 'strcoll': 'interp_locale.strcoll', 'strxfrm': 'interp_locale.strxfrm', #'getdefaultlocale': 'interp_locale.getdefaultlocale', + } + + if interp_locale.HAVE_LANGINFO: + interpleveldefs.update({ + 'nl_langinfo': 'interp_locale.nl_langinfo', + }) + if interp_locale.HAVE_LIBINTL: + interpleveldefs.update({ 'gettext': 'interp_locale.gettext', 'dgettext': 'interp_locale.dgettext', 'dcgettext': 'interp_locale.dcgettext', 'textdomain': 'interp_locale.textdomain', - 'nl_langinfo': 'interp_locale.nl_langinfo', 'bindtextdomain': 'interp_locale.bindtextdomain', 'bind_textdomain_codeset': 'interp_locale.bind_textdomain_codeset', - } + }) appleveldefs = { 'Error': 'app_locale.Error', @@ -24,7 +32,6 @@ } def buildloaders(cls): - from pypy.module._locale import interp_locale for constant, value in interp_locale.constants.iteritems(): Module.interpleveldefs[constant] = "space.wrap(%r)" % value super(Module, cls).buildloaders() Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Mon Mar 2 01:10:29 2009 @@ -7,9 +7,17 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo +import sys + +HAVE_LANGINFO = sys.platform != 'win32' +HAVE_LIBINTL = sys.platform != 'win32' + class CConfig: + includes = ['locale.h', 'limits.h'] + if HAVE_LANGINFO: + includes += ['langinfo.h'] _compilation_info_ = ExternalCompilationInfo( - includes = ['locale.h', 'langinfo.h', 'limits.h'] + includes=includes, ) lconv = platform.Struct("struct lconv", [ # Numeric (non-monetary) information. Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Mon Mar 2 01:10:29 2009 @@ -6,6 +6,14 @@ class AppTestLocaleTrivia: def setup_class(cls): cls.space = gettestobjspace(usemodules=['_locale']) + if sys.platform != 'win32': + cls.w_language_en = cls.space.wrap("en_US") + cls.w_language_utf8 = cls.space.wrap("en_US.UTF-8") + cls.w_language_pl = cls.space.wrap("pl_PL") + else: + cls.w_language_en = cls.space.wrap("English_US") + cls.w_language_utf8 = cls.space.wrap("English_US.65001") + cls.w_language_pl = cls.space.wrap("Polish_Poland") def test_import(self): import _locale @@ -14,22 +22,24 @@ import locale assert locale - def test_contants(self): + def test_constants(self): _CONSTANTS = ( 'LC_CTYPE', 'LC_NUMERIC', 'LC_TIME', 'LC_COLLATE', 'LC_MONETARY', - 'LC_MESSAGES', 'LC_ALL', - 'LC_PAPER', - 'LC_NAME', - 'LC_ADDRESS', - 'LC_TELEPHONE', - 'LC_MEASUREMENT', - 'LC_IDENTIFICATION', 'CHAR_MAX', + + # These are optional + #'LC_MESSAGES', + #'LC_PAPER', + #'LC_NAME', + #'LC_ADDRESS', + #'LC_TELEPHONE', + #'LC_MEASUREMENT', + #'LC_IDENTIFICATION', ) import _locale @@ -40,9 +50,9 @@ def test_setlocale(self): import _locale - raises(TypeError, _locale.setlocale, "", "en_US") + raises(TypeError, _locale.setlocale, "", self.language_en) raises(TypeError, _locale.setlocale, _locale.LC_ALL, 6) - raises(_locale.Error, _locale.setlocale, 123456, "en_US") + raises(_locale.Error, _locale.setlocale, 123456, self.language_en) assert _locale.setlocale(_locale.LC_ALL, None) assert _locale.setlocale(_locale.LC_ALL) @@ -53,11 +63,11 @@ lcase = "abcdefghijklmnopqrstuvwxyz" ucase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - _locale.setlocale(_locale.LC_ALL, "en_US.UTF-8") + _locale.setlocale(_locale.LC_ALL, self.language_utf8) assert string.lowercase == lcase assert string.uppercase == ucase - _locale.setlocale(_locale.LC_ALL, "en_US") + _locale.setlocale(_locale.LC_ALL, self.language_en) assert string.lowercase != lcase assert string.uppercase != ucase @@ -94,7 +104,7 @@ def test_strcoll(self): import _locale - _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + _locale.setlocale(_locale.LC_ALL, self.language_pl) assert _locale.strcoll("a", "b") < 0 assert _locale.strcoll("?", "b") < 0 @@ -109,7 +119,7 @@ def test_strcoll_unicode(self): import _locale - _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + _locale.setlocale(_locale.LC_ALL, self.language_pl) assert _locale.strcoll(u"b", u"b") == 0 assert _locale.strcoll(u"a", u"b") < 0 assert _locale.strcoll(u"b", u"a") > 0 @@ -129,7 +139,7 @@ raises(TypeError, _locale.strxfrm, 1) - _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + _locale.setlocale(_locale.LC_ALL, self.language_pl) a = "1234" b = _locale.strxfrm(a) assert a is not b @@ -138,12 +148,16 @@ import _locale import locale - _locale.setlocale(_locale.LC_ALL, "en_US.UTF-8") + _locale.setlocale(_locale.LC_ALL, self.language_en) assert locale.str(1.1) == '1.1' - _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + _locale.setlocale(_locale.LC_ALL, self.language_pl) assert locale.str(1.1) == '1,1' def test_text(self): + import sys + if sys.platform == 'win32': + skip("No gettext on Windows") + # TODO more tests would be nice import _locale @@ -153,6 +167,10 @@ assert _locale.textdomain("1234") == "1234" def test_nl_langinfo(self): + import sys + if sys.platform == 'win32': + skip("No langinfo on Windows") + import _locale langinfo_consts = [ @@ -221,6 +239,10 @@ raises(TypeError, _locale.nl_langinfo, None) def test_bindtextdomain(self): + import sys + if sys.platform == 'win32': + skip("No textdomain on Windows") + # TODO more tests would be nice import _locale @@ -228,6 +250,10 @@ raises(OSError, _locale.bindtextdomain, '', '1') def test_bind_textdomain_codeset(self): + import sys + if sys.platform == 'win32': + skip("No textdomain on Windows") + import _locale assert _locale.bind_textdomain_codeset('/', None) is None From fijal at codespeak.net Mon Mar 2 10:32:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Mar 2009 10:32:38 +0100 (CET) Subject: [pypy-svn] r62316 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090302093238.D3B15168442@codespeak.net> Author: fijal Date: Mon Mar 2 10:32:36 2009 New Revision: 62316 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: fix test Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Mon Mar 2 10:32:36 2009 @@ -335,6 +335,8 @@ self.history = FakeHistory() self.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): E.size_of_node} + self.cpu = cpu + self.cpu.translate_support_code = False spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() From fijal at codespeak.net Mon Mar 2 10:36:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Mar 2009 10:36:17 +0100 (CET) Subject: [pypy-svn] r62317 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090302093617.C6E87168448@codespeak.net> Author: fijal Date: Mon Mar 2 10:36:17 2009 New Revision: 62317 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Log: Remove this as it mostly invokes interp_operations, which we don't want to run translated I think Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Mon Mar 2 10:36:17 2009 @@ -50,6 +50,3 @@ pass def check_jumps(self, maxcount): pass - -class TestLLBasic(test_basic.BasicTests, LLInterpJitMixin): - pass From fijal at codespeak.net Mon Mar 2 10:50:02 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Mar 2009 10:50:02 +0100 (CET) Subject: [pypy-svn] r62322 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090302095002.9A1ED168455@codespeak.net> Author: fijal Date: Mon Mar 2 10:50:02 2009 New Revision: 62322 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: fight blocked blocks Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Mon Mar 2 10:50:02 2009 @@ -82,7 +82,7 @@ return imm(c.value) elif isinstance(c, ConstPtr): return imm(rffi.cast(lltype.Signed, c.value)) - elif isinstance(c, ConstAddr): + elif ConstAddr.ever_seen and isinstance(c, ConstAddr): return imm(ll2ctypes.cast_adr_to_int(c.value)) else: raise ValueError("convert_to_imm: got a %s" % c) From arigo at codespeak.net Mon Mar 2 10:58:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 10:58:10 +0100 (CET) Subject: [pypy-svn] r62324 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090302095810.B4F2F1684BD@codespeak.net> Author: arigo Date: Mon Mar 2 10:58:08 2009 New Revision: 62324 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Undo a small bit of r62309. The real culprit was "i += 1", which unlike "i = i + 1" is not considered as giving a constant by the flow space. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Mon Mar 2 10:58:08 2009 @@ -351,8 +351,7 @@ jitdriver = warmrunnerdesc.jitdriver num_green_args = len(jitdriver.greens) warmrunnerdesc.num_green_args = num_green_args - green_args_spec = unrolling_iterable( - list(enumerate(warmrunnerdesc.green_args_spec))) + green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) green_args_names = unrolling_iterable(jitdriver.greens) if num_green_args: MAX_HASH_TABLE_BITS = 28 @@ -465,20 +464,17 @@ return self.compile(argshash, *args) handle_hash_collision._dont_inline_ = True - @specialize.arg(2) - def _get_hash_part(self, greenargs, i, TYPE, result): - item = greenargs[i] - return result ^ cast_whatever_to_int(TYPE, item) - def getkeyhash(self, *greenargs): result = r_uint(0x345678) i = 0 mult = r_uint(1000003) - for i, TYPE in green_args_spec: + for TYPE in green_args_spec: if i > 0: result = result * mult mult = mult + 82520 + 2*len(greenargs) - result = self._get_hash_part(greenargs, i, TYPE, result) + item = greenargs[i] + result = result ^ cast_whatever_to_int(TYPE, item) + i = i + 1 return result getkeyhash._always_inline_ = True From arigo at codespeak.net Mon Mar 2 11:22:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 11:22:38 +0100 (CET) Subject: [pypy-svn] r62327 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/x86 metainterp Message-ID: <20090302102238.6372B1684E7@codespeak.net> Author: arigo Date: Mon Mar 2 11:22:36 2009 New Revision: 62327 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: Kill the ever_seen hack and replace it with another (but one-liner) hack. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Mon Mar 2 11:22:36 2009 @@ -68,8 +68,7 @@ llimpl.compile_add_int_const(c, x.value) elif isinstance(x, history.ConstPtr): llimpl.compile_add_ptr_const(c, x.value) - elif (history.ConstAddr.ever_seen and - isinstance(x, history.ConstAddr)): + elif isinstance(x, history.ConstAddr): llimpl.compile_add_int_const(c, x.getint()) else: raise Exception("%s args contain: %r" % (op.getopname(), @@ -232,8 +231,7 @@ llimpl.frame_int_setvalue(frame, argindex, valuebox.value) elif isinstance(valuebox, history.ConstPtr): llimpl.frame_ptr_setvalue(frame, argindex, valuebox.value) - elif (history.ConstAddr.ever_seen and - isinstance(valuebox, history.ConstAddr)): + elif isinstance(valuebox, history.ConstAddr): llimpl.frame_int_setvalue(frame, argindex, valuebox.getint()) else: raise AssertionError('setvalue: valuebox = %s' % (valuebox,)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Mon Mar 2 11:22:36 2009 @@ -82,7 +82,7 @@ return imm(c.value) elif isinstance(c, ConstPtr): return imm(rffi.cast(lltype.Signed, c.value)) - elif ConstAddr.ever_seen and isinstance(c, ConstAddr): + elif isinstance(c, ConstAddr): return imm(ll2ctypes.cast_adr_to_int(c.value)) else: raise ValueError("convert_to_imm: got a %s" % c) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Mon Mar 2 11:22:36 2009 @@ -243,7 +243,7 @@ elif isinstance(box, ConstPtr): self.keepalives.append(box.value) return self.cast_gcref_to_int(box.value) - elif ConstAddr.ever_seen and isinstance(box, ConstAddr): + elif isinstance(box, ConstAddr): return self.cast_adr_to_int(box.value) else: raise ValueError('get_box_value_as_int, wrong arg') Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Mon Mar 2 11:22:36 2009 @@ -43,8 +43,6 @@ for arg in args: assert isinstance(arg, int) - ConstAddr.ever_seen = False - t = TranslationContext() t.config.translation.gc = 'boehm' src = py.code.Source(""" Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Mon Mar 2 11:22:36 2009 @@ -86,6 +86,8 @@ graph = self.unfinished_graphs.pop() self.make_one_bytecode(graph, False) log.info("there are %d JitCode instances." % len(self.all_graphs)) + # xxx annotation hack: make sure there is at least one ConstAddr around + jitcode.constants.append(history.ConstAddr(llmemory.NULL, self.cpu)) return jitcode def make_one_bytecode(self, graph, portal): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Mon Mar 2 11:22:36 2009 @@ -148,11 +148,9 @@ class ConstAddr(Const): # only for constants built before translation type = 'int' - ever_seen = False def __init__(self, adrvalue, cpu): "NOT_RPYTHON" - self.__class__.ever_seen = True assert not we_are_translated() if isinstance(lltype.typeOf(adrvalue), lltype.Ptr): adrvalue = llmemory.cast_ptr_to_adr(adrvalue) # convenience From arigo at codespeak.net Mon Mar 2 11:40:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 11:40:44 +0100 (CET) Subject: [pypy-svn] r62331 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090302104044.283B21684E9@codespeak.net> Author: arigo Date: Mon Mar 2 11:40:43 2009 New Revision: 62331 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_exception.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: A new test, and a fix for a translation issue. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Mon Mar 2 11:40:43 2009 @@ -565,10 +565,12 @@ @arguments("int") def opimpl_put_last_exception(self, index): + assert index >= 0 self.env.insert(index, self.exception_box) @arguments("int") def opimpl_put_last_exc_value(self, index): + assert index >= 0 self.env.insert(index, self.exc_value_box) @arguments() Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_exception.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_exception.py Mon Mar 2 11:40:43 2009 @@ -0,0 +1,19 @@ +import py +from pypy.jit.metainterp.test import test_exception +from pypy.jit.metainterp.test.test_zrpy_basic import LLInterpJitMixin + + +class TestLLExceptions(test_exception.ExceptionTests, LLInterpJitMixin): + def interp_operations(self, *args, **kwds): + py.test.skip("uses interp_operations()") + + # ==========> test_exception.py + + def test_raise(self): skip1() + def test_raise_through(self): skip1() + def test_raise_through_wrong_exc(self): skip1() + def test_raise_through_wrong_exc_2(self): skip1() + + +def skip1(): + py.test.skip("the portal always raises, causing blocked blocks") From arigo at codespeak.net Mon Mar 2 12:06:08 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 12:06:08 +0100 (CET) Subject: [pypy-svn] r62340 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090302110608.31B8C1684E7@codespeak.net> Author: arigo Date: Mon Mar 2 12:06:07 2009 New Revision: 62340 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Undo another small bit of r62309 and do it "right". Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Mon Mar 2 12:06:07 2009 @@ -4,7 +4,7 @@ from pypy.rpython.lltypesystem import rdict, rstr from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.translator.simplify import get_funcobj, checkgraph, simplify_graph +from pypy.translator.simplify import get_funcobj from pypy.translator.unsimplify import split_block from pypy.objspace.flow.model import Constant from pypy import conftest @@ -52,7 +52,6 @@ """Find the block with 'jit_merge_point' and split just before, making sure the input args are in the canonical order. """ - origstartblock = graph.startblock # split the block just before the jit_merge_point() if portalopindex > 0: link = split_block(None, portalblock, portalopindex) @@ -65,12 +64,6 @@ livevars = [v for v in portalop.args[2:] if v.concretetype is not lltype.Void] link = split_block(None, portalblock, 0, livevars) - if origstartblock != portalblock: - portalblock.isstartblock = True - origstartblock.isstartblock = False - graph.startblock = portalblock - simplify_graph(graph) - checkgraph(graph) return link.target def maybe_on_top_of_llinterp(rtyper, fnptr): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Mon Mar 2 12:06:07 2009 @@ -117,8 +117,11 @@ self.jit_merge_point_pos = find_jit_merge_point(graphs) graph, block, pos = self.jit_merge_point_pos graph = copygraph(graph) + graph.startblock.isstartblock = False graph.startblock = support.split_before_jit_merge_point( *find_jit_merge_point([graph])) + graph.startblock.isstartblock = True + checkgraph(graph) for v in graph.getargs(): assert isinstance(v, Variable) assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs()) From arigo at codespeak.net Mon Mar 2 12:07:50 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 12:07:50 +0100 (CET) Subject: [pypy-svn] r62341 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090302110750.3704E1684E9@codespeak.net> Author: arigo Date: Mon Mar 2 12:07:46 2009 New Revision: 62341 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_exception.py (contents, props changed) Log: Port test_zrpy_exception to the x86 backend. Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_exception.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_exception.py Mon Mar 2 12:07:46 2009 @@ -0,0 +1,15 @@ + +import py +from pypy.jit.metainterp.test import test_zrpy_exception +from pypy.jit.backend.x86.support import c_meta_interp + +class Jit386Mixin(object): + @staticmethod + def meta_interp(fn, args, **kwds): + return c_meta_interp(fn, args, **kwds) + +class TestException(Jit386Mixin, test_zrpy_exception.TestLLExceptions): + # for the individual tests see + # ====> ../../../metainterp/test/test_exception.py + pass + From cfbolz at codespeak.net Mon Mar 2 14:25:33 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Mar 2009 14:25:33 +0100 (CET) Subject: [pypy-svn] r62371 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090302132533.1E9AE1684BD@codespeak.net> Author: cfbolz Date: Mon Mar 2 14:25:32 2009 New Revision: 62371 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Log: make W_WordObjects use unsigned integers Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py Mon Mar 2 14:25:32 2009 @@ -16,7 +16,7 @@ """ import sys from pypy.rlib import rrandom, objectmodel -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint from pypy.lang.smalltalk import constants, error from pypy.tool.pairtype import extendabletype from pypy.rlib.objectmodel import instantiate @@ -392,25 +392,14 @@ class W_WordsObject(W_AbstractObjectWithClassReference): def __init__(self, w_class, size): W_AbstractObjectWithClassReference.__init__(self, w_class) - self.words = [0] * size + self.words = [r_uint(0)] * size def at0(self, space, index0): val = self.getword(index0) - return space.wrap_pos_full_int(val) + return space.wrap_uint(val) def atput0(self, space, index0, w_value): - if isinstance(w_value, W_BytesObject): - # TODO: Completely untested! This failed translation bigtime... - # XXX Probably we want to allow all subclasses - if not (w_value.getclass(space).is_same_object( - space.w_LargePositiveInteger) and - w_value.size() == 4): - raise error.UnwrappingError("Failed to convert bytes to word") - word = 0 - for i in range(4): - word += ord(w_value.getchar(i)) << 8*i - else: - word = space.unwrap_int(w_value) + word = space.unwrap_uint(w_value) self.setword(index0, word) def getword(self, n): Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py Mon Mar 2 14:25:32 2009 @@ -1,8 +1,9 @@ from pypy.lang.smalltalk import constants from pypy.lang.smalltalk import model from pypy.lang.smalltalk import shadow -from pypy.rlib.objectmodel import instantiate from pypy.lang.smalltalk.error import UnwrappingError, WrappingError +from pypy.rlib.objectmodel import instantiate +from pypy.rlib.rarithmetic import intmask, r_uint class ObjSpace(object): def __init__(self): @@ -163,17 +164,18 @@ return model.W_SmallInteger(val) raise WrappingError("integer too large to fit into a tagged pointer") - def wrap_pos_full_int(self, val): + def wrap_uint(self, val): if val < 0: raise WrappingError("negative integer") - try: - return self.wrap_int(val) - except WrappingError: - pass + if intmask(val) > 0: + try: + return self.wrap_int(intmask(val)) + except WrappingError: + pass # XXX this is not really working well on 64 bit machines w_result = model.W_BytesObject(self.classtable['w_LargePositiveInteger'], 4) for i in range(4): - w_result.setchar(i, chr((val >> i*8) & 255)) + w_result.setchar(i, chr(intmask((val >> i*8) & 255))) return w_result def wrap_float(self, i): @@ -196,7 +198,7 @@ def wrap_list(self, lst_w): """ - Converts a Python list of wrapper objects into + Converts a Python list of wrapped objects into a wrapped smalltalk array """ lstlen = len(lst_w) @@ -210,6 +212,26 @@ return w_value.value raise UnwrappingError("expected a W_SmallInteger, got %s" % (w_value,)) + def unwrap_uint(self, w_value): + if isinstance(w_value, model.W_SmallInteger): + val = w_value.value + if val < 0: + raise UnwrappingError("got negative integer") + return w_value.value + if isinstance(w_value, model.W_BytesObject): + # TODO: Completely untested! This failed translation bigtime... + # XXX Probably we want to allow all subclasses + if not (w_value.getclass(self).is_same_object( + self.w_LargePositiveInteger) and + w_value.size() == 4): + raise UnwrappingError("Failed to convert bytes to word") + word = 0 + for i in range(4): + word += r_uint(ord(w_value.getchar(i))) << 8*i + return word + else: + raise UnwrappingError("Got unexpected class in unwrap_uint") + def unwrap_char(self, w_char): from pypy.lang.smalltalk import constants w_class = w_char.getclass(self) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Mon Mar 2 14:25:32 2009 @@ -597,11 +597,10 @@ @expose_primitive(SECONDS_CLOCK, unwrap_spec=[object]) def func(interp, w_arg): - return interp.space.wrap_int(73) import time sec_since_epoch = rarithmetic.r_uint(time.time()) sec_since_1901 = sec_since_epoch + secs_between_1901_and_1970 - return interp.space.wrap_pos_full_int(sec_since_1901) + return interp.space.wrap_uint(sec_since_1901) # ___________________________________________________________________________ # Boolean Primitives Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py Mon Mar 2 14:25:32 2009 @@ -462,6 +462,7 @@ # ______________________________________________________________________ # Stack Manipulation + # XXX this should really be done with a fixedsize list as well. def pop(self): return self._stack.pop() Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py Mon Mar 2 14:25:32 2009 @@ -359,7 +359,8 @@ w_pointersobject.hash = self.chunk.hash12 def fillin_wordsobject(self, w_wordsobject): - w_wordsobject.words = self.chunk.data + from pypy.rlib.rarithmetic import r_uint + w_wordsobject.words = [r_uint(x) for x in self.chunk.data] w_class = self.g_class.w_object assert isinstance(w_class, model.W_PointersObject) w_wordsobject.w_class = w_class Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Mon Mar 2 14:25:32 2009 @@ -392,7 +392,6 @@ prim(primitives.FULL_GC, [42]) # Dummy arg def test_seconds_clock(): - py.test.skip("disabled because it breaks translation") import time now = int(time.time()) w_smalltalk_now1 = prim(primitives.SECONDS_CLOCK, [42]) From cfbolz at codespeak.net Mon Mar 2 14:26:21 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Mar 2009 14:26:21 +0100 (CET) Subject: [pypy-svn] r62372 - pypy/branch/spy-graphic/pypy/lang/smalltalk/test Message-ID: <20090302132621.3A4F51684BD@codespeak.net> Author: cfbolz Date: Mon Mar 2 14:26:20 2009 New Revision: 62372 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_objectspace.py Log: a test for the new unsigned wrapping/unwrapping code Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_objectspace.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_objectspace.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_objectspace.py Mon Mar 2 14:26:20 2009 @@ -1,3 +1,4 @@ +import py from pypy.lang.smalltalk import objspace space = objspace.ObjSpace() @@ -24,3 +25,19 @@ def test_metaclass_of_metaclass_is_an_instance_of_metaclass(): w_Metaclass = space.classtable['w_Metaclass'] assert w_Metaclass.w_class.w_class is w_Metaclass + +def test_ruint(): + from pypy.rlib.rarithmetic import r_uint + import sys + for num in [0, 1, 41, 100, 2**31, sys.maxint + 1]: + num = r_uint(num) + assert space.unwrap_uint(space.wrap_uint(num)) == num + for num in [-1, -100, -sys.maxint]: + py.test.raises(objspace.WrappingError, space.wrap_uint, num) + for obj in [space.wrap_char('a'), space.wrap_int(-1)]: + py.test.raises(objspace.UnwrappingError, space.unwrap_uint, obj) + byteobj = space.wrap_uint(sys.maxint + 1) + byteobj.bytes.append('\x01') + py.test.raises(objspace.UnwrappingError, space.unwrap_uint, byteobj) + + From cfbolz at codespeak.net Mon Mar 2 14:29:21 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Mar 2009 14:29:21 +0100 (CET) Subject: [pypy-svn] r62373 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090302132921.ED07D1684D1@codespeak.net> Author: cfbolz Date: Mon Mar 2 14:29:21 2009 New Revision: 62373 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Log: Use a fixed-size stack for context objects. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Mon Mar 2 14:29:21 2009 @@ -79,7 +79,8 @@ frame = interp.w_active_context() s_frame = frame.as_context_get_shadow(interp.space) assert argument_count == len_unwrap_spec - if len(s_frame.stack()) < len_unwrap_spec: + if s_frame.stackdepth() < len_unwrap_spec: + # XXX shouldn't this be a crash instead? raise PrimitiveFailedError() args = () for i, spec in unrolling_unwrap_spec: Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py Mon Mar 2 14:29:21 2009 @@ -1,6 +1,7 @@ import weakref from pypy.lang.smalltalk import model, constants, error from pypy.tool.pairtype import extendabletype +from pypy.rlib import rarithmetic class AbstractShadow(object): """A shadow is an optional extra bit of information that @@ -314,11 +315,14 @@ __metaclass__ = extendabletype def __init__(self, space, w_self): + from pypy.interpreter.miscutils import FixedStack + self._w_sender = space.w_nil - self._stack = [] + self._stack = FixedStack() self.currentBytecode = -1 AbstractRedirectingShadow.__init__(self, space, w_self) + @staticmethod def is_block_context(w_pointers, space): method_or_argc = w_pointers.fetch(space, constants.MTHDCTX_METHOD) @@ -333,7 +337,7 @@ if n0 == constants.CTXPART_STACKP_INDEX: return self.wrap_stackpointer() if self.stackstart() <= n0 < self.external_stackpointer(): - return self._stack[n0-self.stackstart()] + return self._stack.top(self.stackdepth() - (n0-self.stackstart()) - 1) if self.external_stackpointer() <= n0 < self.stackend(): return self.space.w_nil else: @@ -348,7 +352,8 @@ if n0 == constants.CTXPART_STACKP_INDEX: return self.unwrap_store_stackpointer(w_value) if self.stackstart() <= n0 < self.external_stackpointer(): - self._stack[n0 - self.stackstart()] = w_value + return self._stack.set_top(w_value, + self.stackdepth() - (n0-self.stackstart()) - 1) return if self.external_stackpointer() <= n0 < self.stackend(): return @@ -364,20 +369,21 @@ self.tempsize()) def store_stackpointer(self, size): - if size < len(self._stack): + depth = self.stackdepth() + if size < depth: # TODO Warn back to user assert size >= 0 - self._stack = self._stack[:size] + self._stack.drop_n(depth - size) else: - add = [self.space.w_nil] * (size - len(self._stack)) - self._stack.extend(add) + for i in range(depth, size): + self._stack.push(self.space.w_nil) def wrap_stackpointer(self): - return self.space.wrap_int(len(self._stack) + - self.tempsize()) + return self.space.wrap_int(self.stackdepth() + + self.tempsize()) def external_stackpointer(self): - return len(self._stack) + self.stackstart() + return self.stackdepth() + self.stackstart() def w_home(self): raise NotImplementedError() @@ -462,38 +468,39 @@ # ______________________________________________________________________ # Stack Manipulation - # XXX this should really be done with a fixedsize list as well. + def init_stack(self): + self._stack.setup(self.stackend() - self.stackstart()) + + def stack(self): + """NOT_RPYTHON""" # purely for testing + return self._stack.items[:self.stackdepth()] + def pop(self): return self._stack.pop() def push(self, w_v): - self._stack.append(w_v) + self._stack.push(w_v) def push_all(self, lst): - self._stack.extend(lst) + for elt in lst: + self.push(elt) def top(self): return self.peek(0) def peek(self, idx): - return self._stack[-(idx + 1)] + return self._stack.top(idx) def pop_n(self, n): - assert n >= 0 - start = len(self._stack) - n - assert start >= 0 # XXX what if this fails? - del self._stack[start:] + self._stack.drop(n) - def stack(self): - return self._stack + def stackdepth(self): + return rarithmetic.intmask(self._stack.depth()) def pop_and_return_n(self, n): - assert n >= 0 - start = len(self._stack) - n - assert start >= 0 # XXX what if this fails? - res = self._stack[start:] - del self._stack[start:] - return res + result = [self._stack.top(i) for i in range(n - 1, -1, -1)] + self.pop_n(n) + return result def stackend(self): # XXX this is incorrect when there is subclassing @@ -517,6 +524,7 @@ s_result.store_initialip(initialip) s_result.store_w_home(w_home) s_result.store_pc(initialip) + s_result.init_stack() return w_result def fetch(self, n0): @@ -542,6 +550,7 @@ def attach_shadow(self): # Make sure the home context is updated first self.copy_from_w_self(constants.BLKCTX_HOME_INDEX) + self.init_stack() ContextPartShadow.attach_shadow(self) def unwrap_store_initialip(self, w_value): @@ -580,7 +589,7 @@ return self._w_home def reset_stack(self): - self._stack = [] + self.pop_n(self.stackdepth()) def stackstart(self): return constants.BLKCTX_STACK_START @@ -619,6 +628,7 @@ s_result._temps = [space.w_nil] * w_method.tempsize for i in range(len(arguments)): s_result.settemp(i, arguments[i]) + s_result.init_stack() return w_result def fetch(self, n0): @@ -653,6 +663,7 @@ def attach_shadow(self): # Make sure the method is updated first self.copy_from_w_self(constants.MTHDCTX_METHOD) + self.init_stack() # And that there is space for the temps self._temps = [self.space.w_nil] * self.tempsize() ContextPartShadow.attach_shadow(self) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Mon Mar 2 14:29:21 2009 @@ -15,7 +15,9 @@ def __init__(self, stack): self._vars = [None] * 6 + stack s_self = self.as_blockcontext_get_shadow() - s_self._stack = stack + s_self.init_stack() + s_self.reset_stack() + s_self.push_all(stack) s_self.store_expected_argument_count(0) def as_blockcontext_get_shadow(self): self._shadow = shadow.BlockContextShadow(space, self) @@ -40,7 +42,7 @@ interp, argument_count = mock(stack) prim_table[code](interp, argument_count-1) res = interp.s_active_context().pop() - assert not len(interp.s_active_context().stack()) # check args are consumed + assert not interp.s_active_context().stackdepth() # check args are consumed return res def prim_fails(code, stack): From cfbolz at codespeak.net Mon Mar 2 14:31:42 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Mar 2009 14:31:42 +0100 (CET) Subject: [pypy-svn] r62375 - pypy/branch/spy-graphic/pypy/lang/smalltalk Message-ID: <20090302133142.55A451684D1@codespeak.net> Author: cfbolz Date: Mon Mar 2 14:31:41 2009 New Revision: 62375 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py Log: woops Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/shadow.py Mon Mar 2 14:31:41 2009 @@ -373,7 +373,7 @@ if size < depth: # TODO Warn back to user assert size >= 0 - self._stack.drop_n(depth - size) + self._stack.drop(depth - size) else: for i in range(depth, size): self._stack.push(self.space.w_nil) From cfbolz at codespeak.net Mon Mar 2 14:32:16 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Mar 2009 14:32:16 +0100 (CET) Subject: [pypy-svn] r62376 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090302133216.187351684E4@codespeak.net> Author: cfbolz Date: Mon Mar 2 14:32:15 2009 New Revision: 62376 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Log: Implement a couple of primitives that the mini image is trying to run. Some of the implementations are stubs so far, fix this later. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Mon Mar 2 14:32:15 2009 @@ -19,11 +19,12 @@ class Interpreter(object): _w_last_active_context = None + cnt = 0 - def __init__(self, space): + def __init__(self, space, image_name=""): self._w_active_context = None self.space = space - self.cnt = 0 + self.image_name = image_name def w_active_context(self): return self._w_active_context Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py Mon Mar 2 14:32:15 2009 @@ -99,6 +99,9 @@ False means swapping failed""" return False + def clone(self): + raise NotImplementedError + class W_SmallInteger(W_Object): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? @@ -136,6 +139,8 @@ def __hash__(self): return self.value + def clone(self): + return self class W_Float(W_Object): """Boxed float value.""" @@ -172,6 +177,9 @@ def __hash__(self): return hash(self.value) + def clone(self): + return self + class W_AbstractObjectWithIdentityHash(W_Object): """Object with explicit hash (ie all except small ints and floats).""" @@ -344,6 +352,10 @@ W_AbstractObjectWithClassReference._become(self, w_other) return True + def clone(self): + w_result = W_PointersObject(self.w_class, len(self._vars)) + w_result._vars[:] = self._vars + return w_result class W_BytesObject(W_AbstractObjectWithClassReference): def __init__(self, w_class, size): @@ -389,6 +401,11 @@ return False return self.bytes == other.bytes + def clone(self): + w_result = W_BytesObject(self.w_class, len(self.bytes)) + w_result.bytes[:] = self.bytes + return w_result + class W_WordsObject(W_AbstractObjectWithClassReference): def __init__(self, w_class, size): W_AbstractObjectWithClassReference.__init__(self, w_class) @@ -415,6 +432,11 @@ return (W_AbstractObjectWithClassReference.invariant(self) and isinstance(self.words, list)) + def clone(self): + w_result = W_WordsObject(self.w_class, len(self.words)) + w_result.words[:] = self.words + return w_result + # XXX Shouldn't compiledmethod have class reference for subclassed compiled # methods? class W_CompiledMethod(W_AbstractObjectWithIdentityHash): Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Mon Mar 2 14:32:15 2009 @@ -490,6 +490,14 @@ interp.space.objtable['w_display'] = w_rcvr return w_rcvr + at expose_primitive(SCREEN_SIZE, unwrap_spec=[object]) +def func(interp, w_rcvr): + # XXX get the real screen size + w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2) + point = wrapper.PointWrapper(interp.space, w_res) + point.store_x(640) + point.store_y(480) + return w_res # ___________________________________________________________________________ # Control Primitives @@ -549,10 +557,32 @@ w_rcvr.w_class = w_arg.w_class # ___________________________________________________________________________ +# Miscellaneous Primitives (120-127) +CALLOUT_TO_FFI = 120 +IMAGE_NAME = 121 +NOOP = 122 +VALUE_UNINTERRUPTABLY = 123 +LOW_SPACE_SEMAPHORE = 124 +SIGNAL_AT_BYTES_LEFT = 125 + + at expose_primitive(IMAGE_NAME) +def func(interp, argument_count): + if argument_count == 0: + interp.s_active_context().pop() + return interp.space.wrap_string(interp.image_name) + elif argument_count == 1: + pass # XXX + raise PrimitiveFailedError + + + + +# ___________________________________________________________________________ # Squeak Miscellaneous Primitives (128-149) BECOME = 128 FULL_GC = 130 INC_GC = 131 +CLONE = 148 @expose_primitive(BECOME, unwrap_spec=[object, object]) def func(interp, w_rcvr, w_new): @@ -582,6 +612,10 @@ rgc.collect() return fake_bytes_left(interp) + at expose_primitive(CLONE, unwrap_spec=[object]) +def func(interp, w_arg): + return w_arg.clone() + #____________________________________________________________________________ # Time Primitives MILLISECOND_CLOCK = 135 @@ -604,6 +638,32 @@ return interp.space.wrap_uint(sec_since_1901) # ___________________________________________________________________________ +# File primitives (150-169) +# (XXX they are obsolete in Squeak and done with a plugin) + +FILE_AT_END = 150 +FILE_CLOSE = 151 +FILE_GET_POSITION = 152 +FILE_OPEN = 153 +FILE_READ = 154 +FILE_SET_POSITION = 155 +FILE_DELETE = 156 +FILE_SIZE = 157 +FILE_WRITE = 158 +FILE_RENAME = 159 +DIRECTORY_CREATE = 160 +DIRECTORY_DELIMITOR = 161 +DIRECTORY_LOOKUP = 162 +DIRECTORY_DELTE = 163 + + + at expose_primitive(DIRECTORY_DELIMITOR, unwrap_spec=[object]) +def func(interp, _): + import os.path + return interp.space.wrap_char(os.path.sep) + + +# ___________________________________________________________________________ # Boolean Primitives LESSTHAN = 3 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Mon Mar 2 14:32:15 2009 @@ -419,6 +419,24 @@ assert w_method.literalat0(space, 1).is_same_object(space.w_nil) assert w_method.bytes == "\x00" * len(bytecode) +def test_image_name(): + w_v = prim(primitives.IMAGE_NAME, [2]) + assert w_v.bytes == [] + +def test_clone(): + w_obj = mockclass(space, 1, varsized=True).as_class_get_shadow(space).new(1) + w_obj.atput0(space, 0, space.wrap_int(1)) + w_v = prim(primitives.CLONE, [w_obj]) + assert space.unwrap_int(w_v.at0(space, 0)) == 1 + w_obj.atput0(space, 0, space.wrap_int(2)) + assert space.unwrap_int(w_v.at0(space, 0)) == 1 + +def test_directory_delimitor(): + import os.path + w_c = prim(primitives.DIRECTORY_DELIMITOR, [1]) + assert space.unwrap_char(w_c) == os.path.sep + + # Note: # primitives.NEXT is unimplemented as it is a performance optimization From arigo at codespeak.net Mon Mar 2 14:42:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 14:42:11 +0100 (CET) Subject: [pypy-svn] r62384 - in pypy/branch/pyjitpl5/pypy/translator/c: . test Message-ID: <20090302134211.48006168490@codespeak.net> Author: arigo Date: Mon Mar 2 14:42:10 2009 New Revision: 62384 Modified: pypy/branch/pyjitpl5/pypy/translator/c/database.py pypy/branch/pyjitpl5/pypy/translator/c/primitive.py pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py Log: Support for GCREF instances in the C backend. Implemented by considering them as primitive type (hackish, but less than other solutions I thought about...). Modified: pypy/branch/pyjitpl5/pypy/translator/c/database.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/database.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/database.py Mon Mar 2 14:42:10 2009 @@ -3,7 +3,7 @@ Struct, Array, FuncType, PyObject, Void, \ ContainerType, OpaqueType, FixedSizeArray, _uninitialized from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType +from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType, GCREF from pypy.rpython.lltypesystem.rffi import CConstant from pypy.tool.sourcetools import valid_identifier from pypy.translator.c.primitive import PrimitiveName, PrimitiveType @@ -95,7 +95,7 @@ return node def gettype(self, T, varlength=1, who_asks=None, argnames=[]): - if isinstance(T, Primitive): + if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Ptr): try: @@ -174,7 +174,7 @@ if isinstance(obj, CConstant): return obj.c_name # without further checks T = typeOf(obj) - if isinstance(T, Primitive): + if isinstance(T, Primitive) or T == GCREF: return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL Modified: pypy/branch/pyjitpl5/pypy/translator/c/primitive.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/primitive.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/primitive.py Mon Mar 2 14:42:10 2009 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem.llmemory import Address, \ AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \ CompositeOffset, ArrayLengthOffset, \ - GCHeaderOffset + GCHeaderOffset, GCREF from pypy.rpython.lltypesystem.llarena import RoundedUpForAllocation from pypy.translator.c.support import cdecl, barebonearray @@ -128,6 +128,14 @@ else: return 'NULL' +def name_gcref(value, db): + if value: + realobj = value._obj.container + realvalue = cast_opaque_ptr(Ptr(typeOf(realobj)), value) + return db.get(realvalue) + else: + return 'NULL' + # On 64 bit machines, SignedLongLong and Signed are the same, so the # order matters, because we want the Signed implementation. PrimitiveName = { @@ -142,6 +150,7 @@ Bool: name_bool, Void: name_void, Address: name_address, + GCREF: name_gcref, } PrimitiveType = { @@ -156,6 +165,7 @@ Bool: 'bool_t @', Void: 'void @', Address: 'void* @', + GCREF: 'void* @', } def define_c_primitive(ll_type, c_name): Modified: pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py Mon Mar 2 14:42:10 2009 @@ -151,3 +151,25 @@ return result fn = compile(f, [int]) assert fn(1) == 2 + +def test_gcref(): + S = lltype.GcStruct("S", ("x", lltype.Signed)) + s = lltype.malloc(S) + s.x = 123 + g1 = lltype.cast_opaque_ptr(GCREF, s) + g2 = lltype.cast_opaque_ptr(GCREF, lltype.nullptr(S)) + def f2(x): + if x > 0: + return g1 + else: + return g2 + def f(x): + gref = f2(x) + g = lltype.cast_opaque_ptr(lltype.Ptr(S), gref) + if g: + return g.x + else: + return -42 + fn = compile(f, [int], gcpolicy='boehm') + assert fn(3) == 123 + assert fn(-3) == -42 From afa at codespeak.net Mon Mar 2 15:24:05 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 2 Mar 2009 15:24:05 +0100 (CET) Subject: [pypy-svn] r62393 - in pypy/trunk/pypy: module/__builtin__ rpython/module Message-ID: <20090302142405.608461684A2@codespeak.net> Author: afa Date: Mon Mar 2 15:24:03 2009 New Revision: 62393 Modified: pypy/trunk/pypy/module/__builtin__/importing.py pypy/trunk/pypy/rpython/module/ll_os_stat.py Log: Implement float times in os.stat(), on win32 only for the moment. I have to check the cli backend; for the moment it fails because pypy.rlib.runicode.unicode_encode_mbcs() is not ootype-friendly. Modified: pypy/trunk/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/importing.py (original) +++ pypy/trunk/pypy/module/__builtin__/importing.py Mon Mar 2 15:24:03 2009 @@ -428,7 +428,7 @@ pycode = parse_source_module(space, pathname, source) if space.config.objspace.usepycfiles and write_pyc: - mtime = os.stat(pathname)[stat.ST_MTIME] + mtime = int(os.stat(pathname)[stat.ST_MTIME]) cpathname = pathname + 'c' write_compiled_module(space, pycode, cpathname, mtime) Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Mon Mar 2 15:24:03 2009 @@ -13,12 +13,14 @@ from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo -# NOTE: float times are disabled for now, for simplicity. They make the life -# of OO backends more complicated because for them we try to not depend on -# the details of the platform on which we do the translation. Also, they -# seem not essential because they are disabled by default in CPython. +# Support for float times is here. +# Note: For the moment, only Windows implement float times. +# Things are a bit simpler there because 'struct stat' is not used. TIMESPEC = None -ModTime = lltype.Signed +if sys.platform == 'win32': + ModTime = lltype.Float +else: + ModTime = lltype.Signed # all possible fields - some of them are not available on all platforms ALL_STAT_FIELDS = [ @@ -147,14 +149,15 @@ includes = INCLUDES ) -from pypy.rpython.tool import rffi_platform as platform -class CConfig: - # This must be set to 64 on some systems to enable large file support. - _compilation_info_ = compilation_info - STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS) -config = platform.configure(CConfig) +if sys.platform != 'win32': + from pypy.rpython.tool import rffi_platform as platform + class CConfig: + # This must be set to 64 on some systems to enable large file support. + _compilation_info_ = compilation_info + STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS) + config = platform.configure(CConfig) -STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT']) + STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT']) def build_stat_result(st): # only for LL backends @@ -202,19 +205,13 @@ c_func_name = name arg_is_path = (name != 'fstat') - if arg_is_path: - ARG1 = rffi.CCHARP - else: - ARG1 = rffi.INT - os_mystat = rffi.llexternal(c_func_name, [ARG1, STAT_STRUCT], rffi.INT, - compilation_info=compilation_info) def posix_stat_llimpl(arg): stresult = lltype.malloc(STAT_STRUCT.TO, flavor='raw') try: if arg_is_path: arg = rffi.str2charp(arg) - error = rffi.cast(rffi.LONG, os_mystat(arg, stresult)) + error = rffi.cast(rffi.LONG, posix_mystat(arg, stresult)) if arg_is_path: rffi.free_charp(arg) if error != 0: @@ -235,10 +232,16 @@ if arg_is_path: s_arg = str + ARG1 = rffi.CCHARP else: s_arg = int + ARG1 = rffi.INT if sys.platform != 'win32': + posix_mystat = rffi.llexternal(c_func_name, + [ARG1, STAT_STRUCT], rffi.INT, + compilation_info=compilation_info) + register_external( getattr(os, name), [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name,), @@ -333,10 +336,14 @@ m |= 0666 return m - secs_between_epochs = lltype.r_ulonglong(11644473600) # Seconds between 1.1.1601 and 1.1.1970 + def make_longlong(high, low): + return (lltype.r_longlong(high) << 32) + lltype.r_longlong(low) + + # Seconds between 1.1.1601 and 1.1.1970 + secs_between_epochs = lltype.r_longlong(11644473600) + def FILE_TIME_to_time_t_nsec(filetime): - ft = (lltype.r_ulonglong(filetime.c_dwHighDateTime) << 32) - ft += filetime.c_dwLowDateTime + ft = make_longlong(filetime.c_dwHighDateTime, filetime.c_dwLowDateTime) # FILETIME is in units of 100 nsec nsec = (ft % 10000000) * 100 time = (ft / 10000000) - secs_between_epochs @@ -344,8 +351,7 @@ def attribute_data_to_stat(info): st_mode = attributes_to_mode(info.c_dwFileAttributes) - st_size = (lltype.r_ulonglong(info.c_nFileSizeHigh) << 32) - st_size += info.c_nFileSizeLow + st_size = make_longlong(info.c_nFileSizeHigh, info.c_nFileSizeLow) ctime, ctime_ns = FILE_TIME_to_time_t_nsec(info.c_ftCreationTime) mtime, mtime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastWriteTime) atime, atime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastAccessTime) @@ -353,27 +359,30 @@ result = (st_mode, 0, 0, 0, 0, 0, st_size, - atime, mtime, ctime) + atime + atime_ns * 1e-9, + mtime + mtime_ns * 1e-9, + ctime + ctime_ns * 1e-9) return make_stat_result(result) def by_handle_info_to_stat(info): # similar to the one above st_mode = attributes_to_mode(info.c_dwFileAttributes) - st_size = (lltype.r_ulonglong(info.c_nFileSizeHigh) << 32) - st_size += info.c_nFileSizeLow + st_size = make_longlong(info.c_nFileSizeHigh, info.c_nFileSizeLow) ctime, ctime_ns = FILE_TIME_to_time_t_nsec(info.c_ftCreationTime) mtime, mtime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastWriteTime) atime, atime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastAccessTime) # specific to fstat() - st_ino = (lltype.r_ulonglong(info.c_nFileIndexHigh) << 32) + info.c_nFileIndexLow + st_ino = make_longlong(info.c_nFileIndexHigh, info.c_nFileIndexLow) st_nlink = info.c_nNumberOfLinks result = (st_mode, st_ino, 0, st_nlink, 0, 0, st_size, - atime, mtime, ctime) + atime + atime_ns * 1e-9, + mtime + mtime_ns * 1e-9, + ctime + ctime_ns * 1e-9) return make_stat_result(result) From cami at codespeak.net Mon Mar 2 15:44:53 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 15:44:53 +0100 (CET) Subject: [pypy-svn] r62394 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302144453.BB481168562@codespeak.net> Author: cami Date: Mon Mar 2 15:44:53 2009 New Revision: 62394 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: reverted video and video_sprites Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Mon Mar 2 15:44:53 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = True +use_rsdl = False if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 15:44:53 2009 @@ -139,7 +139,7 @@ #XXX remove those dumb helper "objects" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.objects = [None] * constants.OBJECTS_PER_LINE + self.objects = [0] * constants.OBJECTS_PER_LINE self.palette = [0] * 1024 self.frames = 0 @@ -555,23 +555,41 @@ count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): - sprite = self.objects[index] - x = sprite.x + data = self.objects[index] + x = (data >> 24) & 0xFF + flags = (data >> 12) & 0xFF + address = data & 0xFFF if (x + SPRITE_SIZE <= lastx): - sprite.draw(self) + self.draw_object_tile(x, address, flags) else: - sprite.draw_overlapped(self) + self.draw_overlapped_object_tile(x, address, flags) lastx = x def scan_sprites(self): - # search active objects count = 0 + # search active objects for sprite in self.sprites: - if not sprite.hidden and sprite.visible_on_line(self.line_y): - self.objects[count] = sprite - count += 1 - if count >= constants.OBJECTS_PER_LINE: - break + x = sprite.x + y = sprite.y + if sprite.hidden: continue + tile = sprite.tile_number + y = self.line_y - y + 2 * SPRITE_SIZE + if self.control.big_sprite_size_selected: + # 8x16 tile size + tile_size = 15 + tile &= 0xFE + else: + # 8x8 tile size + tile_size = 7 + if y < 0 or y > tile_size: continue + if sprite.y_flipped: + y = tile_size - y + # TODO: build an object abstraction? + self.objects[count] = (x << 24) + (count << 20) + (sprite.get_attributes_and_flags() << 12) + \ + (tile << 4) + (y << 1) + count += 1 + if count >= constants.OBJECTS_PER_LINE: + break self.sort_scan_sprite(count) return count @@ -581,7 +599,8 @@ for index in range(count): highest = index for right in range(index+1, count): - if self.objects[right].x > self.objects[highest].x: + if (self.objects[right] >> 20) > \ + (self.objects[highest] >> 20): highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] @@ -605,20 +624,20 @@ return self.vram[address] + (self.vram[address + 1] << 8) - def draw_object_tile(self, x, y, address, flags): - self.draw_object(set_tile_line_call_wrapper(self), x, y, address, flags) + def draw_object_tile(self, x, address, flags): + self.draw_object(set_tile_line_call_wrapper(self), x, address, flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask - def draw_overlapped_object_tile(self, x, y, address, flags): + def draw_overlapped_object_tile(self, x, address, flags): self.draw_object(set_overlapped_object_line_call_wrapper(self), - x, y, address, flags) + x, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask - def draw_object(self, caller, x, y, address, flags): + def draw_object(self, caller, x, address, flags): pattern = self.get_pattern(address) mask = 0 # priority Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 15:44:53 2009 @@ -30,25 +30,18 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - def set_data_at(self, address, data): - actual = address % 4 - if actual == 0: - self.extract_y_position(data) - if actual == 1: - self.extract_x_position(data) - if actual == 2: - self.extract_tile_number(data) - if actual == 3: - self.extract_attributes_and_flags(data) - - def set_data(self, y_position, x_position, tile_number, attributes_and_flags): + def set_data(self, byte0=-1, byte1=-1, byte2=-1, byte3=-1): """ extracts the sprite data from an oam entry """ - self.extract_y_position(y_position) - self.extract_x_position(x_position) - self.extract_tile_number(tile_number) - self.extract_attributes_and_flags(attributes_and_flags) + if byte0 is not -1: + self.extract_y_position(byte0) + if byte1 is not -1: + self.extract_x_position(byte1) + if byte2 is not -1: + self.extract_tile_number(byte2) + if byte3 is not -1: + self.extract_attributes_and_flags(byte3) def extract_y_position(self, data): """ @@ -106,18 +99,14 @@ return value def hide_check(self): - if self.y <= 0 or self.y >= SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE: + if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: self.hidden = True - elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: + elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: self.hidden = True else: self.hidden = False return self.hidden - def visible_on_line(self, line_y): - y = self.get_draw_y(line_y) - return y < 0 or y > (self.get_height() -1) - def get_tile_number(self): return self.tile.id @@ -136,28 +125,11 @@ def intersects_line(self, line): return line >= self.y and line <= self.y + self.get_height() - def get_draw_y(self, line_y): - return line_y - self.y + 2 * SPRITE_SIZE - - def get_draw_address_data(self, line_y): - tile = self.tile_number - if self.big_size: - tile &= 0xFE - tile_size = self.get_height() -1 - y = self.get_draw_y(line_y) - if self.y_flipped: - y = tile_size - y - return (tile << 4) + (y << 1) - - def draw(self, video): - video.draw_object_tile(self.x, self.y, \ - self.get_draw_address_data(video.line_y), \ - self.get_attributes_and_flags()) - - def draw_overlapped(self, video): - video.draw_overlapped_object_tile(self.x, self.y, \ - self.get_draw_address_data(video.line_y), \ - self.get_attributes_and_flags()) + def draw(self): + pass + + def draw_overlapped(self): + pass # ----------------------------------------------------------------------------- class PaintSprite(Sprite): From tverwaes at codespeak.net Mon Mar 2 15:52:00 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 2 Mar 2009 15:52:00 +0100 (CET) Subject: [pypy-svn] r62395 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302145200.6EE6116849E@codespeak.net> Author: tverwaes Date: Mon Mar 2 15:52:00 2009 New Revision: 62395 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixed for test. Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 15:52:00 2009 @@ -30,18 +30,27 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - def set_data(self, byte0=-1, byte1=-1, byte2=-1, byte3=-1): + def set_data(self, y, x, tile_number, flags): """ extracts the sprite data from an oam entry """ - if byte0 is not -1: - self.extract_y_position(byte0) - if byte1 is not -1: - self.extract_x_position(byte1) - if byte2 is not -1: - self.extract_tile_number(byte2) - if byte3 is not -1: - self.extract_attributes_and_flags(byte3) + self.extract_y_position(y) + self.extract_x_position(x) + self.extract_tile_number(tile_number) + self.extract_attributes_and_flags(flags) + + def set_data_at(self, position, data): + """ + extracts the sprite data from an oam entry + """ + if position == 0: + self.extract_y_position(data) + if position == 1: + self.extract_x_position(data) + if position == 2: + self.extract_tile_number(data) + if position == 3: + self.extract_attributes_and_flags(data) def extract_y_position(self, data): """ From cami at codespeak.net Mon Mar 2 15:58:10 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 15:58:10 +0100 (CET) Subject: [pypy-svn] r62396 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302145810.986031684A3@codespeak.net> Author: cami Date: Mon Mar 2 15:58:08 2009 New Revision: 62396 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: reverting the revert Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Mon Mar 2 15:58:08 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = False +use_rsdl = True if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 15:58:08 2009 @@ -139,7 +139,7 @@ #XXX remove those dumb helper "objects" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.objects = [0] * constants.OBJECTS_PER_LINE + self.objects = [None] * constants.OBJECTS_PER_LINE self.palette = [0] * 1024 self.frames = 0 @@ -555,41 +555,23 @@ count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): - data = self.objects[index] - x = (data >> 24) & 0xFF - flags = (data >> 12) & 0xFF - address = data & 0xFFF + sprite = self.objects[index] + x = sprite.x if (x + SPRITE_SIZE <= lastx): - self.draw_object_tile(x, address, flags) + sprite.draw(self) else: - self.draw_overlapped_object_tile(x, address, flags) + sprite.draw_overlapped(self) lastx = x def scan_sprites(self): - count = 0 # search active objects + count = 0 for sprite in self.sprites: - x = sprite.x - y = sprite.y - if sprite.hidden: continue - tile = sprite.tile_number - y = self.line_y - y + 2 * SPRITE_SIZE - if self.control.big_sprite_size_selected: - # 8x16 tile size - tile_size = 15 - tile &= 0xFE - else: - # 8x8 tile size - tile_size = 7 - if y < 0 or y > tile_size: continue - if sprite.y_flipped: - y = tile_size - y - # TODO: build an object abstraction? - self.objects[count] = (x << 24) + (count << 20) + (sprite.get_attributes_and_flags() << 12) + \ - (tile << 4) + (y << 1) - count += 1 - if count >= constants.OBJECTS_PER_LINE: - break + if not sprite.hidden and sprite.visible_on_line(self.line_y): + self.objects[count] = sprite + count += 1 + if count >= constants.OBJECTS_PER_LINE: + break self.sort_scan_sprite(count) return count @@ -599,8 +581,7 @@ for index in range(count): highest = index for right in range(index+1, count): - if (self.objects[right] >> 20) > \ - (self.objects[highest] >> 20): + if self.objects[right].x > self.objects[highest].x: highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] @@ -624,20 +605,20 @@ return self.vram[address] + (self.vram[address + 1] << 8) - def draw_object_tile(self, x, address, flags): - self.draw_object(set_tile_line_call_wrapper(self), x, address, flags) + def draw_object_tile(self, x, y, address, flags): + self.draw_object(set_tile_line_call_wrapper(self), x, y, address, flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask - def draw_overlapped_object_tile(self, x, address, flags): + def draw_overlapped_object_tile(self, x, y, address, flags): self.draw_object(set_overlapped_object_line_call_wrapper(self), - x, address, flags) + x, y, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask - def draw_object(self, caller, x, address, flags): + def draw_object(self, caller, x, y, address, flags): pattern = self.get_pattern(address) mask = 0 # priority Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 15:58:08 2009 @@ -30,27 +30,25 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - def set_data(self, y, x, tile_number, flags): - """ - extracts the sprite data from an oam entry - """ - self.extract_y_position(y) - self.extract_x_position(x) - self.extract_tile_number(tile_number) - self.extract_attributes_and_flags(flags) - - def set_data_at(self, position, data): - """ - extracts the sprite data from an oam entry - """ - if position == 0: + def set_data_at(self, address, data): + actual = address % 4 + if actual == 0: self.extract_y_position(data) - if position == 1: + if actual == 1: self.extract_x_position(data) - if position == 2: + if actual == 2: self.extract_tile_number(data) - if position == 3: + if actual == 3: self.extract_attributes_and_flags(data) + + def set_data(self, y_position, x_position, tile_number, attributes_and_flags): + """ + extracts the sprite data from an oam entry + """ + self.extract_y_position(y_position) + self.extract_x_position(x_position) + self.extract_tile_number(tile_number) + self.extract_attributes_and_flags(attributes_and_flags) def extract_y_position(self, data): """ @@ -108,14 +106,18 @@ return value def hide_check(self): - if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: + if self.y <= 0 or self.y >= SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE: self.hidden = True - elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: + elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: self.hidden = True else: self.hidden = False return self.hidden + def visible_on_line(self, line_y): + y = self.get_draw_y(line_y) + return y < 0 or y > (self.get_height() -1) + def get_tile_number(self): return self.tile.id @@ -134,11 +136,28 @@ def intersects_line(self, line): return line >= self.y and line <= self.y + self.get_height() - def draw(self): - pass - - def draw_overlapped(self): - pass + def get_draw_y(self, line_y): + return line_y - self.y + 2 * SPRITE_SIZE + + def get_draw_address_data(self, line_y): + tile = self.tile_number + if self.big_size: + tile &= 0xFE + tile_size = self.get_height() -1 + y = self.get_draw_y(line_y) + if self.y_flipped: + y = tile_size - y + return (tile << 4) + (y << 1) + + def draw(self, video): + video.draw_object_tile(self.x, self.y, \ + self.get_draw_address_data(video.line_y), \ + self.get_attributes_and_flags()) + + def draw_overlapped(self, video): + video.draw_overlapped_object_tile(self.x, self.y, \ + self.get_draw_address_data(video.line_y), \ + self.get_attributes_and_flags()) # ----------------------------------------------------------------------------- class PaintSprite(Sprite): From cami at codespeak.net Mon Mar 2 16:08:45 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:08:45 +0100 (CET) Subject: [pypy-svn] r62397 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090302150845.ED90F16856E@codespeak.net> Author: cami Date: Mon Mar 2 16:08:45 2009 New Revision: 62397 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: reverting reverted reverts Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Mon Mar 2 16:08:45 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = True +use_rsdl = False if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py Mon Mar 2 16:08:45 2009 @@ -57,19 +57,19 @@ def test_video_sprite_read_write(): sprite = get_sprite() for i in range(0xFF): - sprite.set_data_at(0, i) + sprite.set_data(byte0=i) assert sprite.get_data()[0] == i for i in range(0xFF): - sprite.set_data_at(1, i) + sprite.set_data(byte1=i) assert sprite.get_data()[1] == i for i in range(0xFF): - sprite.set_data_at(2, i) + sprite.set_data(byte2=i) assert sprite.get_data()[2] == i for i in range(0xFF): - sprite.set_data_at(3, i) + sprite.set_data(byte3=i) assert sprite.get_data()[3] == i def test_size(): Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:08:45 2009 @@ -139,7 +139,7 @@ #XXX remove those dumb helper "objects" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.objects = [None] * constants.OBJECTS_PER_LINE + self.objects = [0] * constants.OBJECTS_PER_LINE self.palette = [0] * 1024 self.frames = 0 @@ -555,23 +555,41 @@ count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): - sprite = self.objects[index] - x = sprite.x + data = self.objects[index] + x = (data >> 24) & 0xFF + flags = (data >> 12) & 0xFF + address = data & 0xFFF if (x + SPRITE_SIZE <= lastx): - sprite.draw(self) + self.draw_object_tile(x, address, flags) else: - sprite.draw_overlapped(self) + self.draw_overlapped_object_tile(x, address, flags) lastx = x def scan_sprites(self): - # search active objects count = 0 + # search active objects for sprite in self.sprites: - if not sprite.hidden and sprite.visible_on_line(self.line_y): - self.objects[count] = sprite - count += 1 - if count >= constants.OBJECTS_PER_LINE: - break + x = sprite.x + y = sprite.y + if sprite.hidden: continue + tile = sprite.tile_number + y = self.line_y - y + 2 * SPRITE_SIZE + if self.control.big_sprite_size_selected: + # 8x16 tile size + tile_size = 15 + tile &= 0xFE + else: + # 8x8 tile size + tile_size = 7 + if y < 0 or y > tile_size: continue + if sprite.y_flipped: + y = tile_size - y + # TODO: build an object abstraction? + self.objects[count] = (x << 24) + (count << 20) + (sprite.get_attributes_and_flags() << 12) + \ + (tile << 4) + (y << 1) + count += 1 + if count >= constants.OBJECTS_PER_LINE: + break self.sort_scan_sprite(count) return count @@ -581,7 +599,8 @@ for index in range(count): highest = index for right in range(index+1, count): - if self.objects[right].x > self.objects[highest].x: + if (self.objects[right] >> 20) > \ + (self.objects[highest] >> 20): highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] @@ -605,20 +624,20 @@ return self.vram[address] + (self.vram[address + 1] << 8) - def draw_object_tile(self, x, y, address, flags): - self.draw_object(set_tile_line_call_wrapper(self), x, y, address, flags) + def draw_object_tile(self, x, address, flags): + self.draw_object(set_tile_line_call_wrapper(self), x, address, flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask - def draw_overlapped_object_tile(self, x, y, address, flags): + def draw_overlapped_object_tile(self, x, address, flags): self.draw_object(set_overlapped_object_line_call_wrapper(self), - x, y, address, flags) + x, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask - def draw_object(self, caller, x, y, address, flags): + def draw_object(self, caller, x, address, flags): pattern = self.get_pattern(address) mask = 0 # priority Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 16:08:45 2009 @@ -30,25 +30,18 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - def set_data_at(self, address, data): - actual = address % 4 - if actual == 0: - self.extract_y_position(data) - if actual == 1: - self.extract_x_position(data) - if actual == 2: - self.extract_tile_number(data) - if actual == 3: - self.extract_attributes_and_flags(data) - - def set_data(self, y_position, x_position, tile_number, attributes_and_flags): + def set_data(self, byte0=-1, byte1=-1, byte2=-1, byte3=-1): """ extracts the sprite data from an oam entry """ - self.extract_y_position(y_position) - self.extract_x_position(x_position) - self.extract_tile_number(tile_number) - self.extract_attributes_and_flags(attributes_and_flags) + if byte0 is not -1: + self.extract_y_position(byte0) + if byte1 is not -1: + self.extract_x_position(byte1) + if byte2 is not -1: + self.extract_tile_number(byte2) + if byte3 is not -1: + self.extract_attributes_and_flags(byte3) def extract_y_position(self, data): """ @@ -106,18 +99,14 @@ return value def hide_check(self): - if self.y <= 0 or self.y >= SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE: + if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: self.hidden = True - elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: + elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: self.hidden = True else: self.hidden = False return self.hidden - def visible_on_line(self, line_y): - y = self.get_draw_y(line_y) - return y < 0 or y > (self.get_height() -1) - def get_tile_number(self): return self.tile.id @@ -133,31 +122,14 @@ def overlaps_on_line(self, sprite, line): return False - def intersects_line(self, line): + def intersects_current_line(self, video): return line >= self.y and line <= self.y + self.get_height() - def get_draw_y(self, line_y): - return line_y - self.y + 2 * SPRITE_SIZE - - def get_draw_address_data(self, line_y): - tile = self.tile_number - if self.big_size: - tile &= 0xFE - tile_size = self.get_height() -1 - y = self.get_draw_y(line_y) - if self.y_flipped: - y = tile_size - y - return (tile << 4) + (y << 1) - - def draw(self, video): - video.draw_object_tile(self.x, self.y, \ - self.get_draw_address_data(video.line_y), \ - self.get_attributes_and_flags()) - - def draw_overlapped(self, video): - video.draw_overlapped_object_tile(self.x, self.y, \ - self.get_draw_address_data(video.line_y), \ - self.get_attributes_and_flags()) + def draw(self): + pass + + def draw_overlapped(self): + pass # ----------------------------------------------------------------------------- class PaintSprite(Sprite): From tverwaes at codespeak.net Mon Mar 2 16:13:32 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 2 Mar 2009 16:13:32 +0100 (CET) Subject: [pypy-svn] r62398 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090302151332.153FD168569@codespeak.net> Author: tverwaes Date: Mon Mar 2 16:13:28 2009 New Revision: 62398 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixed bugs Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py Mon Mar 2 16:13:28 2009 @@ -57,19 +57,19 @@ def test_video_sprite_read_write(): sprite = get_sprite() for i in range(0xFF): - sprite.set_data(byte0=i) + sprite.set_data_at(0, i) assert sprite.get_data()[0] == i for i in range(0xFF): - sprite.set_data(byte1=i) + sprite.set_data_at(1, i) assert sprite.get_data()[1] == i for i in range(0xFF): - sprite.set_data(byte2=i) + sprite.set_data_at(2, i) assert sprite.get_data()[2] == i for i in range(0xFF): - sprite.set_data(byte3=i) + sprite.set_data_at(3, i) assert sprite.get_data()[3] == i def test_size(): Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:13:28 2009 @@ -90,16 +90,7 @@ self.oam[address + 3]) def update_sprite(self, address, data): - # TODO: TEST! - # XXX why cant I use None here - # (because None == 0 in C?) - attribute = [-1] * 4 - # assign the data to the correct attribute - attribute[address % 4] = data - self.get_sprite(address).set_data(attribute[0], - attribute[1], - attribute[2], - attribute[3]) + self.get_sprite(address).set_data_at(address, data) def get_sprite(self, address): address -= constants.OAM_ADDR Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 16:13:28 2009 @@ -30,18 +30,28 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - def set_data(self, byte0=-1, byte1=-1, byte2=-1, byte3=-1): + def set_data(self, y, x, tile_number, flags): """ extracts the sprite data from an oam entry """ - if byte0 is not -1: - self.extract_y_position(byte0) - if byte1 is not -1: - self.extract_x_position(byte1) - if byte2 is not -1: - self.extract_tile_number(byte2) - if byte3 is not -1: - self.extract_attributes_and_flags(byte3) + self.extract_y_position(y) + self.extract_x_position(x) + self.extract_tile_number(tile_number) + self.extract_attributes_and_flags(flags) + + def set_data_at(self, address, data): + """ + extracts the sprite data from an oam entry + """ + position = address % 4 + if position == 0: + self.extract_y_position(data) + if position == 1: + self.extract_x_position(data) + if position == 2: + self.extract_tile_number(data) + if position == 3: + self.extract_attributes_and_flags(data) def extract_y_position(self, data): """ From cami at codespeak.net Mon Mar 2 16:14:03 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:14:03 +0100 (CET) Subject: [pypy-svn] r62399 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302151403.656CD168572@codespeak.net> Author: cami Date: Mon Mar 2 16:14:02 2009 New Revision: 62399 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: added first extraction test for the scan_sprite method Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:14:02 2009 @@ -563,8 +563,9 @@ x = sprite.x y = sprite.y if sprite.hidden: continue + if not sprite.intersects_current_line(self): continue tile = sprite.tile_number - y = self.line_y - y + 2 * SPRITE_SIZE + y = sprite.current_line_y(self) if self.control.big_sprite_size_selected: # 8x16 tile size tile_size = 15 @@ -572,7 +573,6 @@ else: # 8x8 tile size tile_size = 7 - if y < 0 or y > tile_size: continue if sprite.y_flipped: y = tile_size - y # TODO: build an object abstraction? Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 16:14:02 2009 @@ -132,9 +132,19 @@ def overlaps_on_line(self, sprite, line): return False + def get_tile_size(self, video): + if video.control.big_sprite_size_selected: + return 15 + else: + return 7 + def intersects_current_line(self, video): - return line >= self.y and line <= self.y + self.get_height() + y = self.current_line_y(video) + return y >= 0 and y <= self.get_tile_size(video) + def current_line_y(self, video): + return video.line_y - self.y + 2 * SPRITE_SIZE + def draw(self): pass From tverwaes at codespeak.net Mon Mar 2 16:15:24 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 2 Mar 2009 16:15:24 +0100 (CET) Subject: [pypy-svn] r62401 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302151524.C1C79168572@codespeak.net> Author: tverwaes Date: Mon Mar 2 16:15:24 2009 New Revision: 62401 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: removing ''new'' versions of code Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:15:24 2009 @@ -497,49 +497,6 @@ #XXX return sprites.sort(key=operator.itemgetter("x")) - - # ----------------------------------------------- - - def draw_sprites_line_new(self): - count = self.scan_sprites_new() - lastx = 176 - for index in range(176, count): - paint_sprite = self.objects[index] - x = (data >> 24) & 0xFF - flags = (data >> 12) & 0xFF - address = data & 0xFFF - if (paint_sprite.x + SPRITE_SIZE <= lastx): - self.draw_object_tile_new(paint_sprite) - else: - self.draw_overlapped_object_tile_new(x, address, flags) - lastx = paint_sprite.x - - def scan_sprites_new(self): - count = 0 - # search active objects - for sprite in self.sprites: - if sprite.hide_check(): continue - paint_sprite = PaintSprite(count, sprite, self) - self.objects[count] = paint_sprite - count += 1 - if count >= constants.OBJECTS_PER_LINE: break - self.sort_scan_sprite_new_sprite_new(count) - return count - - def sort_scan_sprite_new(self, count): - # sort objects from higher to lower priority - for index in range(count): - rightmost = index - for number in range(index+1, count): - if (self.objects[number].line_position) > \ - (self.objects[rightmost].line_position): - rightmost = number - if rightmost != index: - self.swap_object_indices(rightmost, index) - - def swap_object_indices(self, a, b): - self.objects[a], self.objects[b] = self.objects[b], self.objects[a] - # --------------------------------------------------------------------- def draw_sprites_line(self): From cami at codespeak.net Mon Mar 2 16:31:07 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:31:07 +0100 (CET) Subject: [pypy-svn] r62402 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302153107.9802C168569@codespeak.net> Author: cami Date: Mon Mar 2 16:31:07 2009 New Revision: 62402 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: compacting draw_pixels_line and conquerred the array bounds ;) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:31:07 2009 @@ -503,38 +503,24 @@ count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): - data = self.objects[index] - x = (data >> 24) & 0xFF - flags = (data >> 12) & 0xFF - address = data & 0xFFF - if (x + SPRITE_SIZE <= lastx): - self.draw_object_tile(x, address, flags) + sprite = self.objects[index] + if (sprite.x + SPRITE_SIZE <= lastx): + self.draw_object_tile(sprite.x, \ + sprite.get_tile_address(self), \ + sprite.get_attributes_and_flags()) else: - self.draw_overlapped_object_tile(x, address, flags) - lastx = x + self.draw_overlapped_object_tile(sprite.x, \ + sprite.get_tile_address(self), \ + sprite.get_attributes_and_flags()) + lastx = sprite.x def scan_sprites(self): count = 0 # search active objects for sprite in self.sprites: - x = sprite.x - y = sprite.y if sprite.hidden: continue if not sprite.intersects_current_line(self): continue - tile = sprite.tile_number - y = sprite.current_line_y(self) - if self.control.big_sprite_size_selected: - # 8x16 tile size - tile_size = 15 - tile &= 0xFE - else: - # 8x8 tile size - tile_size = 7 - if sprite.y_flipped: - y = tile_size - y - # TODO: build an object abstraction? - self.objects[count] = (x << 24) + (count << 20) + (sprite.get_attributes_and_flags() << 12) + \ - (tile << 4) + (y << 1) + self.objects[count] = sprite #.get_stupid_intermediate_data(count, self) count += 1 if count >= constants.OBJECTS_PER_LINE: break @@ -547,8 +533,8 @@ for index in range(count): highest = index for right in range(index+1, count): - if (self.objects[right] >> 20) > \ - (self.objects[highest] >> 20): + if (self.objects[right].get_tile_address(self)) > \ + (self.objects[highest].get_tile_address(self)): highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 16:31:07 2009 @@ -118,7 +118,8 @@ return self.hidden def get_tile_number(self): - return self.tile.id + #return self.tile.id + return self.tile_number def get_width(self): return SPRITE_SIZE @@ -144,7 +145,26 @@ def current_line_y(self, video): return video.line_y - self.y + 2 * SPRITE_SIZE + + def get_tile(self, video): + if video.control.big_sprite_size_selected: + return self.get_tile_number() & 0xFE + else: + return self.get_tile_number() + + def get_tile_address(self, video): + return (self.get_tile(video) << 4) + (self.get_draw_y(video) << 1) + def get_draw_y(self, video): + y = self.current_line_y(video) + if self.y_flipped: + y = self.get_tile_size(video) - y + return y + + def get_stupid_intermediate_data(self, count, video): + return (self.x << 24) + (count << 20) + \ + (self.get_attributes_and_flags() << 12) + \ + (self.get_tile_address(video)) def draw(self): pass From cami at codespeak.net Mon Mar 2 16:35:30 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:35:30 +0100 (CET) Subject: [pypy-svn] r62403 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302153530.CC748168569@codespeak.net> Author: cami Date: Mon Mar 2 16:35:30 2009 New Revision: 62403 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: now using sprite as stpid intermediate format Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:35:30 2009 @@ -505,20 +505,16 @@ for index in range(count): sprite = self.objects[index] if (sprite.x + SPRITE_SIZE <= lastx): - self.draw_object_tile(sprite.x, \ - sprite.get_tile_address(self), \ - sprite.get_attributes_and_flags()) + self.draw_object_tile(sprite) else: - self.draw_overlapped_object_tile(sprite.x, \ - sprite.get_tile_address(self), \ - sprite.get_attributes_and_flags()) + self.draw_overlapped_object_tile(sprite) lastx = sprite.x def scan_sprites(self): count = 0 # search active objects for sprite in self.sprites: - if sprite.hidden: continue + #if sprite.hidden: continue if not sprite.intersects_current_line(self): continue self.objects[count] = sprite #.get_stupid_intermediate_data(count, self) count += 1 @@ -558,32 +554,35 @@ return self.vram[address] + (self.vram[address + 1] << 8) - def draw_object_tile(self, x, address, flags): - self.draw_object(set_tile_line_call_wrapper(self), x, address, flags) + def draw_object_tile(self, sprite): + self.draw_object(set_tile_line_call_wrapper(self), sprite) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask - def draw_overlapped_object_tile(self, x, address, flags): - self.draw_object(set_overlapped_object_line_call_wrapper(self), - x, address, flags) + def draw_overlapped_object_tile(self, sprite): + self.draw_object(set_overlapped_object_line_call_wrapper(self), sprite) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask - def draw_object(self, caller, x, address, flags): - pattern = self.get_pattern(address) + def draw_object(self, caller, sprite): + #sprite.x, \ + # sprite.get_tile_address(self), \ + # sprite.get_attributes_and_flags() + + pattern = self.get_pattern(sprite.get_tile_address(self)) mask = 0 # priority - if (flags & 0x80) != 0: + if sprite.object_behind_background: #(flags & 0x80) != 0: mask |= 0x0008 # palette - if (flags & 0x10) != 0: + if sprite.palette_number: #(flags & 0x10) != 0: mask |= 0x0004 - if (flags & 0x20) != 0: - self.draw_object_flipped(x, pattern, mask, caller) + if sprite.y_flipped: #(flags & 0x20) != 0: + self.draw_object_flipped(sprite.x, pattern, mask, caller) else: - self.draw_object_normal(x, pattern, mask, caller) + self.draw_object_normal(sprite.x, pattern, mask, caller) def draw_object_flipped(self, x, pattern, mask, caller): color = (pattern << 1) & 0x0202 From arigo at codespeak.net Mon Mar 2 16:41:47 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 16:41:47 +0100 (CET) Subject: [pypy-svn] r62404 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090302154147.1C26C168467@codespeak.net> Author: arigo Date: Mon Mar 2 16:41:46 2009 New Revision: 62404 Added: pypy/extradoc/sprintinfo/leysin-winter-2009/ - copied from r61483, pypy/extradoc/sprintinfo/leysin-winter-2008/ Removed: pypy/extradoc/sprintinfo/leysin-winter-2009/planning.txt Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: Announcement. Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt Mon Mar 2 16:41:46 2009 @@ -1,43 +1,27 @@ ===================================================================== - PyPy Leysin Winter Sprint (12-19th January 2008) + PyPy Leysin Winter Sprint (14-21th April 2009) ===================================================================== .. image:: http://www.ermina.ch/002.JPG The next PyPy sprint will be in Leysin, Switzerland, for the -fifth time. This is a fully public sprint: newcomers and -topics other than those proposed below are welcome. +sixth time. This sprint will take place immediately after +Easter. This is a fully public sprint: newcomers and topics +other than those proposed below are welcome. ------------------------------ Goals and topics of the sprint ------------------------------ -* Like previous winters, the main side goal is to have fun in winter - sports :-) We can take a couple of days off for ski; at this time of - year, ski days end before 4pm, which still leaves plenty of time - to recover (er, I mean hack). - -* the overall idea of the sprint is to continue working on making PyPy ready - for general use. A few more specific tasks: - - - app-level ctypes: getting to a basically usable point - would be really nice. - - - JIT: there is a long-standing timeshifter refactoring, - towards making the JIT be more interpreter-like. Starting - it during the sprint might be a good way to share some of - the knowledge of how the JIT really works. Alternatively, - we can work on supporting ootype in the timeshifter. - - - Testing: e.g. we run various nightly test runs but the - results are not summarized in a single page yet. - - - LLVM: llvm 2 is now at version 2.1 and nicely stable - again. Our llvm backend has improved in the last few - months, but refactoring it together with the genc backend - to share code more directly would be a nice task. - -* We are open to all sorts of other tasks during the sprint, just - propose something. +* The overall idea of the sprint is to continue working on making PyPy ready + for general use. There are a few tasks left in there. In parallel, we + will continue the work on the JIT, if there is general interest. And as + usual, we are ready to add any other task -- please mention on the mailing + list what you would like to work on; the list of task is not really fixed. + +* And as usual, the main side goal is to have fun in winter sports :-) + We can take a day off for ski until Sunday, the 19th; afterwards, the + installations close. (There was quite a lot of snow this winter, so + there should be some left even though it's relatively late in the season.) ----------------------- Location & Accomodation @@ -49,32 +33,31 @@ http://www.ermina.ch/. The place has a good ADSL Internet connexion with wireless installed. You can of course arrange your own lodging anywhere (so long as you are in Leysin, you cannot be more than a -15 minute walk away from the sprint venue), but I definitely recommend +15 minutes walk away from the sprint venue), but I definitely recommend lodging there too -- you won't find a better view anywhere else (though you probably won't get much worse ones easily, either :-) -I made pre-reservations in the Chalet, so please *confirm* quickly that -you are coming so that we can adjust the reservations as appropriate. The -rate so far has been around 60 CHF a night all included in 2-person rooms, -with breakfast. There are larger rooms too (less expensive) and maybe the -possibility to get a single room if you really want to. +Please *confirm* that you are coming so that we can adjust the reservations +as appropriate. The rate so far has been around 60 CHF a night all included +in 2-person rooms, with breakfast. There are larger rooms too (less +expensive) and maybe the possibility to get a single room if you really want +to. Please register by svn: - http://codespeak.net/svn/pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt + http://codespeak.net/svn/pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt or on the pypy-sprint mailing list if you do not yet have check-in rights: http://codespeak.net/mailman/listinfo/pypy-sprint You need a Swiss-to-(insert country here) power adapter. There will be -some Swiss-to-EU adapters around - bring a EU-format power strip if you +some Swiss-to-EU adapters around -- bring a EU-format power strip if you have one. ----------- Exact times ----------- -Officially, 12th-19th January 2008. Both dates are flexible, you can -arrive or leave earlier or later. We will give introductions and -tutorials depending on who needs them, either on the 13th or the 14th. +Officially, 14-21 April 2009. The idea is that the 14th should be the arrival +day, so we won't work too much until the 15th. Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Mon Mar 2 16:41:46 2009 @@ -11,11 +11,6 @@ Name Arrive/Depart Accomodation ==================== ============== ======================= Armin Rigo -- private -Carl Friedrich Bolz 12th-19th? Ermina -Antonio Cuni 14th-19th? Ermina -Maciej Fijalkowski 11th-20th Ermina (arrive at 10pm) -Toby Watson 12th-19th Ermina -Paul deGrandis 12th-19th Ermina ==================== ============== ======================= People on the following list were present at previous sprints: @@ -23,6 +18,11 @@ ==================== ============== ===================== Name Arrive/Depart Accomodation ==================== ============== ===================== +Carl Friedrich Bolz ? ? +Antonio Cuni ? ? +Maciej Fijalkowski ? ? +Toby Watson ? ? +Paul deGrandis ? ? Christian Tismer ? ? Michael Hudson ? ? Anders Lehmann ? ? @@ -41,8 +41,6 @@ Alexander Schremmer ? ? Anders Chrigstroem ? ? Samuele Pedroni ? ? -Michael Hudson ? ? -Niko Matsakis ? ? Eric van Riet Paap ? ? Jacob Hallen ? ? Laura Creighton ? ? From cami at codespeak.net Mon Mar 2 16:41:48 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:41:48 +0100 (CET) Subject: [pypy-svn] r62405 - pypy/trunk/pypy/translator/goal Message-ID: <20090302154148.E8F871684E9@codespeak.net> Author: cami Date: Mon Mar 2 16:41:47 2009 New Revision: 62405 Modified: pypy/trunk/pypy/translator/goal/targetgbimplementation.py Log: removed the error catch Modified: pypy/trunk/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/trunk/pypy/translator/goal/targetgbimplementation.py Mon Mar 2 16:41:47 2009 @@ -1,11 +1,11 @@ -import os -import py -import pdb +#!/usr/bin/env python +import os, py, pdb, sys from pypy.lang.gameboy.gameboy_implementation import GameBoyImplementation ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" +use_rsdl = False def entry_point(argv=None): if argv is not None and len(argv) > 1: @@ -13,6 +13,7 @@ else: pos = str(9) filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" + filename=None print "loading rom: ", str(filename) gameBoy = GameBoyImplementation() try: @@ -20,10 +21,7 @@ except: print "Corrupt Cartridge" gameBoy.load_cartridge_file(str(filename), verify=False) - try: - gameBoy.mainLoop() - except: - pass + gameBoy.mainLoop() #pdb.runcall(gameBoy.mainLoop) return 0 @@ -34,13 +32,19 @@ return entry_point, None def test_target(): - entry_point(["b", ROM_PATH+"/rom9/rom9.gb"]) + entry_point(sys.argv) # STARTPOINT =================================================================== if __name__ == '__main__': - from AppKit import NSApplication - NSApplication.sharedApplication() + if use_rsdl and sys.platform == 'darwin': + from AppKit import NSApplication + NSApplication.sharedApplication() + try: + import psyco + psyco.full() + except: + pass test_target() From cami at codespeak.net Mon Mar 2 16:52:49 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:52:49 +0100 (CET) Subject: [pypy-svn] r62406 - pypy/trunk/pypy/translator/goal Message-ID: <20090302155249.1FB3F16856C@codespeak.net> Author: cami Date: Mon Mar 2 16:52:48 2009 New Revision: 62406 Modified: pypy/trunk/pypy/translator/goal/targetgbimplementation.py Log: added rom autoload again Modified: pypy/trunk/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/trunk/pypy/translator/goal/targetgbimplementation.py Mon Mar 2 16:52:48 2009 @@ -5,6 +5,8 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" +print ROM_PATH + use_rsdl = False def entry_point(argv=None): @@ -13,7 +15,6 @@ else: pos = str(9) filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" - filename=None print "loading rom: ", str(filename) gameBoy = GameBoyImplementation() try: From cami at codespeak.net Mon Mar 2 16:56:36 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 16:56:36 +0100 (CET) Subject: [pypy-svn] r62407 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302155636.29B7D168495@codespeak.net> Author: cami Date: Mon Mar 2 16:56:35 2009 New Revision: 62407 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: removing superfluous methods Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 16:56:35 2009 @@ -460,44 +460,6 @@ self.draw_sprites_line() self.draw_pixels_line() - # ----------------------------------------------- - - def draw_sprites_line_new(self): - # XXX Not in use yet. Will replace the hacky version. - sprites_on_line = self.get_drawable_sprites_on_line(self.line_y) - last_sprite = sprites_on_line[0] - last_sprite.draw() - for sprite in sprites_on_line[1:]: - if sprite.overlaps_on_line(last_sprite, self.line_y): - sprite.draw_overlapped() - else: - sprite.draw() - - def get_active_sprites_on_line(self, line_y): - found = [] - for i in range(len(self.sprites)): - if self.sprites[i].intersects_line(line_y) and \ - self.sprites[i].enabled: - found.append(self.sprites[i]) - return found - - def get_drawable_sprites_on_line(self, line_y): - sprites_on_line = self.get_active_sprites_on_line(self.line_y) - sprites_on_line = self.sort_drawable_sprites(sprites_on_line) - # only 10 sprites per line - return sprites_on_line[:constants.OBJECTS_PER_LINE] - - def sort_drawable_sprites(self, sprites): - """ - returns an ordered list of selected sprites. - The order rules are as following: - 1. order by x -coordinates, lower first - 2. order by id, lower first - """ - #XXX - return sprites.sort(key=operator.itemgetter("x")) - - # --------------------------------------------------------------------- def draw_sprites_line(self): count = self.scan_sprites() @@ -505,9 +467,9 @@ for index in range(count): sprite = self.objects[index] if (sprite.x + SPRITE_SIZE <= lastx): - self.draw_object_tile(sprite) + sprite.draw(self) else: - self.draw_overlapped_object_tile(sprite) + sprite.draw_overlapped(self) lastx = sprite.x def scan_sprites(self): @@ -516,7 +478,7 @@ for sprite in self.sprites: #if sprite.hidden: continue if not sprite.intersects_current_line(self): continue - self.objects[count] = sprite #.get_stupid_intermediate_data(count, self) + self.objects[count] = sprite count += 1 if count >= constants.OBJECTS_PER_LINE: break @@ -525,12 +487,13 @@ def sort_scan_sprite(self, count): # TODO: optimize :) - # sort objects from high to low priority + # sort objects from high to low priority using the real tile_address for index in range(count): highest = index for right in range(index+1, count): - if (self.objects[right].get_tile_address(self)) > \ - (self.objects[highest].get_tile_address(self)): + + if (self.objects[right].x) > \ + (self.objects[highest].x): highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] @@ -553,7 +516,6 @@ def get_pattern(self, address): return self.vram[address] + (self.vram[address + 1] << 8) - def draw_object_tile(self, sprite): self.draw_object(set_tile_line_call_wrapper(self), sprite) @@ -567,19 +529,15 @@ self.line[pos] = (self.line[pos] & 0x0101) | color | mask def draw_object(self, caller, sprite): - #sprite.x, \ - # sprite.get_tile_address(self), \ - # sprite.get_attributes_and_flags() - pattern = self.get_pattern(sprite.get_tile_address(self)) mask = 0 # priority - if sprite.object_behind_background: #(flags & 0x80) != 0: + if sprite.object_behind_background: mask |= 0x0008 # palette - if sprite.palette_number: #(flags & 0x10) != 0: + if sprite.palette_number: mask |= 0x0004 - if sprite.y_flipped: #(flags & 0x20) != 0: + if sprite.y_flipped: self.draw_object_flipped(sprite.x, pattern, mask, caller) else: self.draw_object_normal(sprite.x, pattern, mask, caller) Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 16:56:35 2009 @@ -160,16 +160,13 @@ if self.y_flipped: y = self.get_tile_size(video) - y return y - - def get_stupid_intermediate_data(self, count, video): - return (self.x << 24) + (count << 20) + \ - (self.get_attributes_and_flags() << 12) + \ - (self.get_tile_address(video)) - def draw(self): - pass + + def draw(self, video): + video.draw_object_tile(self) - def draw_overlapped(self): - pass + def draw_overlapped(self, video): + video.draw_overlapped_object_tile(self) + # ----------------------------------------------------------------------------- class PaintSprite(Sprite): From arigo at codespeak.net Mon Mar 2 17:13:40 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 17:13:40 +0100 (CET) Subject: [pypy-svn] r62410 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090302161340.88289168562@codespeak.net> Author: arigo Date: Mon Mar 2 17:13:37 2009 New Revision: 62410 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt Log: Move "Extra Times" earlier in the doc. Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/announcement.txt Mon Mar 2 17:13:37 2009 @@ -23,6 +23,13 @@ installations close. (There was quite a lot of snow this winter, so there should be some left even though it's relatively late in the season.) +----------- +Exact times +----------- + +Officially, 14-21 April 2009. The idea is that the 14th should be the arrival +day, so we won't work too much until the 15th. + ----------------------- Location & Accomodation ----------------------- @@ -54,10 +61,3 @@ You need a Swiss-to-(insert country here) power adapter. There will be some Swiss-to-EU adapters around -- bring a EU-format power strip if you have one. - ------------ -Exact times ------------ - -Officially, 14-21 April 2009. The idea is that the 14th should be the arrival -day, so we won't work too much until the 15th. From tverwaes at codespeak.net Mon Mar 2 17:23:01 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 2 Mar 2009 17:23:01 +0100 (CET) Subject: [pypy-svn] r62411 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090302162301.8FDFD168569@codespeak.net> Author: tverwaes Date: Mon Mar 2 17:23:01 2009 New Revision: 62411 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_register.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: refactoring control register Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Mon Mar 2 17:23:01 2009 @@ -122,7 +122,7 @@ video.control.write(0x80) - assert video.status.read() == 0x0 + assert video.status.read() == 0x02 video.line_y = value -1 video.status.write(0xFF, write_all=True) Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py Mon Mar 2 17:23:01 2009 @@ -9,7 +9,7 @@ def get_control_register(): video = get_video() - return ControlRegister(Window(video), Background(video)) + return ControlRegister(video, Window(video), Background(video)) def get_status_register(): return StatusRegister(get_video()) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 17:23:01 2009 @@ -46,7 +46,7 @@ self.window = Window(self) self.background = Background(self) self.status = StatusRegister(self) - self.control = ControlRegister(self.window, + self.control = ControlRegister(self, self.window, self.background) self.memory = memory self.create_tile_maps() @@ -221,24 +221,8 @@ return self.control.read() def set_control(self, data): - value = data & 0x80 - if self.control.lcd_enabled != bool(value): - self.reset_control(value) - self.window.update_line_y(data) self.control.write(data) - def reset_control(self, value): - # NOTE: do not reset LY=LYC flag (bit 2) of the STAT register (Mr. Do!) - self.line_y = 0 - if value != 0: - self.status.set_mode(2) - self.cycles = constants.MODE_2_TICKS - self.display = False - else: - self.status.set_mode(0) - self.cycles = constants.MODE_1_TICKS - self.clear_frame() - def get_status(self): return self.status.read(extend=True) Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Mon Mar 2 17:23:01 2009 @@ -84,7 +84,8 @@ Bit 1 - OBJ (Sprite) Display Enable (0=Off, 1=On) Bit 0 - BG Display (for CGB see below) (0=Off, 1=On) """ - def __init__(self, window, background): + def __init__(self, video, window, background): + self.video = video self.window = window self.background = background self.reset() @@ -110,19 +111,37 @@ value += int(self.sprites_enabled) << 1 value += int(self.background.enabled) << 0 return value + + def switch_lcd_enabled(self): + self.lcd_enabled = not self.lcd_enabled + self.video.cycles = 0 + self.video.line_y = 0 + if self.lcd_enabled: + self.video.status.set_mode(2) + self.video.cycles = constants.MODE_2_TICKS + self.video.display = False + else: + self.video.status.set_mode(0) + self.video.cycles = constants.MODE_1_TICKS + self.video.clear_frame() def write(self, value): - self.lcd_enabled = bool(value & (1 << 7)) + if self.lcd_enabled != bool(value & (1 << 7)): + self.switch_lcd_enabled() + + was_enabled = self.window.enabled + self.window.enabled = bool(value & (1 << 5)) + if not was_enabled and self.window.enabled: + self.window.switch_on() + self.window.upper_tile_map_selected = bool(value & (1 << 6)) - self.window.enabled = bool(value & (1 << 5)) self.background_and_window_lower_tile_data_selected = \ bool(value & (1 << 4)) self.background.upper_tile_map_selected = bool(value & (1 << 3)) self.big_sprite_size_selected = bool(value & (1 << 2)) self.sprites_enabled = bool(value & (1 << 1)) self.background.enabled = bool(value & (1 << 0)) - - + def get_selected_tile_data_space(self): if self.background_and_window_lower_tile_data_selected: return constants.VRAM_DATA_A Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 17:23:01 2009 @@ -237,11 +237,9 @@ self.enabled = False self.upper_tile_map_selected = False - def update_line_y(self, data): - # don't draw window if it was not enabled and not being drawn before - if not self.enabled and (data & 0x20) != 0 and \ - self.line_y == 0 and self.video.line_y > self.y: - self.line_y = GAMEBOY_SCREEN_HEIGHT + def switch_on(self): + if self.line_y == 0 and self.video.line_y > self.y: + self.line_y = GAMEBOY_SCREEN_HEIGHT def get_tile_map_space(self): #if (self.control.read() & mask) != 0: From cami at codespeak.net Mon Mar 2 17:29:04 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 17:29:04 +0100 (CET) Subject: [pypy-svn] r62412 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090302162904.A12B5168562@codespeak.net> Author: cami Date: Mon Mar 2 17:29:04 2009 New Revision: 62412 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: compacting draw_pixels_line and conquerred the array bounds ;) Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Mon Mar 2 17:29:04 2009 @@ -116,9 +116,12 @@ value = 0xF6 video.control.lcd_enabled = False + import pdb + pdb.set_trace() video.write(0xFF45, value) assert video.line_y_compare == value + assert video.status.read() == 0x0 video.control.write(0x80) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 17:29:04 2009 @@ -53,12 +53,20 @@ self.create_sprites() self.reset() + # ----------------------------------------------------------------------- + def create_tile_maps(self): # create the maxumal possible sprites - self.tile_map_0 = [None] * 32 * 32 - self.tile_map_1 = [None] * 32 * 32 + self.tile_map_0 = self.create_tile_map(32 * 32) + self.tile_map_1 = self.create_tile_map(32 * 32) self.tile_maps = [self.tile_map_0, self.tile_map_1] + def create_tile_map(self, size): + tile_map = [None] * size + for i in range(size): + tile_map[i] = Tile(self) + return tile_map + def update_tile(self, address, data): # XXX to implement #self.get_tile(address).set_data(); @@ -75,6 +83,7 @@ # tile.reset() pass + # ----------------------------------------------------------------------- def create_sprites(self): self.sprites = [None] * 40 for i in range(40): @@ -102,6 +111,8 @@ #for sprite in self.sprites: # sprite.reset() pass + + # ----------------------------------------------------------------------- def reset(self): self.control.reset() @@ -410,7 +421,7 @@ self.update_tile(address, data) def get_vram(self, address): - #self.get_tile(address).get_data()[address % 4] + #return self.get_tile(address).get_data()[address % 4] return self.vram[address - constants.VRAM_ADDR] # emulation ---------------------------------------------------------------- @@ -457,15 +468,14 @@ lastx = sprite.x def scan_sprites(self): - count = 0 # search active objects + count = 0 for sprite in self.sprites: - #if sprite.hidden: continue - if not sprite.intersects_current_line(self): continue - self.objects[count] = sprite - count += 1 - if count >= constants.OBJECTS_PER_LINE: - break + if sprite.is_shown_on_current_line(self): + self.objects[count] = sprite + count += 1 + if count >= constants.OBJECTS_PER_LINE: + break self.sort_scan_sprite(count) return count @@ -475,9 +485,7 @@ for index in range(count): highest = index for right in range(index+1, count): - - if (self.objects[right].x) > \ - (self.objects[highest].x): + if self.objects[right].x > self.objects[highest].x: highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 17:29:04 2009 @@ -130,9 +130,6 @@ else: return SPRITE_SIZE - def overlaps_on_line(self, sprite, line): - return False - def get_tile_size(self, video): if video.control.big_sprite_size_selected: return 15 @@ -143,6 +140,9 @@ y = self.current_line_y(video) return y >= 0 and y <= self.get_tile_size(video) + def is_shown_on_current_line(self, video): + return not self.hidden and self.intersects_current_line(video) + def current_line_y(self, video): return video.line_y - self.y + 2 * SPRITE_SIZE @@ -198,7 +198,8 @@ class Tile(object): - def __init__(self): + def __init__(self, video): + self.video = video self.reset() def reset(self): From cami at codespeak.net Mon Mar 2 17:34:05 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 17:34:05 +0100 (CET) Subject: [pypy-svn] r62413 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090302163405.91AF1168562@codespeak.net> Author: cami Date: Mon Mar 2 17:34:05 2009 New Revision: 62413 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/video.py Log: renaming OBJECTS_PER_LINE to SPRITES_PER_LINE Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Mon Mar 2 17:34:05 2009 @@ -143,7 +143,7 @@ MODE_1_END_TICKS = 1 # V-Blank Line 153 # Objects per Line -OBJECTS_PER_LINE = 10 +SPRITES_PER_LINE = 10 # LCD Color Palette #COLOR_MAP =[ Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 17:34:05 2009 @@ -139,9 +139,9 @@ self.oam = [0] * constants.OAM_SIZE self.reset_all_sprites() - #XXX remove those dumb helper "objects" + #XXX remove those dumb helper "shown_sprites" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.objects = [0] * constants.OBJECTS_PER_LINE + self.shown_sprites = [0] * constants.SPRITES_PER_LINE self.palette = [0] * 1024 self.frames = 0 @@ -460,7 +460,7 @@ count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): - sprite = self.objects[index] + sprite = self.shown_sprites[index] if (sprite.x + SPRITE_SIZE <= lastx): sprite.draw(self) else: @@ -468,27 +468,27 @@ lastx = sprite.x def scan_sprites(self): - # search active objects + # search active shown_sprites count = 0 for sprite in self.sprites: if sprite.is_shown_on_current_line(self): - self.objects[count] = sprite + self.shown_sprites[count] = sprite count += 1 - if count >= constants.OBJECTS_PER_LINE: + if count >= constants.SPRITES_PER_LINE: break self.sort_scan_sprite(count) return count def sort_scan_sprite(self, count): # TODO: optimize :) - # sort objects from high to low priority using the real tile_address + # sort shown_sprites from high to low priority using the real tile_address for index in range(count): highest = index for right in range(index+1, count): - if self.objects[right].x > self.objects[highest].x: + if self.shown_sprites[right].x > self.shown_sprites[highest].x: highest = right - self.objects[index], self.objects[highest] = \ - self.objects[highest], self.objects[index] + self.shown_sprites[index], self.shown_sprites[highest] = \ + self.shown_sprites[highest], self.shown_sprites[index] def draw_tiles(self, x, tile_map, tile_data): while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: From arigo at codespeak.net Mon Mar 2 17:41:57 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Mar 2009 17:41:57 +0100 (CET) Subject: [pypy-svn] r62414 - in pypy/branch/pyjitpl5/pypy/jit: backend/x86 metainterp Message-ID: <20090302164157.60A2D168576@codespeak.net> Author: arigo Date: Mon Mar 2 17:41:56 2009 New Revision: 62414 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Minimal "fixes". Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Mon Mar 2 17:41:56 2009 @@ -200,6 +200,10 @@ def _binaryop_ovf(asmop, can_swap=False): def genop_binary_ovf(self, op, arglocs, result_loc): getattr(self.mc, asmop)(arglocs[0], arglocs[1]) + if we_are_translated(): + # XXX setting the lowest byte of _exception_addr to 0 or 1 + # does not work after translation + XXX # XXX think about CMOV instead of SETO, this would avoid # a mess in detecting an exception self.mc.SETO(heap8(self._exception_addr)) @@ -238,7 +242,7 @@ genop_int_mul_ovf = _binaryop_ovf("IMUL", True) genop_int_sub_ovf = _binaryop_ovf("SUB") - genop_int_add_ovf = _binaryop_ovf("ADD") + genop_int_add_ovf = _binaryop_ovf("ADD", True) genop_int_lt = _cmpop("L", "G") genop_int_le = _cmpop("LE", "GE") Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Mon Mar 2 17:41:56 2009 @@ -12,7 +12,7 @@ from pypy.jit.metainterp.resoperation import rop, opname -MALLOC_VARSIZE = rop._CANRAISE_LAST + 1 +MALLOC_VARSIZE = rop._LAST + 1 # esi edi and ebp can be added to this list, provided they're correctly # saved and restored @@ -928,7 +928,7 @@ self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] -oplist = [None] * rop._CANRAISE_LAST +oplist = [None] * rop._LAST for name, value in RegAlloc.__dict__.iteritems(): if name.startswith('consider_'): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Mon Mar 2 17:41:56 2009 @@ -159,6 +159,7 @@ INT_MUL_OVF = 112 INT_NEG_OVF = 113 _CANRAISE_LAST = 119 # ----- end of can_raise operations ----- + _LAST = 119 # for the backend to add more internal operations opname = {} # mapping numbers to the original names, for debugging From cami at codespeak.net Mon Mar 2 18:20:09 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Mar 2009 18:20:09 +0100 (CET) Subject: [pypy-svn] r62417 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090302172009.08A78168457@codespeak.net> Author: cami Date: Mon Mar 2 18:20:08 2009 New Revision: 62417 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_register.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: rewrote var big_sprite_size_selected to big_sprites Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Mon Mar 2 18:20:08 2009 @@ -50,7 +50,7 @@ assert len(video.vram) == constants.VRAM_SIZE assert len(video.oam) == constants.OAM_SIZE assert len(video.line) == 176 - assert len(video.objects) == constants.OBJECTS_PER_LINE + assert len(video.objects) == constants.big_sprites assert len(video.palette) == 1024 assert video.frames == 0 assert video.frame_skip == 0 Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Mon Mar 2 18:20:08 2009 @@ -100,6 +100,10 @@ def update_sprite(self, address, data): self.get_sprite(address).set_data_at(address, data) + + def update_sprite_size(self): + for sprite in self.sprites: + sprite.big_size = self.control.big_sprites def get_sprite(self, address): address -= constants.OAM_ADDR Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Mon Mar 2 18:20:08 2009 @@ -96,7 +96,7 @@ self.window.enabled = False self.background_and_window_lower_tile_data_selected = True self.background.upper_tile_map_selected = False - self.big_sprite_size_selected = False + self.big_sprites = False self.sprites_enabled = False self.background.enabled = True @@ -107,7 +107,7 @@ value += int(self.window.enabled) << 5 value += int(self.background_and_window_lower_tile_data_selected) << 4 value += int(self.background.upper_tile_map_selected) << 3 - value += int(self.big_sprite_size_selected) << 2 + value += int(self.big_sprites) << 2 value += int(self.sprites_enabled) << 1 value += int(self.background.enabled) << 0 return value @@ -126,9 +126,10 @@ self.video.clear_frame() def write(self, value): + previous_big_sprites = self.big_sprites if self.lcd_enabled != bool(value & (1 << 7)): self.switch_lcd_enabled() - + was_enabled = self.window.enabled self.window.enabled = bool(value & (1 << 5)) if not was_enabled and self.window.enabled: @@ -138,9 +139,12 @@ self.background_and_window_lower_tile_data_selected = \ bool(value & (1 << 4)) self.background.upper_tile_map_selected = bool(value & (1 << 3)) - self.big_sprite_size_selected = bool(value & (1 << 2)) + self.big_sprites = bool(value & (1 << 2)) self.sprites_enabled = bool(value & (1 << 1)) self.background.enabled = bool(value & (1 << 0)) + + if previous_big_sprites != self.big_sprites: + video.update_sprite_size() def get_selected_tile_data_space(self): if self.background_and_window_lower_tile_data_selected: Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Mon Mar 2 18:20:08 2009 @@ -130,15 +130,15 @@ else: return SPRITE_SIZE - def get_tile_size(self, video): - if video.control.big_sprite_size_selected: + def get_tile_size(self): + if self.big_size: return 15 else: return 7 def intersects_current_line(self, video): y = self.current_line_y(video) - return y >= 0 and y <= self.get_tile_size(video) + return y >= 0 and y <= self.get_tile_size() def is_shown_on_current_line(self, video): return not self.hidden and self.intersects_current_line(video) @@ -147,7 +147,7 @@ return video.line_y - self.y + 2 * SPRITE_SIZE def get_tile(self, video): - if video.control.big_sprite_size_selected: + if video.control.big_sprites: return self.get_tile_number() & 0xFE else: return self.get_tile_number() @@ -158,7 +158,7 @@ def get_draw_y(self, video): y = self.current_line_y(video) if self.y_flipped: - y = self.get_tile_size(video) - y + y = self.get_tile_size() - y return y def draw(self, video): From afa at codespeak.net Mon Mar 2 19:37:35 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 2 Mar 2009 19:37:35 +0100 (CET) Subject: [pypy-svn] r62421 - pypy/trunk/pypy/rpython/module Message-ID: <20090302183735.A315A16857F@codespeak.net> Author: afa Date: Mon Mar 2 19:37:33 2009 New Revision: 62421 Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py Log: Add float times support in os.stat() on Linux platform. Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Mon Mar 2 19:37:33 2009 @@ -9,15 +9,24 @@ from pypy.rpython import extregistry from pypy.rpython.extfunc import register_external from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rpython.tool import rffi_platform as platform from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo # Support for float times is here. -# Note: For the moment, only Windows implement float times. -# Things are a bit simpler there because 'struct stat' is not used. -TIMESPEC = None -if sys.platform == 'win32': +# - ALL_STAT_FIELDS contains Float fields if the system can retrieve +# sub-second timestamps. +# - TIMESPEC is defined when the "struct stat" contains st_atim field. + +if sys.platform == 'linux2': + TIMESPEC = platform.Struct('struct timespec', + [('tv_sec', rffi.TIME_T), + ('tv_nsec', rffi.LONG)]) +else: + TIMESPEC = None + +if sys.platform == 'win32' or TIMESPEC is not None: ModTime = lltype.Float else: ModTime = lltype.Signed @@ -52,22 +61,7 @@ STAT_FIELD_NAMES = [_name for (_name, _TYPE) in ALL_STAT_FIELDS if _name in STAT_FIELD_TYPES] -def _expand(lst, originalname, timespecname): - if TIMESPEC is not None: - XXX # code not used right now - for i, (_name, _TYPE) in enumerate(lst): - if _name == originalname: - # replace the 'st_atime' field of type rffi.DOUBLE - # with a field 'st_atim' of type 'struct timespec' - lst[i] = (timespecname, TIMESPEC.TO) - break - -LL_STAT_FIELDS = STAT_FIELDS[:] -_expand(LL_STAT_FIELDS, 'st_atime', 'st_atim') -_expand(LL_STAT_FIELDS, 'st_mtime', 'st_mtim') -_expand(LL_STAT_FIELDS, 'st_ctime', 'st_ctim') - -del _expand, _name, _TYPE +del _name, _TYPE # For OO backends, expose only the portable fields (the first 10). PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS] @@ -145,14 +139,38 @@ INCLUDES = ['sys/types.h', 'sys/stat.h', 'unistd.h'] compilation_info = ExternalCompilationInfo( + # This must be set to 64 on some systems to enable large file support. pre_include_bits = ['#define _FILE_OFFSET_BITS 64'], includes = INCLUDES ) if sys.platform != 'win32': - from pypy.rpython.tool import rffi_platform as platform + + LL_STAT_FIELDS = STAT_FIELDS[:] + + if TIMESPEC is not None: + class CConfig_for_timespec: + _compilation_info_ = compilation_info + TIMESPEC = TIMESPEC + + TIMESPEC = lltype.Ptr( + platform.configure(CConfig_for_timespec)['TIMESPEC']) + + def _expand(lst, originalname, timespecname): + for i, (_name, _TYPE) in enumerate(lst): + if _name == originalname: + # replace the 'st_atime' field of type rffi.DOUBLE + # with a field 'st_atim' of type 'struct timespec' + lst[i] = (timespecname, TIMESPEC.TO) + break + + _expand(LL_STAT_FIELDS, 'st_atime', 'st_atim') + _expand(LL_STAT_FIELDS, 'st_mtime', 'st_mtim') + _expand(LL_STAT_FIELDS, 'st_ctime', 'st_ctim') + + del _expand + class CConfig: - # This must be set to 64 on some systems to enable large file support. _compilation_info_ = compilation_info STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS) config = platform.configure(CConfig) From fijal at codespeak.net Mon Mar 2 22:36:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Mar 2009 22:36:36 +0100 (CET) Subject: [pypy-svn] r62426 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/x86 backend/x86/test metainterp metainterp/test Message-ID: <20090302213636.EF17D169E0A@codespeak.net> Author: fijal Date: Mon Mar 2 22:36:35 2009 New Revision: 62426 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Log: Re-introduce list optimizations. Notable the lazy list (of FixedList) and virtual list (also for FixedList only) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Mon Mar 2 22:36:35 2009 @@ -94,6 +94,7 @@ 'getfield_raw' : (('ptr', 'fieldname'), 'intorptr'), 'setarrayitem_gc' : (('ptr', 'int', 'int', 'intorptr'), None), 'getarrayitem_gc' : (('ptr', 'int', 'int'), 'intorptr'), + 'arraylen_gc' : (('ptr', 'int'), 'int'), 'call_ptr' : (('ptr', 'varargs'), 'ptr'), 'call__4' : (('ptr', 'varargs'), 'int'), 'call_void' : (('ptr', 'varargs'), None), @@ -759,6 +760,10 @@ array = array._obj.container return array.getitem(index) + def op_arraylen_gc(self, array, arraydesc): + array = array._obj.container + return len(array.items) + def op_setarrayitem_gc(self, array, arraydesc, index, newvalue): ITEMTYPE = symbolic.Size2Type[arraydesc/2] array = array._obj.container Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Mon Mar 2 22:36:35 2009 @@ -381,6 +381,10 @@ basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) self.mc.MOV(resloc, addr_add_const(base_loc, ofs_length)) + def genop_arraylen_gc(self, op, arglocs, resloc): + base_loc, ofs_loc = arglocs + self.mc.MOV(resloc, addr_add(base_loc, imm(0))) + def genop_strgetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Mon Mar 2 22:36:35 2009 @@ -742,12 +742,17 @@ return res - def consider_new_array(self, op): - arraydescr = op.args[0].getint() + def _unpack_arraydescr(self, arraydescr): + if arraydescr < 0: + arraydescr = ~arraydescr assert arraydescr size_of_field = arraydescr >> 16 ofs = arraydescr & 0xffff - return self._malloc_varsize(0, ofs, 0, size_of_field, op.args[1], + return size_of_field, ofs + + def consider_new_array(self, op): + size_of_field, basesize = self._unpack_arraydescr(op.args[0].getint()) + return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[1], op.result) def consider_oononnull(self, op): @@ -781,10 +786,7 @@ [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) def consider_setarrayitem_gc(self, op): - arraydescr = op.args[1].getint() - assert arraydescr - scale = arraydescr >> 16 - ofs = arraydescr & 0xffff + scale, ofs = self._unpack_arraydescr(op.args[1].getint()) assert scale == 2 args = [op.args[0], op.args[2], op.args[3]] base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) @@ -804,11 +806,7 @@ [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) def consider_getarrayitem_gc(self, op): - arraydescr = op.args[1].getint() - assert arraydescr - scale = arraydescr >> 16 - ofs = arraydescr & 0xffff - assert scale == 2 + scale, ofs = self._unpack_arraydescr(op.args[1].getint()) args = [op.args[0], op.args[2]] base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[2], args) @@ -870,10 +868,18 @@ def consider_strlen(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - self.eventually_free_var(op.args[0]) + self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] + def consider_arraylen_gc(self, op): + _, ofs = self._unpack_arraydescr(op.args[1].getint()) + base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + self.eventually_free_vars(op.args) + result_loc, more_ops = self.force_allocate_reg(op.result, []) + return ops0 + more_ops + [Perform(op, [base_loc, imm(ofs)], + result_loc)] + def consider_strgetitem(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Mon Mar 2 22:36:35 2009 @@ -388,7 +388,10 @@ while itemsize != 1: itemsize >>= 1 counter += 1 - return basesize + counter * 0x10000 + res = basesize + counter * 0x10000 + if isinstance(A.OF, lltype.Ptr): + res = ~res + return res @staticmethod def fielddescrof(S, fieldname): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py Mon Mar 2 22:36:35 2009 @@ -1,8 +1,9 @@ -from pypy.jit.metainterp.test.test_slist import ListTests +from pypy.jit.metainterp.test import test_slist, test_dlist from pypy.jit.backend.x86.test.test_basic import Jit386Mixin -class TestSList(Jit386Mixin, ListTests): +class TestSList(Jit386Mixin, test_slist.ListTests, test_dlist.ListTests): # for the individual tests see # ====> ../../../metainterp/test/test_slist.py + # ====> ../../../metainterp/test/test_dlist.py pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_tl.py Mon Mar 2 22:36:35 2009 @@ -6,7 +6,7 @@ class TestTL(Jit386Mixin, ToyLanguageTests): # for the individual tests see - # ====> ../../test/test_tl.py + # ====> ../../../metainterp/test/test_tl.py pass class TestTLC(Jit386Mixin): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Mon Mar 2 22:36:35 2009 @@ -616,9 +616,9 @@ self.emit('jit_merge_point') assert ([self.var_position(i) for i in op.args[2:]] == range(0, 2*(len(op.args) - 2), 2)) -## for i in range(2, len(op.args)): -## arg = op.args[i] -## self._eventualy_builtin(arg) + for i in range(2, len(op.args)): + arg = op.args[i] + #self._eventualy_builtin(arg) elif op.args[0].value == 'can_enter_jit': self.emit('can_enter_jit') self.emit_varargs(op.args[2:]) @@ -713,7 +713,7 @@ def handle_list_call(self, op, oopspec_name, args, TP): if not (oopspec_name.startswith('list.') or oopspec_name == 'newlist'): return False - if hasattr(TP, '_ll_resize'): + if hasattr(TP.TO, '_ll_resize'): return False # non-resizable lists: they are just arrays ARRAY = TP.TO @@ -757,7 +757,11 @@ # if (oopspec_name == 'list.len' or oopspec_name == 'list.len_foldable'): - xxx # ... 'arraylen_gc' + self.emit('arraylen_gc') + self.emit(self.var_position(args[0])) + self.emit(self.const_position(arraydescr)) + self.register_var(op.result) + return True # return False Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Mon Mar 2 22:36:35 2009 @@ -1,7 +1,7 @@ from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, ResOperation) -from pypy.jit.metainterp.history import Options +from pypy.jit.metainterp.history import Options, AbstractValue from pypy.jit.metainterp.specnode import (FixedClassSpecNode, #FixedListSpecNode, VirtualInstanceSpecNode, @@ -9,12 +9,25 @@ NotSpecNode, DelayedSpecNode, SpecNodeWithBox, + DelayedFixedListSpecNode, #DelayedListSpecNode, + VirtualFixedListSpecNode, #VirtualListSpecNode, ) from pypy.rlib.objectmodel import we_are_translated #from pypy.jit.metainterp.codewriter import ListDescr + +class FixedList(AbstractValue): + def __init__(self, arraydescr): + self.arraydescr = arraydescr + + def equals(self, other): + # it's all really impossible, it should default to True simply + assert isinstance(other, FixedList) + assert other.arraydescr == self.arraydescr + return True + class CancelInefficientLoop(Exception): pass @@ -33,8 +46,8 @@ self.allocations = [] self.setfields = [] # the same as above, but for lists and for running setitem -## self.list_allocations = [] -## self.setitems = [] + self.list_allocations = [] + self.setitems = [] def deal_with_box(self, box, nodes, liveboxes, memo): if isinstance(box, Const) or box not in nodes: @@ -49,30 +62,28 @@ virtual = instnode.virtual virtualized = instnode.virtualized if virtual: -## if isinstance(instnode.cls.source, ListDescr): -## ld = instnode.cls.source -## assert isinstance(ld, ListDescr) -## alloc_offset = len(self.list_allocations) -## malloc_func = ld.malloc_func -## assert instnode.cursize != -1 -## self.list_allocations.append((malloc_func, -## instnode.cursize)) -## res = (alloc_offset + 1) << 16 -## else: - if 1: + if isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + assert isinstance(ld, FixedList) + alloc_offset = len(self.list_allocations) + if instnode.cursize == -1: + xxx + self.list_allocations.append((ConstInt(ld.arraydescr), + instnode.cursize)) + res = (alloc_offset + 1) << 16 + else: alloc_offset = len(self.allocations) self.allocations.append(instnode.cls.source.getint()) res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): num = self.deal_with_box(node.source, nodes, liveboxes, memo) -## if isinstance(instnode.cls.source, ListDescr): -## ld = instnode.cls.source -## x = (alloc_offset + 1) << 16 -## assert ofs < instnode.cursize -## self.setitems.append((ld.setfunc, x, ofs, num)) -## else: - if 1: + if isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + x = (alloc_offset + 1) << 16 + assert isinstance(ld, FixedList) + self.setitems.append((x, ConstInt(ld.arraydescr), ofs, num)) + else: self.setfields.append((alloc_offset, ofs, num)) elif virtualized: res = ~len(liveboxes) @@ -104,8 +115,8 @@ self.cleanfields = {} self.dirtyfields = {} self.expanded_fields = {} + self.cursize = -1 #self.origsize = -1 - #self.cursize = -1 def is_nonzero(self): return self.cls is not None or self.nonzero @@ -142,16 +153,10 @@ not self.expanded_fields): if self.cls is None: return NotSpecNode() -## if isinstance(known_class, ListDescr): -## return FixedListSpecNode(known_class) + if isinstance(known_class, FixedList): + return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: -## if (isinstance(known_class, ListDescr) -## and self.cursize != other.origsize): -## # or DelayedListSpecNode, later on -## self.escaped = True -## other.escaped = True -## return FixedListSpecNode(known_class) fields = [] if self is other: d = other.curfields.copy() @@ -168,9 +173,9 @@ self.origfields[ofs] = InstanceNode(node.source.clonebox()) specnode = NotSpecNode() fields.append((ofs, specnode)) -## if isinstance(known_class, ListDescr): -## return VirtualListSpecNode(known_class, fields, -## other.cursize) + if isinstance(known_class, FixedList): + return VirtualFixedListSpecNode(known_class, fields, + other.cursize) return VirtualInstanceSpecNode(known_class, fields) if not other.virtualized and self.expanded_fields: fields = [] @@ -179,8 +184,8 @@ for ofs in lst: specnode = SpecNodeWithBox(self.origfields[ofs].source) fields.append((ofs, specnode)) -## if isinstance(known_class, ListDescr): -## return DelayedListSpecNode(known_class, fields) + if isinstance(known_class, FixedList): + return DelayedFixedListSpecNode(known_class, fields) return DelayedSpecNode(known_class, fields) else: assert self is other @@ -213,7 +218,6 @@ if self.virtualized: flags += 'V' return "" % (self.source, flags) - def optimize_loop(options, old_loops, loop): if not options.specialize: # for tests only if old_loops: @@ -315,6 +319,16 @@ self.nodes[box] = instnode self.first_escaping_op = False continue + elif opnum == rop.NEW_ARRAY: + box = op.result + instnode = InstanceNode(box, escaped=False) + instnode.cls = InstanceNode(FixedList(op.args[0].getint())) + self.nodes[box] = instnode + if self.getnode(op.args[1]).const: + instnode.cursize = op.args[1].getint() + else: + instnode.escaped = True + continue ## elif opname == 'newlist': ## box = op.results[0] ## instnode = InstanceNode(box, escaped=False) @@ -341,6 +355,35 @@ ## instnode.cursize = size ## instnode.origsize = size ## continue + elif opnum == rop.GETARRAYITEM_GC: + instnode = self.getnode(op.args[0]) + if instnode.cls is None: + instnode.cls = InstanceNode(FixedList(op.args[1].getint())) + fieldbox = op.args[2] + if self.getnode(fieldbox).const: + item = self.getsource(fieldbox).getint() + assert item >= 0 # XXX + self.find_nodes_getfield(instnode, item, op.result) + else: + instnode.escaped = True + self.nodes[op.result] = InstanceNode(op.result, + escaped=True) + continue + elif opnum == rop.SETARRAYITEM_GC: + instnode = self.getnode(op.args[0]) + if instnode.cls is None: + instnode.cls = InstanceNode(FixedList(op.args[1].getint())) + fieldbox = op.args[2] + if self.getnode(fieldbox).const: + item = self.getsource(fieldbox).getint() + assert item >= 0 # XXX + self.find_nodes_setfield(instnode, item, + self.getnode(op.args[3])) + else: + instnode.escaped = True + self.dependency_graph.append((instnode, + self.getnode(op.args[3]))) + continue elif opnum == rop.SETFIELD_GC: instnode = self.getnode(op.args[0]) fieldbox = op.args[1] @@ -547,11 +590,13 @@ rev_boxes[fieldbox] = len(liveboxes) liveboxes.append(fieldbox) fieldindex = ~rev_boxes[fieldbox] -## if node.cls is not None and isinstance(node.cls.source, ListDescr): -## f = node.cls.source.setfunc -## storage.setitems.append((f, index, ofs, fieldindex)) -## else: - if 1: + if (node.cls is not None and + isinstance(node.cls.source, FixedList)): + ld = node.cls.source + assert isinstance(ld, FixedList) + ad = ConstInt(ld.arraydescr) + storage.setitems.append((index, ad, ofs, fieldindex)) + else: storage.setfields.append((index, ofs, fieldindex)) if not we_are_translated(): items = [box for box in liveboxes if isinstance(box, Box)] @@ -649,6 +694,9 @@ op = ResOperation(rop.JUMP, args, None) newoperations.append(op) continue +## elif opnum == rop.ARRAYLEN_GC: +## instnode = self.nodes[op.args[0]] + ## elif opname == 'guard_builtin': ## instnode = self.nodes[op.args[0]] ## if instnode.cls is None: @@ -705,6 +753,13 @@ continue # otherwise we need this getfield, but it does not # invalidate caches + elif opnum == rop.GETARRAYITEM_GC: + instnode = self.nodes[op.args[0]] + ofsbox = self.getsource(op.args[2]) + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() + if self.optimize_getfield(instnode, ofs, op.result): + continue ## elif opname == 'getitem': ## instnode = self.nodes[op.args[1]] ## ofsbox = self.getsource(op.args[2]) @@ -719,6 +774,12 @@ instnode.virtual = True assert instnode.cls is not None continue + elif opnum == rop.NEW_ARRAY: + instnode = self.nodes[op.result] + if not instnode.escaped: + instnode.virtual = True + instnode.cursize = op.args[1].getint() + continue ## elif opname == 'newlist': ## instnode = self.nodes[op.results[0]] ## assert isinstance(instnode.cls.source, ListDescr) @@ -765,6 +826,16 @@ ofs = op.args[1].getint() self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue + elif opnum == rop.SETARRAYITEM_GC: + instnode = self.nodes[op.args[0]] + if instnode.cls is None: + instnode.cls = InstanceNode(FixedList(op.args[1].getint())) + ofsbox = self.getsource(op.args[2]) + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() + valuenode = self.getnode(op.args[3]) + self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) + continue ## elif opname == 'setitem': ## instnode = self.nodes[op.args[1]] ## valuenode = self.getnode(op.args[3]) @@ -815,7 +886,8 @@ self.nodes[box] = instnode continue elif (not op.has_no_side_effect() - and opnum != rop.SETFIELD_GC): + and opnum != rop.SETFIELD_GC and + opnum != rop.SETARRAYITEM_GC): # the setfield operations do not clean up caches, although # they have side effects self.cleanup_field_caches(newoperations) @@ -835,13 +907,15 @@ for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): # XXX move to InstanceNode eventually -## if (node.cls is not None and -## isinstance(node.cls.source, ListDescr)): -## newoperations.append(ResOperation('setitem', -## [node.cls.source.setfunc, node.source, -## ConstInt(ofs), valuenode.source], [])) -## else: - if 1: + if (node.cls is not None and + isinstance(node.cls.source, FixedList)): + ld = node.cls.source + assert isinstance(ld, FixedList) + ad = ConstInt(ld.arraydescr) + newoperations.append(ResOperation(rop.SETARRAYITEM_GC, + [node.source, ad, ConstInt(ofs), valuenode.source], + None)) + else: newoperations.append(ResOperation(rop.SETFIELD_GC, [node.source, ConstInt(ofs), valuenode.source], None)) node.dirtyfields = {} @@ -879,12 +953,11 @@ new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode) -def box_from_index(allocated_boxes, ## allocated_lists, - boxes_from_frame, index): +def box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index): if index < 0: return boxes_from_frame[~index] -## if index > 0xffff: -## return allocated_lists[(index - 1) >> 16] + if index > 0xffff: + return allocated_lists[(index - 1) >> 16] return allocated_boxes[index] def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): @@ -904,29 +977,29 @@ [sizebox, vtablebox], 'ptr', False) allocated_boxes.append(instbox) -## for malloc_func, lgt in storage.list_allocations: -## sizebox = ConstInt(lgt) -## [listbox] = history.execute_and_record('newlist', -## [malloc_func, sizebox], -## 'ptr', False) -## allocated_lists.append(listbox) + for ad, lgt in storage.list_allocations: + sizebox = ConstInt(lgt) + listbox = history.execute_and_record(rop.NEW_ARRAY, + [ad, sizebox], + 'ptr', False) + allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: - fieldbox = box_from_index(allocated_boxes, ## allocated_lists, + fieldbox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) - box = box_from_index(allocated_boxes, ## allocated_lists, + box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) history.execute_and_record(rop.SETFIELD_GC, [box, ConstInt(ofs), fieldbox], 'void', False) -## for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: -## itembox = box_from_index(allocated_boxes, allocated_lists, -## boxes_from_frame, index_in_arglist) -## box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, -## index_in_alloc) -## history.execute_and_record('setitem', -## [setfunc, box, ConstInt(ofs), itembox], -## 'void', False) + for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: + itembox = box_from_index(allocated_boxes, allocated_lists, + boxes_from_frame, index_in_arglist) + box = box_from_index(allocated_boxes, allocated_lists, + boxes_from_frame, index_in_alloc) + history.execute_and_record(rop.SETARRAYITEM_GC, + [box, ad, ConstInt(ofs), itembox], + 'void', False) ## if storage.setitems: ## #history.execute_and_record('guard_no_exception', [], 'void', False) ## # XXX this needs to check for exceptions somehow @@ -936,8 +1009,8 @@ for index in storage.indices: if index < 0: newboxes.append(boxes_from_frame[~index]) -## elif index > 0xffff: -## newboxes.append(allocated_lists[(index - 1) >> 16]) + elif index > 0xffff: + newboxes.append(allocated_lists[(index - 1) >> 16]) else: newboxes.append(allocated_boxes[index]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Mon Mar 2 22:36:35 2009 @@ -332,6 +332,10 @@ self.execute(rop.SETARRAYITEM_GC, [arraybox, arraydesc, indexbox, itembox], 'void') + @arguments("box", "constbox") + def opimpl_arraylen_gc(self, arraybox, arraydesc): + self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') + @arguments("box") def opimpl_ptr_nonzero(self, box): self.execute(rop.OONONNULL, [box], 'int', True) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Mon Mar 2 22:36:35 2009 @@ -23,7 +23,7 @@ class NotSpecNode(SpecNode): def mutate_nodes(self, instnode): - pass + instnode.cursize = -1 def equals(self, other): if type(other) is NotSpecNode: @@ -168,40 +168,45 @@ [instnode.source, ConstInt(ofs)], box)) newboxlist.append(box) -##class DelayedListSpecNode(DelayedSpecNode): +class DelayedFixedListSpecNode(DelayedSpecNode): -## def expand_boxlist(self, instnode, newboxlist, oplist): -## from pypy.jit.metainterp.history import ResOperation, ConstInt -## from pypy.jit.metainterp.codewriter import ListDescr + def expand_boxlist(self, instnode, newboxlist, oplist): + from pypy.jit.metainterp.history import ResOperation, ConstInt + from pypy.jit.metainterp.resoperation import rop + from pypy.jit.metainterp.optimize import FixedList -## newboxlist.append(instnode.source) -## for ofs, subspecnode in self.fields: -## assert isinstance(subspecnode, SpecNodeWithBox) -## if oplist is None: -## instnode.cleanfields[ofs] = instnode.origfields[ofs] -## newboxlist.append(instnode.curfields[ofs].source) -## else: -## if ofs in instnode.cleanfields: -## newboxlist.append(instnode.cleanfields[ofs].source) -## else: -## ld = instnode.cls.source -## assert isinstance(ld, ListDescr) -## box = subspecnode.box.clonebox() -## oplist.append(ResOperation('getitem', -## [ld.getfunc, instnode.source, ConstInt(ofs)], [box])) -## newboxlist.append(box) - -## def extract_runtime_data(self, cpu, valuebox, resultlist): -## from pypy.jit.metainterp.codewriter import ListDescr - -## resultlist.append(valuebox) -## ld = self.known_class -## assert isinstance(ld, ListDescr) -## for ofs, subspecnode in self.fields: -## fieldbox = cpu.execute_operation('getitem', -## [ld.getfunc, valuebox, ConstInt(ofs)], -## ld.tp) -## subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + newboxlist.append(instnode.source) + cls = self.known_class + assert isinstance(cls, FixedList) + ad = ConstInt(cls.arraydescr) + for ofs, subspecnode in self.fields: + assert isinstance(subspecnode, SpecNodeWithBox) + if oplist is None: + instnode.cleanfields[ofs] = instnode.origfields[ofs] + newboxlist.append(instnode.curfields[ofs].source) + else: + if ofs in instnode.cleanfields: + newboxlist.append(instnode.cleanfields[ofs].source) + else: + box = subspecnode.box.clonebox() + oplist.append(ResOperation(rop.GETARRAYITEM_GC, + [instnode.source, ad, ConstInt(ofs)], box)) + newboxlist.append(box) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.resoperation import rop + from pypy.jit.metainterp.optimize import FixedList + + resultlist.append(valuebox) + cls = self.known_class + assert isinstance(cls, FixedList) + arraydescr = cls.arraydescr + ad = ConstInt(arraydescr) + for ofs, subspecnode in self.fields: + fieldbox = cpu.execute_operation(rop.GETARRAYITEM_GC, + [valuebox, ad, ConstInt(ofs)], + cpu.typefor(arraydescr)) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualizableSpecNode(VirtualizedSpecNode): @@ -223,28 +228,31 @@ return False return SpecNodeWithFields.equals(self, other) -##class VirtualListSpecNode(VirtualSpecNode): +class VirtualFixedListSpecNode(VirtualSpecNode): -## def __init__(self, known_class, fields, known_length): -## VirtualSpecNode.__init__(self, known_class, fields) -## self.known_length = known_length - -## def mutate_nodes(self, instnode): -## VirtualSpecNode.mutate_nodes(self, instnode) -## instnode.known_length = self.known_length - -## def equals(self, other): -## if not isinstance(other, VirtualListSpecNode): -## return False -## return SpecNodeWithFields.equals(self, other) + def __init__(self, known_class, fields, known_length): + VirtualSpecNode.__init__(self, known_class, fields) + self.known_length = known_length + + def mutate_nodes(self, instnode): + VirtualSpecNode.mutate_nodes(self, instnode) + instnode.known_length = self.known_length + + def equals(self, other): + if not isinstance(other, VirtualFixedListSpecNode): + return False + return SpecNodeWithFields.equals(self, other) -## def extract_runtime_data(self, cpu, valuebox, resultlist): -## from pypy.jit.metainterp.codewriter import ListDescr - -## for ofs, subspecnode in self.fields: -## cls = self.known_class -## assert isinstance(cls, ListDescr) -## fieldbox = cpu.execute_operation('getitem', -## [cls.getfunc, valuebox, ConstInt(ofs)], -## cls.tp) -## subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.resoperation import rop + from pypy.jit.metainterp.history import ConstInt + from pypy.jit.metainterp.optimize import FixedList + + for ofs, subspecnode in self.fields: + cls = self.known_class + assert isinstance(cls, FixedList) + ad = ConstInt(cls.arraydescr) + fieldbox = cpu.execute_operation(rop.GETARRAYITEM_GC, + [valuebox, ad, ConstInt(ofs)], + cpu.typefor(cls.arraydescr)) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Mon Mar 2 22:36:35 2009 @@ -6,7 +6,8 @@ from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy from pypy import conftest -def get_metainterp(func, values, CPUClass, type_system, policy): +def get_metainterp(func, values, CPUClass, type_system, policy, + listops=False): from pypy.annotation.policy import AnnotatorPolicy from pypy.annotation.model import lltype_to_annotation from pypy.rpython.test.test_llinterp import gengraph @@ -17,7 +18,7 @@ stats = history.Stats() cpu = CPUClass(rtyper, stats, False) graph = rtyper.annotator.translator.graphs[0] - opt = history.Options(specialize=False, listops=False) + opt = history.Options(specialize=False, listops=listops) metainterp = pyjitpl.OOMetaInterp(graph, [], cpu, stats, opt) metainterp.num_green_args = 0 return metainterp, rtyper @@ -41,7 +42,7 @@ kwds['CPUClass'] = self.CPUClass return ll_meta_interp(*args, **kwds) - def interp_operations(self, f, args, policy=None): + def interp_operations(self, f, args, policy=None, **kwds): class DoneWithThisFrame(Exception): pass @@ -51,7 +52,8 @@ if policy is None: policy = JitPolicy() metainterp, rtyper = get_metainterp(f, args, self.CPUClass, - self.type_system, policy=policy) + self.type_system, policy=policy, + **kwds) cw = codewriter.CodeWriter(metainterp, policy) graph = rtyper.annotator.translator.graphs[0] maingraph = cw.make_one_bytecode(graph, False) @@ -82,7 +84,7 @@ def meta_interp(self, *args, **kwds): py.test.skip("not for ootype right now") - def interp_operations(self, f, args, policy=None): + def interp_operations(self, f, args, policy=None, **kwds): py.test.skip("not for ootype right now") class BasicTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Mon Mar 2 22:36:35 2009 @@ -1,6 +1,5 @@ import py -py.test.skip("turned off for now") from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin @@ -17,10 +16,12 @@ n -= 1 return l[0] - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) - self.check_loops(getitem=0, setitem=1, guard_exception=0, - guard_no_exception=1) + self.check_loops(getarrayitem_gc=0, setarrayitem_gc=1) +# XXX fix codewriter +# guard_exception=0, +# guard_no_exception=1) def test_list_escapes(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) @@ -35,9 +36,9 @@ n -= 1 return l[3] - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) - self.check_loops(setitem=2, getitem=0) + self.check_loops(setarrayitem_gc=2, getarrayitem_gc=0) def test_list_escapes_but_getitem_goes(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) @@ -55,9 +56,84 @@ n -= 1 return l[3] - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) - self.check_loops(setitem=3, getitem=0) + self.check_loops(setarrayitem_gc=3, getarrayitem_gc=0) + + def test_list_of_ptrs(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + class A(object): + def __init__(self, x): + self.x = x + + def f(n): + l = [A(3)] + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + x = l[0].x + 1 + l[0] = A(x) + n -= 1 + return l[0].x + + res = self.meta_interp(f, [10], listops=True) + assert res == f(10) + self.check_loops(setarrayitem_gc=1, getarrayitem_gc=0, + new_with_vtable=1) # A should escape + + def test_list_checklength(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + + def f(n, a): + l = [0] * a + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + if len(l) < 3: + return 42 + l[0] = n + n -= 1 + return l[0] + + res = self.meta_interp(f, [10, 13], listops=True) + assert res == f(10, 13) + self.check_loops(setarrayitem_gc=1, arraylen_gc=1) + + def test_list_checklength_run(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + + def f(n, a): + l = [0] * a + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + if len(l) > n: + return 42 + l[0] = n + n -= 1 + return l[0] + + res = self.meta_interp(f, [50, 13], listops=True) + assert res == 42 + self.check_loops(setarrayitem_gc=1, arraylen_gc=1) + + def test_checklength_cannot_go_away(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + + def f(n): + l = [0] * n + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + if len(l) < 3: + return len(l) + l = [0] * n + n -= 1 + return 0 + + res = self.meta_interp(f, [10], listops=True) + assert res == 2 + self.check_loops(arraylen_gc=1) def test_list_indexerror(self): # this is an example where IndexError is raised before Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Mon Mar 2 22:36:35 2009 @@ -0,0 +1,109 @@ + +import py +from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.jit.metainterp.optimize import (PerfectSpecializer, + CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, + rebuild_boxes_from_guard_failure, AllocationStorage, + NotSpecNode, FixedList) +from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt +from pypy.jit.metainterp.test.test_optimize import Loop, equaloplists, cpu +from pypy.jit.metainterp.specnode import DelayedFixedListSpecNode + +# delayed list tests + +class A: + TP = lltype.GcArray(lltype.Signed) + lst = lltype.malloc(TP, 3) + l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lst)) + e0 = BoxInt(0) + e1 = BoxInt(0) + ad = ConstInt(cpu.arraydescrof(TP)) + ops = [ + ResOperation(rop.MERGE_POINT, [l], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e0), + ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e0], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e1), + ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e1], None), + ResOperation(rop.JUMP, [l], None), + ] + +def test_A_find_nodes(): + spec = PerfectSpecializer(Loop(A.ops)) + spec.find_nodes() + node = spec.nodes[A.l] + assert isinstance(node.cls.source, FixedList) + assert node.expanded_fields.keys() == [0] + +def test_A_intersect(): + spec = PerfectSpecializer(Loop(A.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + assert isinstance(spec.specnodes[0], DelayedFixedListSpecNode) + +def test_A_optimize_loop(): + spec = PerfectSpecializer(Loop(A.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + ResOperation(rop.MERGE_POINT, [A.l, A.e0], None), + ResOperation(rop.SETARRAYITEM_GC, [A.l, A.ad, ConstInt(0), A.e0], None), + ResOperation(rop.JUMP, [A.l, A.e0], None) + ]) + +# ---------------------------------------------------------------------------- + +class B: + locals().update(A.__dict__) + e2 = BoxInt(0) + e3 = BoxInt(0) + ops = [ + ResOperation(rop.MERGE_POINT, [l], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e0), + ResOperation(rop.INT_ADD, [e0, ConstInt(1)], e1), + ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e1], None), + ResOperation(-123, [e1], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e2), + ResOperation(rop.INT_ADD, [e2, ConstInt(1)], e3), + ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e3], None), + ResOperation(rop.JUMP, [l], None), + ] + +def test_B_optimize_loop(): + spec = PerfectSpecializer(Loop(B.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + ResOperation(rop.MERGE_POINT, [B.l, B.e0], None), + ResOperation(rop.INT_ADD, [B.e0, ConstInt(1)], B.e1), + ResOperation(rop.SETARRAYITEM_GC, [B.l, B.ad, ConstInt(0), B.e1], None), + ResOperation(-123, [B.e1], None), + ResOperation(rop.GETARRAYITEM_GC, [B.l, B.ad, ConstInt(0)], B.e2), + ResOperation(rop.INT_ADD, [B.e2, ConstInt(1)], B.e3), + ResOperation(rop.SETARRAYITEM_GC, [B.l, B.ad, ConstInt(0), B.e3], None), + ResOperation(rop.JUMP, [B.l, B.e3], None), + ]) + +# ---------------------------------------------------------------------------- + +class C: + locals().update(A.__dict__) + e3 = BoxInt(0) + e2 = BoxInt(0) + ops = [ + ResOperation(rop.MERGE_POINT, [l], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e0), + ResOperation(rop.INT_ADD, [e0, ConstInt(1)], e1), + ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e1], None), + ResOperation(-123, [e1], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e2), + ResOperation(rop.INT_ADD, [e2, ConstInt(1)], e3), + ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e3], None), + ResOperation(rop.JUMP, [l], None), + ] + +def test_C_optimize_loop(): + py.test.skip("XXX") + xxx Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Mon Mar 2 22:36:35 2009 @@ -15,11 +15,10 @@ lst.append(n) n -= len(lst) return len(lst) - res = self.meta_interp(f, [42]) + res = self.meta_interp(f, [42], listops=True) assert res == 9 def test_list_operations(self): - py.test.skip("pop(int) not supported") class FooBar: def __init__(self, z): self.z = z @@ -33,7 +32,7 @@ lst2.append(FooBar(5)) m += lst2.pop().z # 49 return m - res = self.interp_operations(f, [11]) + res = self.interp_operations(f, [11], listops=True) assert res == 49 def test_lazy_getitem_1(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Mon Mar 2 22:36:35 2009 @@ -93,7 +93,8 @@ cls.main = main def test_tl_base(self): - res = self.meta_interp(self.main.im_func, [0, 6]) + # XXX + res = self.meta_interp(self.main.im_func, [0, 6], listops=False) assert res == 5040 py.test.skip("re-enable list optimizations") self.check_loops({'merge_point':1, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Mon Mar 2 22:36:35 2009 @@ -1,6 +1,4 @@ import py -py.test.skip("re-enable list optimizations") - from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype @@ -10,9 +8,8 @@ class ListTests: def check_all_virtualized(self): - self.check_loops(new=0, newlist=0, - getitem=0, setitem=0, append=0, pop=0, len=0, - insert=0) + self.check_loops(new_array=0, setarrayitem_gc=0, getarrayitem_gc=0, + arraylen_gc=0) def test_simple_array(self): jitdriver = JitDriver(greens = [], reds = ['n']) @@ -23,7 +20,7 @@ lst = [n] n = lst[0] - 1 return n - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == 0 self.check_loops(int_sub=1) self.check_all_virtualized() @@ -40,7 +37,7 @@ n -= 1 return l[0] - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) self.check_all_virtualized() @@ -58,12 +55,13 @@ n -= 1 return l[0] - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) # one setitem should be gone by now - self.check_loops(newlist=1, setitem=1, getitem=1) + self.check_loops(call_ptr=1, setarrayitem_gc=1, getarrayitem_gc=1) def test_vlist_with_default_read(self): + py.test.skip("for now, more support in codewriter needed") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): l = [1] * 20 @@ -78,10 +76,11 @@ n -= 1 return l[0] - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) def test_append_pop(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: @@ -99,6 +98,7 @@ self.check_all_virtualized() def test_insert(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: @@ -115,6 +115,7 @@ self.check_all_virtualized() def test_nonzero(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: @@ -135,6 +136,7 @@ self.check_loops(listnonzero=0, guard_true=1, guard_false=0) def test_append_pop_rebuild(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: @@ -154,6 +156,7 @@ self.check_all_virtualized() def test_list_escapes(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while True: @@ -169,6 +172,7 @@ self.check_all_virtualized() def test_list_reenters(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: @@ -185,6 +189,7 @@ self.check_all_virtualized() def test_cannot_merge(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: @@ -202,6 +207,7 @@ self.check_all_virtualized() def test_list_escapes(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def g(l): pass @@ -220,6 +226,7 @@ self.check_loops(append=1) def test_list_escapes_various_ops(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def g(l): pass @@ -242,6 +249,7 @@ self.check_loops(append=2) def test_list_escapes_find_nodes(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def g(l): pass @@ -264,6 +272,7 @@ self.check_loops(append=2) def test_stuff_escapes_via_setitem(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n', 'l']) class Stuff(object): def __init__(self, x): @@ -283,6 +292,7 @@ self.check_loops(append=1) def test_virtual_escaping_via_list(self): + py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n', 'l']) class Stuff(object): def __init__(self, x): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Mon Mar 2 22:36:35 2009 @@ -50,3 +50,6 @@ pass def check_jumps(self, maxcount): pass + + def interp_operations(self, *args, **kwds): + py.test.skip("interp operations makes no sense when translated") From fijal at codespeak.net Mon Mar 2 23:13:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Mar 2009 23:13:09 +0100 (CET) Subject: [pypy-svn] r62427 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090302221309.A9340169E09@codespeak.net> Author: fijal Date: Mon Mar 2 23:13:06 2009 New Revision: 62427 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: A test and a fix. Note - it's essential to cache based on list type and not on item type, because otherwise we end up having similar, but different lists that differ on adtmeths for example Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Mon Mar 2 23:13:06 2009 @@ -128,7 +128,8 @@ history = metainterp.history loop.operations = history.operations close_loop(loop, loop.operations[0], endliveboxes) - old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop) + old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, + metainterp.cpu) if old_loop is not None: return old_loop finish_loop_or_bridge(metainterp, loop, loop.operations[0]) @@ -164,7 +165,8 @@ op = ResOperation(rop.JUMP, endliveboxes, None) operations.append(op) # - old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge) + old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge, + metainterp.cpu) if old_loop is None: return None bridge.jump_to = old_loop Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Mon Mar 2 23:13:06 2009 @@ -49,7 +49,7 @@ self.list_allocations = [] self.setitems = [] - def deal_with_box(self, box, nodes, liveboxes, memo): + def deal_with_box(self, box, nodes, liveboxes, memo, cpu): if isinstance(box, Const) or box not in nodes: virtual = False virtualized = False @@ -66,10 +66,16 @@ ld = instnode.cls.source assert isinstance(ld, FixedList) alloc_offset = len(self.list_allocations) + ad = ConstInt(ld.arraydescr) if instnode.cursize == -1: - xxx - self.list_allocations.append((ConstInt(ld.arraydescr), - instnode.cursize)) + # fish fish fish + res = cpu.execute_operation(rop.ARRAYLEN_GC, + [instnode.source, ad], + 'int') + size = res.getint() + else: + size = instnode.cursize + self.list_allocations.append((ad, size)) res = (alloc_offset + 1) << 16 else: alloc_offset = len(self.allocations) @@ -77,7 +83,8 @@ res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo) + num = self.deal_with_box(node.source, nodes, liveboxes, memo, + cpu) if isinstance(instnode.cls.source, FixedList): ld = instnode.cls.source x = (alloc_offset + 1) << 16 @@ -90,7 +97,8 @@ memo[box] = res liveboxes.append(box) for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo) + num = self.deal_with_box(node.source, nodes, liveboxes, memo, + cpu) self.setfields.append((res, ofs, num)) else: res = ~len(liveboxes) @@ -116,7 +124,6 @@ self.dirtyfields = {} self.expanded_fields = {} self.cursize = -1 - #self.origsize = -1 def is_nonzero(self): return self.cls is not None or self.nonzero @@ -218,7 +225,7 @@ if self.virtualized: flags += 'V' return "" % (self.source, flags) -def optimize_loop(options, old_loops, loop): +def optimize_loop(options, old_loops, loop, cpu=None): if not options.specialize: # for tests only if old_loops: return old_loops[0] @@ -232,10 +239,10 @@ for old_loop in old_loops: if perfect_specializer.match_exactly(old_loop): return old_loop - perfect_specializer.optimize_loop() + perfect_specializer.optimize_loop(cpu) return None -def optimize_bridge(options, old_loops, bridge): +def optimize_bridge(options, old_loops, bridge, cpu=None): if not options.specialize: # for tests only return old_loops[0] @@ -244,7 +251,7 @@ for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): perfect_specializer.adapt_for_match(old_loop.operations) - perfect_specializer.optimize_loop() + perfect_specializer.optimize_loop(cpu) return old_loop return None # no loop matches @@ -564,7 +571,7 @@ specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) return newboxlist - def optimize_guard(self, op): + def optimize_guard(self, op, cpu): liveboxes = [] storage = AllocationStorage() memo = {} @@ -573,7 +580,7 @@ op = op.clone() for box in old_boxes: indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo)) + liveboxes, memo, cpu)) rev_boxes = {} for i in range(len(liveboxes)): box = liveboxes[i] @@ -655,7 +662,7 @@ ## instnode.curfields[field] = valuenode ## instnode.cursize += 1 - def optimize_loop(self): + def optimize_loop(self, cpu): #self.ready_results = {} newoperations = [] exception_might_have_happened = False @@ -715,14 +722,14 @@ if not exception_might_have_happened: continue exception_might_have_happened = False - newoperations.append(self.optimize_guard(op)) + newoperations.append(self.optimize_guard(op, cpu)) continue elif (opnum == rop.GUARD_TRUE or opnum == rop.GUARD_FALSE): instnode = self.nodes[op.args[0]] if instnode.const: continue - newoperations.append(self.optimize_guard(op)) + newoperations.append(self.optimize_guard(op, cpu)) continue elif opnum == rop.GUARD_CLASS: instnode = self.nodes[op.args[0]] @@ -730,7 +737,7 @@ assert op.args[1].equals(instnode.cls.source) continue instnode.cls = InstanceNode(op.args[1], const=True) - newoperations.append(self.optimize_guard(op)) + newoperations.append(self.optimize_guard(op, cpu)) continue elif opnum == rop.GUARD_VALUE: instnode = self.nodes[op.args[0]] @@ -738,13 +745,13 @@ if instnode.const: continue instnode.const = True - newoperations.append(self.optimize_guard(op)) + newoperations.append(self.optimize_guard(op, cpu)) continue elif opnum == rop.GUARD_NONVIRTUALIZED: instnode = self.nodes[op.args[0]] if instnode.virtualized or instnode.virtual: continue - newoperations.append(self.optimize_guard(op)) + newoperations.append(self.optimize_guard(op, cpu)) continue elif opnum == rop.GETFIELD_GC: instnode = self.nodes[op.args[0]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Mon Mar 2 23:13:06 2009 @@ -93,8 +93,7 @@ cls.main = main def test_tl_base(self): - # XXX - res = self.meta_interp(self.main.im_func, [0, 6], listops=False) + res = self.meta_interp(self.main.im_func, [0, 6], listops=True) assert res == 5040 py.test.skip("re-enable list optimizations") self.check_loops({'merge_point':1, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Mon Mar 2 23:13:06 2009 @@ -142,7 +142,7 @@ frame.s -= 1 return x - res = self.meta_interp(f, [10]) + res = self.meta_interp(f, [10], listops=True) assert res == f(10) def test_virtual_on_virtualizable(self): @@ -173,6 +173,7 @@ res = self.meta_interp(f, [30]) assert res == f(30) + self.check_loops(getfield_gc=0) def test_unequal_list_lengths_cannot_be_virtual(self): jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], From fijal at codespeak.net Mon Mar 2 23:20:16 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Mar 2009 23:20:16 +0100 (CET) Subject: [pypy-svn] r62428 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090302222016.7FFC7169E08@codespeak.net> Author: fijal Date: Mon Mar 2 23:20:15 2009 New Revision: 62428 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: re-enabled. I suppose the guard_value there is needed actually Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Mon Mar 2 23:20:15 2009 @@ -95,18 +95,17 @@ def test_tl_base(self): res = self.meta_interp(self.main.im_func, [0, 6], listops=True) assert res == 5040 - py.test.skip("re-enable list optimizations") self.check_loops({'merge_point':1, 'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, - 'guard_false':1}) + 'guard_false':1, 'guard_value':1}) def test_tl_2(self): - res = self.meta_interp(self.main.im_func, [1, 10]) + res = self.meta_interp(self.main.im_func, [1, 10], listops=True) assert res == self.main.im_func(1, 10) - py.test.skip("re-enable list optimizations") self.check_loops({'merge_point':1, 'int_sub':1, 'int_le':1, - 'int_is_true':1, 'guard_false':1, 'jump':1}) + 'int_is_true':1, 'guard_false':1, 'jump':1, + 'guard_value':1}) class TestOOtype(ToyLanguageTests, OOJitMixin): pass From hpk at codespeak.net Mon Mar 2 23:48:16 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 2 Mar 2009 23:48:16 +0100 (CET) Subject: [pypy-svn] r62431 - pypy/trunk/pypy Message-ID: <20090302224816.F08D9168571@codespeak.net> Author: hpk Date: Mon Mar 2 23:48:16 2009 New Revision: 62431 Modified: pypy/trunk/pypy/conftest.py Log: InterpreterLevel tests: - substituting PyPy's "space" hack with a pytest_pyfuncarg() invocation - using new runtest() method instead of deprecated execute() Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Mon Mar 2 23:48:16 2009 @@ -42,6 +42,10 @@ group.addoption('-P', '--platform', action="callback", type="string", default="host", callback=_set_platform, help="set up tests to use specified platform as compile/run target") + + def pytest_pyfuncarg_space(self, pyfuncitem): + return gettestobjspace() + ConftestPlugin = PyPyTestPlugin _SPACECACHE={} @@ -256,7 +260,6 @@ else: return IntTestFunction(name, parent=self) - def skip_on_missing_buildoption(**ropts): __tracebackhide__ = True import sys @@ -325,14 +328,9 @@ def _keywords(self): return super(IntTestFunction, self)._keywords() + ['interplevel'] - def execute(self, target, *args): - co = target.func_code + def runtest(self): try: - if 'space' in co.co_varnames[:co.co_argcount]: - space = gettestobjspace() - target(space, *args) - else: - target(*args) + super(IntTestFunction, self).runtest() except OperationError, e: check_keyboard_interrupt(e) raise @@ -353,6 +351,9 @@ "if conftest.option.view is False") class AppTestFunction(PyPyTestFunction): + def _prunetraceback(self, traceback): + return traceback + def _haskeyword(self, keyword): return keyword == 'applevel' or \ super(AppTestFunction, self)._haskeyword(keyword) From hpk at codespeak.net Mon Mar 2 23:54:17 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 2 Mar 2009 23:54:17 +0100 (CET) Subject: [pypy-svn] r62432 - in pypy/trunk/pypy: interpreter/test module/__builtin__/test Message-ID: <20090302225417.746B216857B@codespeak.net> Author: hpk Date: Mon Mar 2 23:54:16 2009 New Revision: 62432 Modified: pypy/trunk/pypy/interpreter/test/test_module.py pypy/trunk/pypy/module/__builtin__/test/test_builtin.py Log: some examples for using space argument directly and getting rid of Class/Instance setup_* Modified: pypy/trunk/pypy/interpreter/test/test_module.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_module.py (original) +++ pypy/trunk/pypy/interpreter/test/test_module.py Mon Mar 2 23:54:16 2009 @@ -2,24 +2,20 @@ from pypy.interpreter.module import Module class TestModule: - def setup_class(cls): - cls.m = Module(cls.space, cls.space.wrap('m')) - def teardown_class(cls): - del cls.m - - def test_name(self): - w = self.space.wrap - w_m = w(self.m) - assert self.space.eq_w(self.space.getattr(w_m, w('__name__')), w('m')) - - def test_attr(self): - w = self.space.wrap - w_m = w(self.m) + def test_name(self, space): + w = space.wrap + m = Module(space, space.wrap('m')) + w_m = w(m) + assert space.eq_w(space.getattr(w_m, w('__name__')), w('m')) + + def test_attr(self, space): + w = space.wrap + w_m = w(Module(space, space.wrap('m'))) self.space.setattr(w_m, w('x'), w(15)) - assert self.space.eq_w(self.space.getattr(w_m, w('x')), w(15)) - self.space.delattr(w_m, w('x')) - self.space.raises_w(self.space.w_AttributeError, - self.space.delattr, w_m, w('x')) + assert space.eq_w(space.getattr(w_m, w('x')), w(15)) + space.delattr(w_m, w('x')) + space.raises_w(space.w_AttributeError, + space.delattr, w_m, w('x')) class AppTest_ModuleObject: def test_attr(self): Modified: pypy/trunk/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_builtin.py Mon Mar 2 23:54:16 2009 @@ -545,30 +545,21 @@ class TestInternal: - - def setup_method(self,method): - space = self.space - - def get_builtin(self, name): - return self.space.builtin.get(name) - - def test_execfile(self): + def test_execfile(self, space): from pypy.tool.udir import udir fn = str(udir.join('test_execfile')) f = open(fn, 'w') print >>f, "i=42" f.close() - w_execfile = self.get_builtin('execfile') - space = self.space + w_execfile = space.builtin.get("execfile") w_dict = space.newdict() - self.space.call_function(w_execfile, + space.call_function(w_execfile, space.wrap(fn), w_dict, space.w_None) w_value = space.getitem(w_dict, space.wrap('i')) - assert self.space.eq_w(w_value, space.wrap(42)) + assert space.eq_w(w_value, space.wrap(42)) - def test_execfile_different_lineendings(self): - space = self.space + def test_execfile_different_lineendings(self, space): from pypy.tool.udir import udir d = udir.ensure('lineending', dir=1) dos = d.join('dos.py') From hpk at codespeak.net Tue Mar 3 00:28:17 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 3 Mar 2009 00:28:17 +0100 (CET) Subject: [pypy-svn] r62434 - pypy/trunk/pypy Message-ID: <20090302232817.7B8F5169E10@codespeak.net> Author: hpk Date: Tue Mar 3 00:28:15 2009 New Revision: 62434 Modified: pypy/trunk/pypy/conftest.py Log: avoid another deprecation warning Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Tue Mar 3 00:28:15 2009 @@ -233,8 +233,7 @@ # if hasattr(mod, 'objspacename'): # mod.space = getttestobjspace(mod.objspacename) - def join(self, name): - obj = getattr(self.obj, name) + def makeitem(self, name, obj): if isclass(obj): if name.startswith('AppTest'): return AppClassCollector(name, parent=self) From hpk at codespeak.net Tue Mar 3 00:31:48 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 3 Mar 2009 00:31:48 +0100 (CET) Subject: [pypy-svn] r62435 - pypy/trunk/pypy Message-ID: <20090302233148.A744B169E10@codespeak.net> Author: hpk Date: Tue Mar 3 00:31:48 2009 New Revision: 62435 Modified: pypy/trunk/pypy/conftest.py Log: hopefully the last occurences of deprecated APIs for now Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Tue Mar 3 00:31:48 2009 @@ -360,7 +360,9 @@ def _keywords(self): return ['applevel'] + super(AppTestFunction, self)._keywords() - def execute(self, target, *args): + def runtest(self): + target = self.obj + args = self._args assert not args if option.runappdirect: return target(*args) @@ -387,7 +389,9 @@ space.setattr(w_instance, space.wrap(name[2:]), getattr(instance, name)) - def execute(self, target, *args): + def runtest(self): + target = self.obj + args = self._args assert not args if option.runappdirect: return target(*args) From fijal at codespeak.net Tue Mar 3 00:31:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 00:31:52 +0100 (CET) Subject: [pypy-svn] r62436 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090302233152.D9C5D169E15@codespeak.net> Author: fijal Date: Tue Mar 3 00:31:52 2009 New Revision: 62436 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Log: essential checkin to make test_tl work. Don't cache ARRAYS by item, because of other attrs issues (like adtmeths) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Tue Mar 3 00:31:52 2009 @@ -715,8 +715,8 @@ return ptr def op_new_array(self, arraydesc, count): - ITEMTYPE = symbolic.Size2Type[arraydesc/2] - return lltype.malloc(lltype.GcArray(ITEMTYPE), count) + TYPE = symbolic.Size2Type[arraydesc/2] + return lltype.malloc(TYPE, count) def op_getfield_gc(self, ptr, fielddesc): STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Tue Mar 3 00:31:52 2009 @@ -265,7 +265,7 @@ @staticmethod def arraydescrof(A): assert isinstance(A, lltype.GcArray) - size = symbolic.get_size(A.OF) + size = symbolic.get_size(A) token = history.getkind(A.OF) if token == 'ptr': bit = 1 From tverwaes at codespeak.net Tue Mar 3 01:58:53 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 01:58:53 +0100 (CET) Subject: [pypy-svn] r62437 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090303005853.0B1CE16857E@codespeak.net> Author: tverwaes Date: Tue Mar 3 01:58:50 2009 New Revision: 62437 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_register.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: major refactoring. moving from hardcoded tile addresses and vram to tile_maps containing tile_groups containing indexes in a tile_data array containing tiles which know how to draw themselves. Also corrected the sizes in the constants file. 8 - 2 = 6; not 8 :) Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Tue Mar 3 01:58:50 2009 @@ -125,8 +125,16 @@ VRAM_SIZE = 0x2000 # VRAM Tile Data/Maps Addresses -VRAM_DATA_A = 0x0000 # 4KB Tile Data (8000..8FFF) -VRAM_DATA_B = 0x0800 # 4KB Tile Data (8800..97FF) +TILE_DATA_SIZE = 0x00C0 # 1/4th of 0x2000; 2 data maps with 2 bytes per tile + # line and 8 lines +TILE_DATA_ADDR = 0x8000 + +VRAM_DATA_A = 0x0000 # 3KB Tile Data (8000..8BFF) +VRAM_DATA_B = 0x0C00 # 3KB Tile Data (8C00..97FF) + +TILE_MAP_ADDR = 0x9800 +TILE_MAP_SIZE = 32 # 32 Groups +TILE_GROUP_SIZE = 32 # of 32 addresses VRAM_MAP_A = 0x1800 # 1KB BG Tile Map 0 (9800..9BFF) VRAM_MAP_B = 0x1C00 # 1KB BG Tile Map 1 (9C00..9FFF) Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Tue Mar 3 01:58:50 2009 @@ -47,7 +47,7 @@ assert video.display == True assert video.v_blank == True assert video.dirty == True - assert len(video.vram) == constants.VRAM_SIZE + # assert len(video.vram) == constants.VRAM_SIZE assert len(video.oam) == constants.OAM_SIZE assert len(video.line) == 176 assert len(video.objects) == constants.big_sprites @@ -116,8 +116,6 @@ value = 0xF6 video.control.lcd_enabled = False - import pdb - pdb.set_trace() video.write(0xFF45, value) assert video.line_y_compare == value @@ -511,3 +509,26 @@ assert video.line == [0] * (8+160+8) +def test_update_tile(): + video = get_video() + assert len(video.tile_data_0) == constants.TILE_DATA_SIZE + assert len(video.tile_data_1) == constants.TILE_DATA_SIZE + for i in range(constants.TILE_DATA_SIZE * 2): + for j in range(0x100): + video.write(constants.TILE_DATA_ADDR + i, j) + assert video.read(constants.TILE_DATA_ADDR + i) == j + +def test_update_tile_map(): + video = get_video() + assert len(video.tile_map_0) == constants.TILE_MAP_SIZE + assert len(video.tile_map_1) == constants.TILE_MAP_SIZE + for i in range(constants.TILE_MAP_SIZE * 2): + for j in range(0x100): + video.write(constants.TILE_MAP_ADDR + i, j) + assert video.read(constants.TILE_MAP_ADDR + i) == j + +def test_fill_tiles(): + video = get_video() + for i in range(constants.TILE_DATA_SIZE * (2 * constants.SPRITE_SIZE) * 2): + video.write(constants.TILE_DATA_ADDR + i, 5) + assert video.read(constants.TILE_DATA_ADDR + i) == 5 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py Tue Mar 3 01:58:50 2009 @@ -36,10 +36,10 @@ control = get_control_register() control.background_and_window_lower_tile_data_selected = False - assert control.get_selected_tile_data_space() == constants.VRAM_DATA_B + assert control.get_selected_tile_data_space() == control.video.tile_data_1 control.background_and_window_lower_tile_data_selected = True - assert control.get_selected_tile_data_space() == constants.VRAM_DATA_A + assert control.get_selected_tile_data_space() == control.video.tile_data_0 # StatusRegister --------------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Tue Mar 3 01:58:50 2009 @@ -1,12 +1,10 @@ """ PyGirl Emulator - constants.LCD Video Display Processor + LCD Video Display Processor """ import math import operator -from pypy.lang.gameboy import constants -from pypy.lang.gameboy.constants import SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH, \ - GAMEBOY_SCREEN_HEIGHT +from pypy.lang.gameboy.constants import * from pypy.lang.gameboy.ram import iMemory from pypy.lang.gameboy.cpu import process_2s_complement from pypy.lang.gameboy.video_register import ControlRegister, StatusRegister @@ -50,6 +48,7 @@ self.background) self.memory = memory self.create_tile_maps() + self.create_tiles() self.create_sprites() self.reset() @@ -57,31 +56,51 @@ def create_tile_maps(self): # create the maxumal possible sprites - self.tile_map_0 = self.create_tile_map(32 * 32) - self.tile_map_1 = self.create_tile_map(32 * 32) + self.tile_map_0 = self.create_tile_map() + self.tile_map_1 = self.create_tile_map() self.tile_maps = [self.tile_map_0, self.tile_map_1] - def create_tile_map(self, size): - tile_map = [None] * size - for i in range(size): - tile_map[i] = Tile(self) - return tile_map + def create_tile_map(self): + return [self.create_tile_group() for i in range(TILE_MAP_SIZE)] + + def create_tile_group(self): + return [0x00 for i in range(TILE_GROUP_SIZE)] + + def create_tiles(self): + self.tile_data_0 = self.create_tile_data() + self.tile_data_1 = self.create_tile_data() + self.tile_data = [self.tile_data_0, self.tile_data_1] + + def create_tile_data(self): + return [Tile(i, self) for i in range(TILE_DATA_SIZE)] def update_tile(self, address, data): - # XXX to implement - #self.get_tile(address).set_data(); - pass + self.get_tile(address).set_data_at(address, data); def get_tile(self, address): - # XXX to implement - pass - - def reset_all_tiles(self): - #for tile in self.tile_map_0: - # tile.reset() - #for tile in self.tile_map_1: - # tile.reset() - pass + tile_index = (address - TILE_DATA_ADDR) / (SPRITE_SIZE*2) + if tile_index < TILE_DATA_SIZE: + return self.tile_data_0[tile_index] + else: + return self.tile_data_1[tile_index - TILE_DATA_SIZE] + + def select_tile_group_for(self, address): + tile_map_index = address - TILE_MAP_ADDR #) >> 1 + if tile_map_index < TILE_MAP_SIZE * TILE_GROUP_SIZE: + map = self.tile_map_0 + else: + map = self.tile_map_1 + tile_map_index -= TILE_MAP_SIZE * TILE_GROUP_SIZE + tile_group = map[tile_map_index >> 5] + return tile_group, tile_map_index & 0x1F + + def get_tile_map(self, address): + tile_group, group_index = self.select_tile_group_for(address) + return tile_group[group_index] + + def update_tile_map(self, address, data): + tile_group, group_index = self.select_tile_group_for(address) + tile_group[group_index] = data # ----------------------------------------------------------------------- def create_sprites(self): @@ -106,16 +125,11 @@ sprite.big_size = self.control.big_sprites def get_sprite(self, address): - address -= constants.OAM_ADDR + address -= OAM_ADDR # address divided by 4 gives the correct sprite, each sprite has 4 # bytes of attributes return self.sprites[ int(math.floor(address / 4)) ] - def reset_all_sprites(self): - #for sprite in self.sprites: - # sprite.reset() - pass - # ----------------------------------------------------------------------- def reset(self): @@ -123,7 +137,7 @@ self.status.reset() self.background.reset() self.window.reset() - self.cycles = constants.MODE_2_TICKS + self.cycles = MODE_2_TICKS self.line_y = 0 self.line_y_compare = 0 self.dma = 0xFF @@ -137,15 +151,13 @@ self.v_blank = True self.dirty = True - self.vram = [0] * constants.VRAM_SIZE - self.reset_all_tiles() + # self.vram = [0] * VRAM_SIZE # Object Attribute Memory - self.oam = [0] * constants.OAM_SIZE - self.reset_all_sprites() + self.oam = [0] * OAM_SIZE #XXX remove those dumb helper "shown_sprites" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.shown_sprites = [0] * constants.SPRITES_PER_LINE + self.shown_sprites = [0] * SPRITES_PER_LINE self.palette = [0] * 1024 self.frames = 0 @@ -156,68 +168,68 @@ def write(self, address, data): address = int(address) # assert data >= 0x00 and data <= 0xFF - if address == constants.LCDC : + if address == LCDC : self.set_control(data) - elif address == constants.STAT: + elif address == STAT: self.set_status(data) - elif address == constants.SCY: + elif address == SCY: self.set_scroll_y(data) - elif address == constants.SCX: + elif address == SCX: self.set_scroll_x(data) - #elif address == constants.LY: + #elif address == LY: # Read Only: line_y # pass - elif address == constants.LYC: + elif address == LYC: self.set_line_y_compare(data) - elif address == constants.DMA: + elif address == DMA: self.set_dma(data) - elif address == constants.BGP: + elif address == BGP: self.set_background_palette(data) - elif address == constants.OBP0: + elif address == OBP0: self.set_object_palette_0(data) - elif address == constants.OBP1: + elif address == OBP1: self.set_object_palette_1(data) - elif address == constants.WY: + elif address == WY: self.set_window_y(data) - elif address == constants.WX: + elif address == WX: self.set_window_x(data) - elif constants.OAM_ADDR <= address < \ - constants.OAM_ADDR + constants.OAM_SIZE: + elif OAM_ADDR <= address < \ + OAM_ADDR + OAM_SIZE: self.set_oam(address, data) - elif constants.VRAM_ADDR <= address < \ - constants.VRAM_ADDR + constants.VRAM_SIZE: + elif VRAM_ADDR <= address < \ + VRAM_ADDR + VRAM_SIZE: self.set_vram(address, data) def read(self, address): - if address == constants.LCDC: + if address == LCDC: return self.get_control() - elif address == constants.STAT: + elif address == STAT: return self.get_status() - elif address == constants.SCY: + elif address == SCY: return self.get_scroll_y() - elif address == constants.SCX: + elif address == SCX: return self.get_scroll_x() - elif address == constants.LY: + elif address == LY: return self.get_line_y() - elif address == constants.LYC: + elif address == LYC: return self.get_line_y_compare() - elif address == constants.DMA: + elif address == DMA: return self.get_dma() - elif address == constants.BGP: + elif address == BGP: return self.get_background_palette() - elif address == constants.OBP0: + elif address == OBP0: return self.get_object_palette_0() - elif address == constants.OBP1: + elif address == OBP1: return self.get_object_palette_1() - elif address == constants.WY: + elif address == WY: return self.get_window_y() - elif address == constants.WX: + elif address == WX: return self.get_window_x() - elif constants.OAM_ADDR <= address < \ - constants.OAM_ADDR + constants.OAM_SIZE: + elif OAM_ADDR <= address < \ + OAM_ADDR + OAM_SIZE: return self.get_oam(address) - elif constants.VRAM_ADDR <= address < \ - constants.VRAM_ADDR + constants.VRAM_SIZE: + elif VRAM_ADDR <= address < \ + VRAM_ADDR + VRAM_SIZE: return self.get_vram(address) return 0xFF @@ -329,7 +341,7 @@ """ self.dma = data # copy the memory region - for index in range(constants.OAM_SIZE): + for index in range(OAM_SIZE): self.oam[index] = self.memory.read((self.dma << 8) + index) self.update_all_sprites() @@ -410,23 +422,27 @@ attributes of the sprites, this works only during the v-blank and the h-blank period. """ - self.oam[address - constants.OAM_ADDR] = data & 0xFF + self.oam[address - OAM_ADDR] = data & 0xFF self.update_sprite(address, data) def get_oam(self, address): return self.get_sprite(address).get_data_at(address); def set_vram(self, address, data): - """ - sets one byte of the video memory. - The video memory contains the tiles used to display. - """ - self.vram[address - constants.VRAM_ADDR] = data & 0xFF - self.update_tile(address, data) + """ + sets one byte of the video memory. + The video memory contains the tiles used to display. + """ + if address < TILE_MAP_ADDR: + self.update_tile(address, data) + else: + self.update_tile_map(address, data) def get_vram(self, address): - #return self.get_tile(address).get_data()[address % 4] - return self.vram[address - constants.VRAM_ADDR] + if address < TILE_MAP_ADDR: + return self.get_tile(address).get_data_at(address) + else: + return self.get_tile_map(address) # emulation ---------------------------------------------------------------- @@ -478,7 +494,7 @@ if sprite.is_shown_on_current_line(self): self.shown_sprites[count] = sprite count += 1 - if count >= constants.SPRITES_PER_LINE: + if count >= SPRITES_PER_LINE: break self.sort_scan_sprite(count) return count @@ -494,23 +510,21 @@ self.shown_sprites[index], self.shown_sprites[highest] = \ self.shown_sprites[highest], self.shown_sprites[index] - def draw_tiles(self, x, tile_map, tile_data): + def draw_tiles(self, x_start, tile_group, y, group_index=0): + x = x_start + tile_data = self.control.get_selected_tile_data_space() while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: - tile = self.vram[tile_map] - assert tile == (tile & 0xFF) + tile_index = tile_group[group_index % TILE_GROUP_SIZE] if not self.control.background_and_window_lower_tile_data_selected: - tile = (tile ^ 0x80) & 0xFF - self.draw_tile(x, tile_data + (tile << 4)) - tile_map = (tile_map & 0x1FE0) + ((tile_map + 1) & 0x001F) + tile_index ^= 0x80 + tile = tile_data[tile_index] + tile.draw(x, y) + group_index += 1 x += SPRITE_SIZE - def draw_tile(self, x, address): - pattern = self.get_pattern(address) - for i in range(0, SPRITE_SIZE): - self.line[x + i] = (pattern >> (7-i)) & 0x0101 - def get_pattern(self, address): - return self.vram[address] + (self.vram[address + 1] << 8) + # TODO: remove method! + return self.get_vram(VRAM_ADDR + address) + (self.get_vram(VRAM_ADDR + address + 1) << 8) def draw_object_tile(self, sprite): self.draw_object(set_tile_line_call_wrapper(self), sprite) @@ -587,7 +601,7 @@ color = (self.object_palette_1 >> ((((pattern >> 4) & 0x02) +\ ((pattern >> 1) & 0x01)) << 1)) & 0x03 index = ((pattern & 0x30) << 4) + (pattern & 0x0F) - #self.palette[index] = constants.COLOR_MAP[color] + #self.palette[index] = COLOR_MAP[color] self.palette[index] = color self.dirty = False @@ -596,8 +610,8 @@ class VideoDriver(object): def __init__(self): - self.width = int(constants.GAMEBOY_SCREEN_WIDTH) - self.height = int(constants.GAMEBOY_SCREEN_HEIGHT) + self.width = int(GAMEBOY_SCREEN_WIDTH) + self.height = int(GAMEBOY_SCREEN_HEIGHT) self.clear_pixels() def clear_pixels(self): Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Tue Mar 3 01:58:50 2009 @@ -144,10 +144,10 @@ self.background.enabled = bool(value & (1 << 0)) if previous_big_sprites != self.big_sprites: - video.update_sprite_size() + self.video.update_sprite_size() def get_selected_tile_data_space(self): if self.background_and_window_lower_tile_data_selected: - return constants.VRAM_DATA_A + return self.video.tile_data_0 else: - return constants.VRAM_DATA_B + return self.video.tile_data_1 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Tue Mar 3 01:58:50 2009 @@ -153,7 +153,7 @@ return self.get_tile_number() def get_tile_address(self, video): - return (self.get_tile(video) << 4) + (self.get_draw_y(video) << 1) + return (self.get_tile(video) << 4) + (self.get_draw_y(video) << 1) def get_draw_y(self, video): y = self.current_line_y(video) @@ -194,43 +194,60 @@ self.y = self.get_height() - 1 - self.y # ----------------------------------------------------------------------------- - - + + class Tile(object): - def __init__(self, video): + def __init__(self, number, video): self.video = video + self.number = number self.reset() + self.data = [0x00 for i in range(2*SPRITE_SIZE)] + + def draw(self, x, y): + pattern = self.get_pattern_at(y << 1) + for i in range(SPRITE_SIZE): + value = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 + self.video.line[x + i] = value def reset(self): pass def set_tile_data(self, data): - pass + self.data = data - def get_pixel_data(self): - return self.pixel_data - - def get_selected_tile_map_space(self): - pass - def get_data_at(self, address): - return self.get_data()[address % self.byte_size()] + return self.data[address % (2*SPRITE_SIZE)] - def get_data(): - return [] + def set_data_at(self, address, data): + self.data[address % (2*SPRITE_SIZE)] = data - def byte_size(self): - return 0 + def get_data(self): + return self.data + + def get_pattern_at(self, address): + return self.get_data_at(address) +\ + (self.get_data_at(address + 1) << 8) # ----------------------------------------------------------------------------- -class Window(object): - +class Drawable(object): def __init__(self, video): self.video = video self.reset() + def get_tile_map_space(self): + if self.upper_tile_map_selected: + return self.video.tile_map_1 + else: + return self.video.tile_map_0 + + def reset(self): + raise Exception("Not implemented") + + +class Window(Drawable): + def reset(self): self.x = 0 self.y = 0 @@ -241,36 +258,21 @@ def switch_on(self): if self.line_y == 0 and self.video.line_y > self.y: self.line_y = GAMEBOY_SCREEN_HEIGHT - - def get_tile_map_space(self): - #if (self.control.read() & mask) != 0: - if self.upper_tile_map_selected: - return constants.VRAM_MAP_B - else: - return constants.VRAM_MAP_A - + def draw_line(self, line_y): - if line_y >= self.y and self.x < 167 and \ + if line_y >= self.y and self.x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE-1 and \ self.line_y < GAMEBOY_SCREEN_HEIGHT: - tile_map, tile_data = self.prepare_window_data() - self.video.draw_tiles(self.x + 1, tile_map, tile_data) + + tile_map = self.get_tile_map_space() + tile_group = tile_map[self.line_y >> 5] + + self.video.draw_tiles(self.x + 1, tile_group, self.line_y) self.line_y += 1 - def prepare_window_data(self): - tile_map = self.get_tile_map_space() - tile_map += (self.line_y >> 3) << 5 - tile_data = self.video.control.get_selected_tile_data_space() - tile_data += (self.line_y & 7) << 1 - return tile_map, tile_data; - # ----------------------------------------------------------------------------- -class Background(object): +class Background(Drawable): - def __init__(self, video): - self.video = video - self.reset() - def reset(self): # SCROLLX and SCROLLY hold the coordinates of background to # be displayed in the left upper corner of the screen. @@ -279,28 +281,15 @@ self.enabled = True self.upper_tile_map_selected = False - def get_tile_map_space(self): - #if (self.control.read() & mask) != 0: - if self.upper_tile_map_selected: - return constants.VRAM_MAP_B - else: - return constants.VRAM_MAP_A - def draw_clean_line(self, line_y): - for x in range(8+GAMEBOY_SCREEN_WIDTH+8): + for x in range(SPRITE_SIZE+GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE): self.video.line[x] = 0x00 def draw_line(self, line_y): - y = (self.scroll_y + line_y) & 0xFF - x = self.scroll_x & 0xFF - tile_map, tile_data = self.prepare_background_data(x, y) - self.video.draw_tiles(8 - (x & 7), tile_map, tile_data) - - def prepare_background_data(self, x, y): - tile_map = self.get_tile_map_space() - tile_map += ((y >> 3) << 5) + (x >> 3) - tile_data = self.video.control.get_selected_tile_data_space() - tile_data += (y & 7) << 1 - return tile_map, tile_data - - + y = self.scroll_y + line_y + x = self.scroll_x + + tile_map = self.get_tile_map_space() + tile_group = tile_map[y >> 3] + # print "Background" + self.video.draw_tiles(8 - (x % 8), tile_group, y, x >> 3) From tverwaes at codespeak.net Tue Mar 3 02:15:21 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 02:15:21 +0100 (CET) Subject: [pypy-svn] r62438 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090303011521.B9410169DB2@codespeak.net> Author: tverwaes Date: Tue Mar 3 02:15:18 2009 New Revision: 62438 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py Log: type bug Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Tue Mar 3 02:15:18 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = False +use_rsdl = True if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Tue Mar 3 02:15:18 2009 @@ -157,7 +157,7 @@ #XXX remove those dumb helper "shown_sprites" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.shown_sprites = [0] * SPRITES_PER_LINE + self.shown_sprites = [None] * SPRITES_PER_LINE self.palette = [0] * 1024 self.frames = 0 From hpk at codespeak.net Tue Mar 3 09:32:11 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 3 Mar 2009 09:32:11 +0100 (CET) Subject: [pypy-svn] r62440 - pypy/trunk/pypy Message-ID: <20090303083211.A40A7169DFC@codespeak.net> Author: hpk Date: Tue Mar 3 09:32:09 2009 New Revision: 62440 Modified: pypy/trunk/pypy/conftest.py Log: fix 5000 tests approximately: only collect tests and classes if names actually match :) Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Tue Mar 3 09:32:09 2009 @@ -234,7 +234,7 @@ # mod.space = getttestobjspace(mod.objspacename) def makeitem(self, name, obj): - if isclass(obj): + if isclass(obj) and self.classnamefilter(name): if name.startswith('AppTest'): return AppClassCollector(name, parent=self) elif name.startswith('ExpectTest'): @@ -249,7 +249,7 @@ else: return IntClassCollector(name, parent=self) - elif hasattr(obj, 'func_code'): + elif hasattr(obj, 'func_code') and self.funcnamefilter(name): if name.startswith('app_test_'): assert not obj.func_code.co_flags & 32, \ "generator app level functions? you must be joking" From hpk at codespeak.net Tue Mar 3 09:41:28 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 3 Mar 2009 09:41:28 +0100 (CET) Subject: [pypy-svn] r62441 - pypy/trunk/lib-python Message-ID: <20090303084128.CEF9E16856E@codespeak.net> Author: hpk Date: Tue Mar 3 09:41:28 2009 New Revision: 62441 Modified: pypy/trunk/lib-python/conftest.py Log: avoid another deprecation warning Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Tue Mar 3 09:41:28 2009 @@ -27,16 +27,19 @@ # Interfacing/Integrating with py.test's collection process # -Option = py.test.config.Option -option = py.test.config.addoptions("compliance testing options", - Option('-T', '--timeout', action="store", type="string", +class LibPythonPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("complicance testing options") + group.addoption('-T', '--timeout', action="store", type="string", default="100mp", dest="timeout", help="fail a test module after the given timeout. " - "specify in seconds or 'NUMmp' aka Mega-Pystones"), - Option('--pypy', action="store", type="string", + "specify in seconds or 'NUMmp' aka Mega-Pystones") + group.addoption('--pypy', action="store", type="string", dest="pypy", help="use given pypy executable to run lib-python tests. " "This will run the tests directly (i.e. not through py.py)") - ) + +ConftestPlugin = LibPythonPlugin +option = py.test.config.option def gettimeout(): timeout = option.timeout.lower() From fijal at codespeak.net Tue Mar 3 10:33:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 10:33:18 +0100 (CET) Subject: [pypy-svn] r62443 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090303093318.4B63616856E@codespeak.net> Author: fijal Date: Tue Mar 3 10:33:17 2009 New Revision: 62443 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Add a marker for ovf ops Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Tue Mar 3 10:33:17 2009 @@ -56,6 +56,9 @@ def can_raise(self): return rop._CANRAISE_FIRST <= self.opnum <= rop._CANRAISE_LAST + def is_ovf(self): + return rop._OVF_FIRST <= self.opnum <= rop._OVF_LAST + # ____________________________________________________________ @@ -154,10 +157,12 @@ CALL_PTR = _CALL + typ.PTR CALL_VOID = _CALL + typ.VOID # + _OVF_FIRST = 109 INT_ADD_OVF = 110 INT_SUB_OVF = 111 INT_MUL_OVF = 112 INT_NEG_OVF = 113 + _OVF_LAST = 114 _CANRAISE_LAST = 119 # ----- end of can_raise operations ----- _LAST = 119 # for the backend to add more internal operations From fijal at codespeak.net Tue Mar 3 10:34:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 10:34:17 +0100 (CET) Subject: [pypy-svn] r62444 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090303093417.155F316856E@codespeak.net> Author: fijal Date: Tue Mar 3 10:34:16 2009 New Revision: 62444 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: Do the right thing about overflow ops. Took couple hours... But as a side effect, we have a way to nicely detect boolean tests and use processor flags for this. As a side effect, run some operations directly. I don't want to care too much about execute_operation running Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Tue Mar 3 10:34:16 2009 @@ -7,8 +7,7 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, - arg_pos, lower_byte, stack_pos, Perform, - MALLOC_VARSIZE) + arg_pos, lower_byte, stack_pos, Perform) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.support import gc_malloc_fnaddr @@ -86,6 +85,8 @@ if not we_are_translated(): self.dump_op(op) self.position = i + # XXX eventually change to numbers or kill + # alltogether if op.opname == 'load': self.regalloc_load(op) elif op.opname == 'store': @@ -94,6 +95,10 @@ self.regalloc_perform_discard(op) elif op.opname == 'perform': self.regalloc_perform(op) + elif op.opname == 'perform_with_guard': + self.regalloc_perform_with_guard(op) + else: + raise NotImplementedError(op.opname) if not we_are_translated(): self.dump_op('') self.mc.done() @@ -184,6 +189,10 @@ def regalloc_perform_discard(self, op): genop_discard_list[op.op.opnum](self, op.op, op.arglocs) + def regalloc_perform_with_guard(self, op): + genop_guard_list[op.op.opnum](self, op.op, op.guard_op, op.arglocs, + op.result_loc) + def regalloc_store_to_arg(self, op): self.mc.MOV(arg_pos(op.pos), op.from_loc) @@ -198,15 +207,28 @@ return genop_binary def _binaryop_ovf(asmop, can_swap=False): - def genop_binary_ovf(self, op, arglocs, result_loc): + def genop_binary_ovf(self, op, guard_op, arglocs, result_loc): getattr(self.mc, asmop)(arglocs[0], arglocs[1]) - if we_are_translated(): - # XXX setting the lowest byte of _exception_addr to 0 or 1 - # does not work after translation - XXX - # XXX think about CMOV instead of SETO, this would avoid - # a mess in detecting an exception - self.mc.SETO(heap8(self._exception_addr)) + index = self.cpu.make_guard_index(guard_op) + recovery_code_addr = self.mc2.tell() + stacklocs = guard_op.stacklocs + locs = arglocs[2:] + assert len(locs) == len(stacklocs) + for i in range(len(locs)): + loc = locs[i] + if isinstance(loc, REG): + self.mc2.MOV(stack_pos(stacklocs[i]), loc) + self.mc2.MOV(eax, imm(self._ovf_error_vtable)) + self.mc2.MOV(addr_add(imm(self._exception_addr), imm(0)), eax) + self.mc2.MOV(eax, imm(self._ovf_error_inst)) + self.mc2.MOV(addr_add(imm(self._exception_addr), imm(WORD)), eax) + self.mc2.PUSH(esp) # frame address + self.mc2.PUSH(imm(index)) # index of guard that failed + self.mc2.CALL(rel32(self.cpu.get_failure_recovery_func_addr())) + self.mc2.ADD(esp, imm(8)) + self.mc2.JMP(eax) + self.mc.JO(rel32(recovery_code_addr)) + guard_op._jmp_from = self.mc.tell() return genop_binary_ovf def _cmpop(cond, rev_cond): @@ -319,10 +341,7 @@ # xxx ignore NULL returns for now self.mc.POP(mem(eax, 0)) - def genop_malloc_varsize(self, op, arglocs, result_loc): - loc_size = arglocs[0] - self.call(self.malloc_func_addr, [loc_size], eax) - + # same as malloc varsize after all def genop_new(self, op, arglocs, result_loc): assert result_loc is eax loc_size = arglocs[0] @@ -539,8 +558,9 @@ self.gen_call(op, arglocs, resloc) self.mc.MOVZX(eax, eax) -genop_discard_list = [None] * (MALLOC_VARSIZE + 1) -genop_list = [None] * (MALLOC_VARSIZE + 1) +genop_discard_list = [None] * rop._LAST +genop_list = [None] * rop._LAST +genop_guard_list = [None] * rop._LAST for name, value in Assembler386.__dict__.iteritems(): if name.startswith('genop_'): @@ -551,6 +571,8 @@ num = getattr(rop, opname.upper()) if value.func_code.co_argcount == 3: genop_discard_list[num] = value + elif value.func_code.co_argcount == 5: + genop_guard_list[num] = value else: genop_list[num] = value Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Tue Mar 3 10:34:16 2009 @@ -11,9 +11,6 @@ from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname - -MALLOC_VARSIZE = rop._LAST + 1 - # esi edi and ebp can be added to this list, provided they're correctly # saved and restored REGS = [eax, ecx, edx] @@ -57,6 +54,18 @@ def __repr__(self): return '%s <- %s(%s)' % (self.result_loc, self.op, self.arglocs) +class PerformWithGuard(PseudoOperation): + opname = 'perform_with_guard' + + def __init__(self, op, guard_op, arglocs, result_loc): + self.op = op + self.guard_op = guard_op + self.result_loc = result_loc + self.arglocs = arglocs + + def __repr__(self): + return '%s <- %s(%s) [GUARDED]' % (self.result_loc, self.op, self.arglocs) + class PerformDiscard(PseudoOperation): opname = 'perform_discard' @@ -199,7 +208,8 @@ # load/store places new_ops = [] self.loop_consts = loop_consts - for i in range(len(operations)): + i = 0 + while i < len(operations): op = operations[i] self.position = i if op.has_no_side_effect() and op.result not in self.longevity: @@ -207,9 +217,16 @@ else: canfold = False if not canfold: - new_ops += oplist[op.opnum](self, op) + # detect overflow ops + if op.is_ovf(): + assert operations[i + 1].opnum == rop.GUARD_NO_EXCEPTION + new_ops += oplist[op.opnum](self, op, operations[i + 1]) + i += 1 + else: + new_ops += oplist[op.opnum](self, op, None) self.eventually_free_var(op.result) self._check_invariants() + i += 1 return new_ops def _compute_vars_longevity(self, operations): @@ -445,7 +462,7 @@ loc = self.reg_bindings[result_v] return loc, ops - def consider_merge_point(self, op): + def consider_merge_point(self, op, ignored): # XXX we can sort out here by longevity if we need something # more optimal ops = [PerformDiscard(op, [])] @@ -473,7 +490,7 @@ self.eventually_free_vars(op.args) return ops - def consider_catch(self, op): + def consider_catch(self, op, ignored): locs = [] for arg in op.args: l = self.loc(arg) @@ -486,7 +503,7 @@ self.eventually_free_vars(op.args) return [PerformDiscard(op, [])] - def _consider_guard(self, op): + def _consider_guard(self, op, ignored): loc, ops = self.make_sure_var_in_reg(op.args[0], []) locs = self._locs_from_liveboxes(op) self.eventually_free_var(op.args[0]) @@ -496,14 +513,14 @@ consider_guard_true = _consider_guard consider_guard_false = _consider_guard - def consider_guard_nonvirtualized(self, op): + def consider_guard_nonvirtualized(self, op, ignored): # XXX implement it locs = self._locs_from_liveboxes(op) self.eventually_free_var(op.args[0]) self.eventually_free_vars(op.liveboxes) return [] - def consider_guard_no_exception(self, op): + def consider_guard_no_exception(self, op, ignored): box = TempBox() loc, ops = self.force_allocate_reg(box, []) locs = self._locs_from_liveboxes(op) @@ -511,7 +528,7 @@ self.eventually_free_var(box) return ops + [PerformDiscard(op, [loc] + locs)] - def consider_guard_exception(self, op): + def consider_guard_exception(self, op, ignored): loc, ops = self.make_sure_var_in_reg(op.args[0], []) box = TempBox() loc1, ops1 = self.force_allocate_reg(box, op.args) @@ -527,7 +544,7 @@ self.eventually_free_var(box) return ops + ops1 + ops2 + [Perform(op, [loc, loc1] + locs, resloc)] - #def consider_guard2(self, op): + #def consider_guard2(self, op, ignored): # loc1, ops1 = self.make_sure_var_in_reg(op.args[0], []) # loc2, ops2 = self.make_sure_var_in_reg(op.args[1], []) # locs = [self.loc(arg) for arg in op.liveboxes] @@ -543,7 +560,7 @@ #consider_guard_is = consider_guard2 #consider_guard_isnot = consider_guard2 - def consider_guard_value(self, op): + def consider_guard_value(self, op, ignored): x = self.loc(op.args[0]) if not (isinstance(x, REG) or isinstance(op.args[1], Const)): x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) @@ -554,14 +571,14 @@ self.eventually_free_vars(op.liveboxes + op.args) return ops + [PerformDiscard(op, [x, y] + locs)] - def consider_guard_class(self, op): + def consider_guard_class(self, op, ignored): x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) y = self.loc(op.args[1]) locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes + op.args) return ops + [PerformDiscard(op, [x, y] + locs)] - def consider_return(self, op): + def consider_return(self, op, ignored): if op.args: arglocs = [self.loc(op.args[0])] self.eventually_free_var(op.args[0]) @@ -569,20 +586,23 @@ arglocs = [] return [PerformDiscard(op, arglocs)] - def _consider_binop(self, op): + def _consider_binop_part(self, op, ignored): x = op.args[0] ops = [] if isinstance(x, Const): res, ops = self.force_allocate_reg(op.result, []) argloc = self.loc(op.args[1]) self.eventually_free_var(op.args[1]) - load_op = Load(x, self.loc(x), res) - return ops + [load_op, Perform(op, [res, argloc], res)] + load_op = Load(x, self.loc(x), res) + return res, argloc, ops + [load_op] loc, ops = self.force_result_in_reg(op.result, x, op.args) argloc = self.loc(op.args[1]) self.eventually_free_var(op.args[1]) + return loc, argloc, ops + + def _consider_binop(self, op, ignored): + loc, argloc, ops = self._consider_binop_part(op, ignored) return ops + [Perform(op, [loc, argloc], loc)] - # otherwise load this variable to some register consider_int_add = _consider_binop consider_int_mul = _consider_binop @@ -593,21 +613,24 @@ consider_uint_sub = _consider_binop #consider_uint_and = _consider_binop - def _consider_binop_ovf(self, op): - return self._consider_binop(op) + def _consider_binop_ovf(self, op, guard_op): + loc, argloc, ops = self._consider_binop_part(op, None) + locs = self._locs_from_liveboxes(guard_op) + self.eventually_free_vars(guard_op.liveboxes) + return ops + [PerformWithGuard(op, guard_op, [loc, argloc] + locs, loc)] consider_int_mul_ovf = _consider_binop_ovf consider_int_sub_ovf = _consider_binop_ovf consider_int_add_ovf = _consider_binop_ovf # XXX ovf_neg op - def consider_int_neg(self, op): + def consider_int_neg(self, op, ignored): res, ops = self.force_result_in_reg(op.result, op.args[0], []) return ops + [Perform(op, [res], res)] consider_bool_not = consider_int_neg - def consider_int_rshift(self, op): + def consider_int_rshift(self, op, ignored): tmpvar = TempBox() reg, ops = self.force_allocate_reg(tmpvar, [], ecx) y = self.loc(op.args[1]) @@ -616,7 +639,7 @@ self.eventually_free_vars(op.args + [tmpvar]) return ops + more_ops + [Perform(op, [x, y, reg], x)] - def consider_int_mod(self, op): + def consider_int_mod(self, op, ignored): l0, ops0 = self.make_sure_var_in_reg(op.args[0], [], eax) l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) l2, ops2 = self.force_allocate_reg(op.result, [], edx) @@ -627,7 +650,7 @@ self.eventually_free_vars(op.args + [tmpvar]) return ops0 + ops1 + ops2 + ops3 + [Perform(op, [eax, ecx], edx)] - def consider_int_floordiv(self, op): + def consider_int_floordiv(self, op, ignored): tmpvar = TempBox() l0, ops0 = self.force_result_in_reg(op.result, op.args[0], [], eax) l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) @@ -637,7 +660,7 @@ self.eventually_free_vars(op.args + [tmpvar]) return ops0 + ops1 + ops2 + [Perform(op, [eax, ecx], eax)] - def _consider_compop(self, op): + def _consider_compop(self, op, ignored): vx = op.args[0] vy = op.args[1] arglocs = [self.loc(vx), self.loc(vy)] @@ -695,7 +718,7 @@ self.free_regs = REGS[:] return ops + [PerformDiscard(op, arglocs)] - def consider_call_ptr(self, op): + def consider_call_ptr(self, op, ignored): return self._call(op, [self.loc(arg) for arg in op.args]) consider_call_void = consider_call_ptr @@ -704,13 +727,13 @@ consider_call__4 = consider_call_ptr consider_call__8 = consider_call_ptr - def consider_new(self, op): + def consider_new(self, op, ignored): return self._call(op, [self.loc(arg) for arg in op.args]) - def consider_new_with_vtable(self, op): + def consider_new_with_vtable(self, op, ignored): return self._call(op, [self.loc(arg) for arg in op.args]) - def consider_newstr(self, op): + def consider_newstr(self, op, ignored): ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] ofs_items = symbolic.get_field_token(rstr.STR.chars, 'items')[0] ofs_length = symbolic.get_field_token(rstr.STR.chars, 'length')[0] @@ -730,7 +753,7 @@ else: ops0 = [] loc = imm(ofs + ofs_items + (v.getint() << size)) - ops = self._call(ResOperation(MALLOC_VARSIZE, [v], res_v) + ops = self._call(ResOperation(rop.NEW, [v], res_v) , [loc], [v]) loc, ops1 = self.make_sure_var_in_reg(v, [res_v]) assert self.loc(res_v) == eax @@ -750,12 +773,12 @@ ofs = arraydescr & 0xffff return size_of_field, ofs - def consider_new_array(self, op): + def consider_new_array(self, op, ignored): size_of_field, basesize = self._unpack_arraydescr(op.args[0].getint()) return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[1], op.result) - def consider_oononnull(self, op): + def consider_oononnull(self, op, ignored): argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) reg = self.try_allocate_reg(op.result) @@ -769,7 +792,7 @@ size_loc = imm(fielddescr >> 16) return ofs_loc, size_loc - def consider_setfield_gc(self, op): + def consider_setfield_gc(self, op, ignored): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) @@ -777,7 +800,7 @@ return (ops0 + ops2 + [PerformDiscard(op, [base_loc, ofs_loc, size_loc, value_loc])]) - def consider_strsetitem(self, op): + def consider_strsetitem(self, op, ignored): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) @@ -785,7 +808,7 @@ return (ops0 + ops1 + ops2 + [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) - def consider_setarrayitem_gc(self, op): + def consider_setarrayitem_gc(self, op, ignored): scale, ofs = self._unpack_arraydescr(op.args[1].getint()) assert scale == 2 args = [op.args[0], op.args[2], op.args[3]] @@ -797,7 +820,7 @@ [PerformDiscard(op, [base_loc, ofs_loc, value_loc, imm(scale), imm(ofs)])]) - def consider_getfield_gc(self, op): + def consider_getfield_gc(self, op, ignored): ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) @@ -805,7 +828,7 @@ return (ops0 + more_ops + [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) - def consider_getarrayitem_gc(self, op): + def consider_getarrayitem_gc(self, op, ignored): scale, ofs = self._unpack_arraydescr(op.args[1].getint()) args = [op.args[0], op.args[2]] base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) @@ -819,7 +842,7 @@ consider_getfield_raw = consider_getfield_gc - def _consider_listop(self, op): + def _consider_listop(self, op, ignored): return self._call(op, [self.loc(arg) for arg in op.args]) xxx_consider_getitem = _consider_listop @@ -831,7 +854,7 @@ xxx_consider_insert = _consider_listop xxx_consider_listnonzero = _consider_listop -# def consider_same_as(self, op): +# def consider_same_as(self, op, ignored): # x = op.args[0] # if isinstance(x, Const): # pos = self.allocate_new_loc(op.result) @@ -850,13 +873,13 @@ # consider_cast_int_to_char = consider_same_as # xxx_consider_cast_int_to_ptr = consider_same_as - def consider_int_is_true(self, op): + def consider_int_is_true(self, op, ignored): argloc, ops = self.force_allocate_reg(op.args[0], []) self.eventually_free_var(op.args[0]) resloc, more_ops = self.force_allocate_reg(op.result, []) return ops + more_ops + [Perform(op, [argloc], resloc)] - def _consider_nullity(self, op): + def _consider_nullity(self, op, ignored): # doesn't need a register in arg argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) @@ -866,13 +889,13 @@ consider_ooisnull = _consider_nullity consider_oononnull = _consider_nullity - def consider_strlen(self, op): + def consider_strlen(self, op, ignored): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] - def consider_arraylen_gc(self, op): + def consider_arraylen_gc(self, op, ignored): _, ofs = self._unpack_arraydescr(op.args[1].getint()) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) @@ -880,7 +903,7 @@ return ops0 + more_ops + [Perform(op, [base_loc, imm(ofs)], result_loc)] - def consider_strgetitem(self, op): + def consider_strgetitem(self, op, ignored): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) @@ -888,7 +911,7 @@ return (ops0 + ops1 + more_ops + [Perform(op, [base_loc, ofs_loc], result_loc)]) - def consider_jump(self, op): + def consider_jump(self, op, ignored): ops = [] laterops = [] middle_ops = [] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Tue Mar 3 10:34:16 2009 @@ -14,6 +14,7 @@ from pypy.jit.backend.x86.assembler import Assembler386 from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname +from pypy.jit.backend.x86.executor import execute class CPU386(object): debug = True @@ -55,8 +56,9 @@ def _setup_ovf_error(self): if self.translate_support_code: - self._ovf_error_vtable = 0 - self._ovf_error_inst = 0 + self.assembler._ovf_error_vtable = 0 + self.assembler._ovf_error_inst = 0 + xxx # do something here else: bk = self.rtyper.annotator.bookkeeper @@ -64,8 +66,8 @@ ovferror_repr = rclass.getclassrepr(self.rtyper, clsdef) ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance( self.rtyper, clsdef) - self._ovf_error_vtable = self.cast_ptr_to_int(ll_inst.typeptr) - self._ovf_error_inst = self.cast_ptr_to_int(ll_inst) + self.assembler._ovf_error_vtable = self.cast_ptr_to_int(ll_inst.typeptr) + self.assembler._ovf_error_inst = self.cast_ptr_to_int(ll_inst) def setup(self): self.assembler = Assembler386(self, self.translate_support_code) @@ -128,23 +130,18 @@ def set_meta_interp(self, metainterp): self.metainterp = metainterp - def _get_overflow_error(self): - self.assembler._exception_data[1] = self._ovf_error_inst - return self._ovf_error_vtable - def get_exception(self, frame): res = self.assembler._exception_data[0] self.assembler._exception_data[0] = 0 - if res == 1: - # it's an overflow error, but we need to do all the dance - # to get a correct exception - return self._get_overflow_error() return res def get_exc_value(self, frame): return self.cast_int_to_gcref(self.assembler._exception_data[1]) def execute_operation(self, opnum, valueboxes, result_type): + if execute[opnum] is not None: + return execute[opnum](valueboxes) + # mostly a hack: fall back to compiling and executing the single # operation. key = [] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Tue Mar 3 10:34:16 2009 @@ -341,6 +341,7 @@ assert c.value == 3 def test_ovf_ops(self): + py.test.skip("Cannot run like this, rewrite me") arg0 = BoxInt(12) arg1 = BoxInt(13) res = self.execute_operation(rop.INT_MUL_OVF, [arg0, arg1], 'int') From fijal at codespeak.net Tue Mar 3 11:39:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 11:39:38 +0100 (CET) Subject: [pypy-svn] r62445 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090303103938.18566168505@codespeak.net> Author: fijal Date: Tue Mar 3 11:39:36 2009 New Revision: 62445 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Log: done and don't care Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Tue Mar 3 11:39:36 2009 @@ -1,9 +1,4 @@ -* Kill hack for .position attr of modrm (there is a method for that as well, - unsure what's saner) - -* SETO vs CMOVO - * test_zrpy_exceptions, needed * fix ll2ctypes for typeptr accesses (test_tl*) From fijal at codespeak.net Tue Mar 3 12:06:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 12:06:14 +0100 (CET) Subject: [pypy-svn] r62446 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090303110614.7758016850A@codespeak.net> Author: fijal Date: Tue Mar 3 12:06:12 2009 New Revision: 62446 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: fix test Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Tue Mar 3 12:06:12 2009 @@ -134,7 +134,7 @@ spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [A.sum, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), @@ -183,7 +183,7 @@ spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [B.sum, B.n1], None), # guard_class is gone @@ -240,7 +240,7 @@ spec = PerfectSpecializer(Loop(C.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone @@ -302,7 +302,7 @@ spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [E.sum, E.v], None), # guard_class is gone @@ -341,7 +341,7 @@ spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) guard_op = spec.loop.operations[-2] v_sum_b = BoxInt(13) v_v_b = BoxInt(14) @@ -400,7 +400,7 @@ spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [F.sum, F.v, F.n3], None), ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), @@ -432,7 +432,7 @@ spec = PerfectSpecializer(Loop(F2.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, F2.ops) # ____________________________________________________________ @@ -464,7 +464,7 @@ spec = PerfectSpecializer(Loop(G.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [G.sum, G.v], None), # guard_class is gone @@ -595,7 +595,7 @@ spec = PerfectSpecializer(Loop(K0.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K0.sum, K0.n1, K0.v], None), @@ -630,7 +630,7 @@ spec = PerfectSpecializer(Loop(K1.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K1.sum, K1.n1, K1.v], None), @@ -665,7 +665,7 @@ spec = PerfectSpecializer(Loop(K.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K.sum, K.n1, K.v], None), ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), @@ -697,7 +697,7 @@ spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [L.sum, L.n1, L.v], None), ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), @@ -729,7 +729,7 @@ spec = PerfectSpecializer(Loop(M.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [M.sum, M.n1, M.v], None), @@ -761,7 +761,7 @@ spec = PerfectSpecializer(Loop(N.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [N.sum, N.n1, N.v], None), @@ -792,7 +792,7 @@ spec = PerfectSpecializer(Loop(O1.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O1.n1), @@ -823,7 +823,7 @@ spec = PerfectSpecializer(Loop(O2.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O2.n1), @@ -856,7 +856,7 @@ spec = PerfectSpecializer(Loop(O3.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O3.n1), From fijal at codespeak.net Tue Mar 3 12:09:30 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 12:09:30 +0100 (CET) Subject: [pypy-svn] r62447 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090303110930.4BE4E168513@codespeak.net> Author: fijal Date: Tue Mar 3 12:09:29 2009 New Revision: 62447 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: fix the backend Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Tue Mar 3 12:09:29 2009 @@ -765,7 +765,7 @@ return len(array.items) def op_setarrayitem_gc(self, array, arraydesc, index, newvalue): - ITEMTYPE = symbolic.Size2Type[arraydesc/2] + ITEMTYPE = symbolic.Size2Type[arraydesc/2].OF array = array._obj.container newvalue = self._cast_newvalue(arraydesc, ITEMTYPE, newvalue) array.setitem(index, newvalue) From fijal at codespeak.net Tue Mar 3 12:10:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 12:10:21 +0100 (CET) Subject: [pypy-svn] r62448 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090303111021.5669B16850A@codespeak.net> Author: fijal Date: Tue Mar 3 12:10:20 2009 New Revision: 62448 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Log: another test fixing Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Tue Mar 3 12:10:20 2009 @@ -45,7 +45,7 @@ spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation(rop.MERGE_POINT, [A.l, A.e0], None), ResOperation(rop.SETARRAYITEM_GC, [A.l, A.ad, ConstInt(0), A.e0], None), @@ -74,7 +74,7 @@ spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation(rop.MERGE_POINT, [B.l, B.e0], None), ResOperation(rop.INT_ADD, [B.e0, ConstInt(1)], B.e1), From fijal at codespeak.net Tue Mar 3 12:11:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 12:11:22 +0100 (CET) Subject: [pypy-svn] r62449 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090303111122.13094168513@codespeak.net> Author: fijal Date: Tue Mar 3 12:11:21 2009 New Revision: 62449 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: yet-another-arg missing Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 3 12:11:21 2009 @@ -116,7 +116,7 @@ spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop() + spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [A.sum, A.fr, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), From arigo at codespeak.net Tue Mar 3 12:14:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 3 Mar 2009 12:14:00 +0100 (CET) Subject: [pypy-svn] r62450 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090303111400.E2390168513@codespeak.net> Author: arigo Date: Tue Mar 3 12:13:57 2009 New Revision: 62450 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: Fix op_arraylen_gc in the backend. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Tue Mar 3 12:13:57 2009 @@ -762,7 +762,7 @@ def op_arraylen_gc(self, array, arraydesc): array = array._obj.container - return len(array.items) + return array.getlength() def op_setarrayitem_gc(self, array, arraydesc, index, newvalue): ITEMTYPE = symbolic.Size2Type[arraydesc/2].OF From cfbolz at codespeak.net Tue Mar 3 13:18:52 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:18:52 +0100 (CET) Subject: [pypy-svn] r62455 - pypy/trunk/pypy/config Message-ID: <20090303121852.40CD9168507@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:18:50 2009 New Revision: 62455 Modified: pypy/trunk/pypy/config/pypyoption.py Log: don't compile bz2 if the headers are not there Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Tue Mar 3 13:18:50 2009 @@ -71,6 +71,7 @@ "_rawffi" : ["pypy.rlib.libffi"], "zlib" : ["pypy.rlib.rzlib"], + "bz2" : ["pypy.module.bz2.interp_bz2"], } def get_module_validator(modname): From cfbolz at codespeak.net Tue Mar 3 13:20:04 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:20:04 +0100 (CET) Subject: [pypy-svn] r62456 - pypy/trunk/pypy/objspace/std Message-ID: <20090303122004.B835C16850A@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:20:04 2009 New Revision: 62456 Modified: pypy/trunk/pypy/objspace/std/objspace.py pypy/trunk/pypy/objspace/std/setobject.py Log: Removed some code duplication. Fix an error message. Kill the rarely used space.new[frozen]set. Modified: pypy/trunk/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/pypy/objspace/std/objspace.py Tue Mar 3 13:20:04 2009 @@ -556,12 +556,6 @@ def newcomplex(self, realval, imagval): return W_ComplexObject(realval, imagval) - def newset(self, rdict_w): - return W_SetObject(self, rdict_w) - - def newfrozenset(self, rdict_w): - return W_FrozensetObject(self, rdict_w) - def newlong(self, val): # val is an int return W_LongObject.fromint(self, val) Modified: pypy/trunk/pypy/objspace/std/setobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/setobject.py (original) +++ pypy/trunk/pypy/objspace/std/setobject.py Tue Mar 3 13:20:04 2009 @@ -76,7 +76,7 @@ if w_setiter.len != len(content): w_setiter.len = -1 # Make this error state sticky raise OperationError(space.w_RuntimeError, - space.wrap("dictionary changed size during iteration")) + space.wrap("Set changed size during iteration")) # look for the next entry w_result = w_setiter.next_entry() if w_result is not None: @@ -116,7 +116,8 @@ def _convert_set_to_frozenset(space, w_obj): if space.is_true(space.isinstance(w_obj, space.w_set)): - return space.newfrozenset(make_setdata_from_w_iterable(space, w_obj)) + return W_FrozensetObject(space, + make_setdata_from_w_iterable(space, w_obj)) else: return None @@ -197,6 +198,16 @@ return ld, rdict +def _issubset_dict(ldict, rdict): + if len(ldict) > len(rdict): + return False + + for w_key in ldict: + if w_key not in rdict: + return False + return True + + #end helper functions def set_update__Set_Set(space, w_left, w_other): @@ -327,13 +338,7 @@ if space.is_w(w_left, w_other): return space.w_True ld, rd = w_left.setdata, w_other.setdata - if len(ld) > len(rd): - return space.w_False - - for w_key in ld: - if w_key not in rd: - return space.w_False - return space.w_True + return space.wrap(_issubset_dict(ld, rd)) set_issubset__Set_Frozenset = set_issubset__Set_Set frozenset_issubset__Frozenset_Set = set_issubset__Set_Set @@ -344,13 +349,7 @@ return space.w_True ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other) - if len(ld) > len(rd): - return space.w_False - - for w_key in ld: - if w_key not in rd: - return space.w_False - return space.w_True + return space.wrap(_issubset_dict(ld, rd)) frozenset_issubset__Frozenset_ANY = set_issubset__Set_ANY @@ -365,13 +364,7 @@ return space.w_True ld, rd = w_left.setdata, w_other.setdata - if len(ld) < len(rd): - return space.w_False - - for w_key in rd: - if w_key not in ld: - return space.w_False - return space.w_True + return space.wrap(_issubset_dict(rd, ld)) set_issuperset__Set_Frozenset = set_issuperset__Set_Set set_issuperset__Frozenset_Set = set_issuperset__Set_Set @@ -382,13 +375,7 @@ return space.w_True ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other) - if len(ld) < len(rd): - return space.w_False - - for w_key in rd: - if w_key not in ld: - return space.w_False - return space.w_True + return space.wrap(_issubset_dict(rd, ld)) frozenset_issuperset__Frozenset_ANY = set_issuperset__Set_ANY From cfbolz at codespeak.net Tue Mar 3 13:21:42 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:21:42 +0100 (CET) Subject: [pypy-svn] r62457 - pypy/trunk/pypy/objspace/std Message-ID: <20090303122142.8D1C7168507@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:21:41 2009 New Revision: 62457 Modified: pypy/trunk/pypy/objspace/std/intobject.py pypy/trunk/pypy/objspace/std/smallintobject.py Log: Kill some strange code. Share at least one helper between smallintobject and intobject. Modified: pypy/trunk/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/pypy/objspace/std/intobject.py Tue Mar 3 13:21:41 2009 @@ -106,7 +106,7 @@ space.wrap("integer multiplication")) return wrapint(space, z) -def _floordiv(space, w_int1, w_int2): +def floordiv__Int_Int(space, w_int1, w_int2): x = w_int1.intval y = w_int2.intval try: @@ -118,14 +118,14 @@ raise FailedToImplement(space.w_OverflowError, space.wrap("integer division")) return wrapint(space, z) +div__Int_Int = floordiv__Int_Int -def _truediv(space, w_int1, w_int2): - # XXX how to do delegation to float elegantly? - # avoiding a general space.div operation which pulls - # the whole interpreter in. - # Instead, we delegate to long for now. - raise FailedToImplement(space.w_TypeError, - space.wrap("integer division")) +def truediv__Int_Int(space, w_int1, w_int2): + x = float(w_int1.intval) + y = float(w_int2.intval) + if y == 0.0: + raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float division")) + return space.wrap(x / y) def mod__Int_Int(space, w_int1, w_int2): x = w_int1.intval @@ -156,11 +156,6 @@ w = space.wrap return space.newtuple([w(z), w(m)]) -def div__Int_Int(space, w_int1, w_int2): - return _floordiv(space, w_int1, w_int2) - -floordiv__Int_Int = _floordiv -truediv__Int_Int = _truediv # helper for pow() def _impl_int_int_pow(space, iv, iw, iz=0): @@ -216,11 +211,6 @@ space.wrap("integer negation")) return wrapint(space, x) -# pos__Int is supposed to do nothing, unless it has -# a derived integer object, where it should return -# an exact one. -def pos__Int(space, w_int1): - return int__Int(space, w_int1) def abs__Int(space, w_int1): if w_int1.intval >= 0: @@ -297,6 +287,7 @@ return w_int1 a = w_int1.intval return wrapint(space, a) +pos__Int = int__Int def index__Int(space, w_int1): return int__Int(space, w_int1) Modified: pypy/trunk/pypy/objspace/std/smallintobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/smallintobject.py (original) +++ pypy/trunk/pypy/objspace/std/smallintobject.py Tue Mar 3 13:21:41 2009 @@ -63,35 +63,21 @@ str__SmallInt = repr__SmallInt -def lt__SmallInt_SmallInt(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i < j ) - -def le__SmallInt_SmallInt(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i <= j ) - -def eq__SmallInt_SmallInt(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i == j ) - -def ne__SmallInt_SmallInt(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i != j ) - -def gt__SmallInt_SmallInt(space, w_int1, w_int2): - i = w_int1.intval - j = w_int2.intval - return space.newbool( i > j ) - -def ge__SmallInt_SmallInt(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 + "__SmallInt_SmallInt" + 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__SmallInt(space, w_int1): # unlike CPython, we don't special-case the value -1 in most of our @@ -134,7 +120,7 @@ space.wrap("integer multiplication")) return wrapint(space, z) -def _floordiv(space, w_int1, w_int2): +def div__SmallInt_SmallInt(space, w_int1, w_int2): x = w_int1.intval y = w_int2.intval try: @@ -147,13 +133,14 @@ space.wrap("integer division")) return wrapint(space, z) -def _truediv(space, w_int1, w_int2): - # XXX how to do delegation to float elegantly? - # avoiding a general space.div operation which pulls - # the whole interpreter in. - # Instead, we delegate to long for now. - raise FailedToImplement(space.w_TypeError, - space.wrap("integer division")) +floordiv__SmallInt_SmallInt = div__SmallInt_SmallInt + +def truediv__SmallInt_SmallInt(space, w_int1, w_int2): + x = float(w_int1.intval) + y = float(w_int2.intval) + if y == 0.0: + raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float division")) + return space.wrap(x / y) def mod__SmallInt_SmallInt(space, w_int1, w_int2): x = w_int1.intval @@ -183,44 +170,8 @@ m = x % y return space.newtuple([space.wrap(z), space.wrap(m)]) -def div__SmallInt_SmallInt(space, w_int1, w_int2): - return _floordiv(space, w_int1, w_int2) - -floordiv__SmallInt_SmallInt = _floordiv -truediv__SmallInt_SmallInt = _truediv - -# helper for pow() -def _impl_int_int_pow(space, iv, iw, iz=0): - if iw < 0: - if iz != 0: - raise OperationError(space.w_TypeError, - space.wrap("pow() 2nd argument " - "cannot be negative when 3rd argument specified")) - ## bounce it, since it always returns float - raise FailedToImplement(space.w_ValueError, - space.wrap("integer exponentiation")) - temp = iv - ix = 1 - try: - while iw > 0: - if iw & 1: - ix = ovfcheck(ix*temp) - iw >>= 1 #/* Shift exponent down by 1 bit */ - if iw==0: - break - temp = ovfcheck(temp*temp) #/* Square the value of temp */ - if iz: - #/* If we did a multiplication, perform a modulo */ - ix = ix % iz; - temp = temp % iz; - if iz: - ix = ix % iz - except OverflowError: - raise FailedToImplement(space.w_OverflowError, - space.wrap("integer exponentiation")) - return wrapint(space, ix) - def pow__SmallInt_SmallInt_SmallInt(space, w_int1, w_int2, w_int3): + from pypy.objspace.std.intobject import _impl_int_int_pow x = w_int1.intval y = w_int2.intval z = w_int3.intval @@ -230,6 +181,7 @@ return _impl_int_int_pow(space, x, y, z) def pow__SmallInt_SmallInt_None(space, w_int1, w_int2, w_int3): + from pypy.objspace.std.intobject import _impl_int_int_pow x = w_int1.intval y = w_int2.intval return _impl_int_int_pow(space, x, y) @@ -243,11 +195,6 @@ space.wrap("integer negation")) return wrapint(space, x) -# pos__SmallInt is supposed to do nothing, unless it has -# a derived integer object, where it should return -# an exact one. -def pos__SmallInt(space, w_int1): - return int__SmallInt(space, w_int1) def abs__SmallInt(space, w_int1): if w_int1.intval >= 0: @@ -351,6 +298,7 @@ return w_int1 a = w_int1.intval return wrapint(space, a) +pos__SmallInt = int__SmallInt """ # Not registered From tverwaes at codespeak.net Tue Mar 3 13:23:38 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 13:23:38 +0100 (CET) Subject: [pypy-svn] r62458 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090303122338.1F6FA168507@codespeak.net> Author: tverwaes Date: Tue Mar 3 13:23:37 2009 New Revision: 62458 Modified: pypy/trunk/pypy/lang/gameboy/cartridge.py pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: found a bug in the cartridge. we never reset the rom-size to 0!! Modified: pypy/trunk/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cartridge.py (original) +++ pypy/trunk/pypy/lang/gameboy/cartridge.py Tue Mar 3 13:23:37 2009 @@ -297,7 +297,6 @@ self.rom_bank = self.rom_bank_size self.ram_bank = 0 self.ram_enable = False - self.rom_size = 0 self.ram_size = 0 def set_rom(self, buffer): @@ -408,6 +407,8 @@ # % hex(address)) def write_rom_bank_1(self, address, data): + #import pdb + #pdb.set_trace() if (data & 0x1F) == 0: data = 1 if self.memory_model == 0: @@ -825,7 +826,7 @@ MEMORY_BANK_TYPE_RANGES = [ - (constants.TYPE_MBC1, constants.TYPE_MBC1_RAM_BATTERY, MBC1), + (constants.TYPE_ROM_ONLY, 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), @@ -837,10 +838,10 @@ def initialize_mapping_table(): result = [DefaultMBC] * 256 for entry in MEMORY_BANK_TYPE_RANGES: - if len(entry) == 2: - positions = [entry[0]] - else: - positions = range(entry[0], entry[1]+1) + #if len(entry) == 2: + # positions = [entry[0]] + #else: + positions = range(entry[0], entry[1]+1) for pos in positions: result[pos] = entry[-1] return result Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 3 13:23:37 2009 @@ -237,7 +237,8 @@ # Fetching 1 cycle if use_cycles: self.cycles += 1 - if self.pc.get(use_cycles) <= 0x3FFF: + pc = self.pc.get(use_cycles) + if pc <= 0x3FFF: data = self.rom[self.pc.get(use_cycles)] else: data = self.memory.read(self.pc.get(use_cycles)) @@ -288,7 +289,8 @@ def load(self, getCaller, setCaller): # 1 cycle - setCaller.set(getCaller.get()) # 1 cycle + value = getCaller.get() + setCaller.set(value) # 1 cycle def load_fetch_register(self, register): self.load(CPUFetchCaller(self), RegisterCallWrapper(register)) Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Tue Mar 3 13:23:37 2009 @@ -45,6 +45,7 @@ self.reset_value = reset_value def set(self, value, use_cycles=True): + # previous = self.get(False) value = value & 0xFFFF self.set_hi(value >> 8, use_cycles) self.set_lo(value & 0xFF, use_cycles) @@ -209,4 +210,4 @@ #def is_carry_compare(self, a, b): # self.is_carry = (a < b) - \ No newline at end of file + Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Tue Mar 3 13:23:37 2009 @@ -275,10 +275,10 @@ @printframe("comparing memory") def compare_video_memory(self, data): cmp = [ - ("vram", self.video.vram, "vram"), + # ("vram", self.video.vram, "vram"), ("oam", self.video.oam, "oam"), ("line", self.video.line, "line"), - ("objects", self.video.objects, "objects"), + # ("objects", self.video.objects, "objects"), ("palette", self.video.palette, "palette"), ] self.compare_memory_set(cmp, data, label="video"); Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Tue Mar 3 13:23:37 2009 @@ -12,7 +12,8 @@ # ------------------------------------------------------------------------------ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" -filename = ROM_PATH + "/rom9/rom9.gb" +# filename = ROM_PATH + "/rom9/rom9.gb" +filename = "/home/tverwaes/roms/KirbysDreamLand.gb" SOCKET_PORT = 55682 skip_count = 22545 Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Tue Mar 3 13:23:37 2009 @@ -124,7 +124,7 @@ def write(self, address, data): receiver = self.get_receiver(address) if receiver is None: - raise Exception("invalid read address given") + raise Exception(("invalid write address given: ",address," ",data)) receiver.write(address, data) if address == constants.STAT or address == 0xFFFF: self.cpu.handle_pending_interrupts() @@ -132,7 +132,7 @@ def read(self, address): receiver = self.get_receiver(address) if receiver is None: - # raise Exception("invalid read address given") + # raise Exception("invalid read address given: ", address) return 0xFF return receiver.read(address) Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Tue Mar 3 13:23:37 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = True +use_rsdl = False if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi From cfbolz at codespeak.net Tue Mar 3 13:23:42 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:23:42 +0100 (CET) Subject: [pypy-svn] r62459 - pypy/trunk/pypy/objspace/std Message-ID: <20090303122342.0929B168572@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:23:42 2009 New Revision: 62459 Modified: pypy/trunk/pypy/objspace/std/dicttype.py Log: kill old comment Modified: pypy/trunk/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/trunk/pypy/objspace/std/dicttype.py (original) +++ pypy/trunk/pypy/objspace/std/dicttype.py Tue Mar 3 13:23:42 2009 @@ -229,24 +229,3 @@ __reduce__ = gateway.interp2app(descr_dictiter__reduce__, unwrap_spec=[gateway.W_Root, gateway.ObjSpace]), ) -#note: registering in dictobject.py - - -### fragment for frame object left here - #w(10), - #w(self.co_argcount), - #w(self.co_nlocals), - #w(self.co_stacksize), - #w(self.co_flags), - #w(self.co_code), - #space.newtuple(self.co_consts_w), - #space.newtuple(self.co_names_w), - #space.newtuple([w(v) for v in self.co_varnames]), - #w(self.co_filename), - #w(self.co_name), - #w(self.co_firstlineno), - #w(self.co_lnotab), - #space.newtuple([w(v) for v in self.co_freevars]), - #space.newtuple([w(v) for v in self.co_cellvars]), - #hidden_applevel=False, magic = 62061 | 0x0a0d0000 - From cfbolz at codespeak.net Tue Mar 3 13:24:25 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:24:25 +0100 (CET) Subject: [pypy-svn] r62460 - pypy/trunk/pypy/objspace/std Message-ID: <20090303122425.21376168536@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:24:24 2009 New Revision: 62460 Modified: pypy/trunk/pypy/objspace/std/complexobject.py Log: kill some superstitious asserts in complexobject. Modified: pypy/trunk/pypy/objspace/std/complexobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/complexobject.py (original) +++ pypy/trunk/pypy/objspace/std/complexobject.py Tue Mar 3 13:24:24 2009 @@ -1,7 +1,6 @@ from pypy.interpreter import gateway from pypy.objspace.std.objspace import W_Object, OperationError from pypy.objspace.std.objspace import registerimplementation, register_all -from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.floatobject import W_FloatObject, _hash_float import math @@ -33,9 +32,6 @@ def _diff(c1, c2): return (c1[0]-c2[0],c1[1]-c2[1]) -def _neg(c): - return (-c[0],-c[1]) - def _prod(c1, c2): r = c1[0]*c2[0] - c1[1]*c2[1] i = c1[0]*c2[1] + c1[1]*c2[0] @@ -144,7 +140,6 @@ def _w2t(space, w_complex): "convert an interplevel complex object to a tuple representation" - assert space.is_true(space.isinstance(w_complex, space.w_complex)) return w_complex.realval, w_complex.imagval def _t2w(space, c): @@ -197,7 +192,7 @@ return _t2w(space, div) def pow__Complex_Complex_ANY(space, w_complex1, w_complex2, thirdArg): - if not isinstance(thirdArg, W_NoneObject): + if not space.is_w(thirdArg, space.w_None): raise OperationError(space.w_ValueError, space.wrap('complex modulo')) try: v = _w2t(space, w_complex1) @@ -214,26 +209,19 @@ return _t2w(space, p) def neg__Complex(space, w_complex): - assert space.is_true(space.isinstance(w_complex, space.w_complex)) return W_ComplexObject(-w_complex.realval, -w_complex.imagval) def pos__Complex(space, w_complex): - assert space.is_true(space.isinstance(w_complex, space.w_complex)) return W_ComplexObject(w_complex.realval, w_complex.imagval) def abs__Complex(space, w_complex): - assert space.is_true(space.isinstance(w_complex, space.w_complex)) return space.newfloat(math.hypot(w_complex.realval, w_complex.imagval)) def eq__Complex_Complex(space, w_complex1, w_complex2): - assert space.is_true(space.isinstance(w_complex1, space.w_complex)) - assert space.is_true(space.isinstance(w_complex2, space.w_complex)) return space.newbool((w_complex1.realval == w_complex2.realval) and (w_complex1.imagval == w_complex2.imagval)) def ne__Complex_Complex(space, w_complex1, w_complex2): - assert space.is_true(space.isinstance(w_complex1, space.w_complex)) - assert space.is_true(space.isinstance(w_complex2, space.w_complex)) return space.newbool((w_complex1.realval != w_complex2.realval) or (w_complex1.imagval != w_complex2.imagval)) @@ -245,7 +233,6 @@ le__Complex_Complex = lt__Complex_Complex def nonzero__Complex(space, w_complex): - assert space.is_true(space.isinstance(w_complex, space.w_complex)) return space.newbool((w_complex.realval != 0.0) or (w_complex.imagval != 0.0)) From cfbolz at codespeak.net Tue Mar 3 13:25:00 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:25:00 +0100 (CET) Subject: [pypy-svn] r62461 - pypy/trunk/pypy/objspace/std Message-ID: <20090303122500.3B0F3168507@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:24:58 2009 New Revision: 62461 Modified: pypy/trunk/pypy/objspace/std/floatobject.py Log: Kill more superstitious code: FloatingPointErrors are never raised. Modified: pypy/trunk/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/floatobject.py (original) +++ pypy/trunk/pypy/objspace/std/floatobject.py Tue Mar 3 13:24:58 2009 @@ -248,41 +248,24 @@ def add__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval - try: - z = x + y - except FloatingPointError: - raise FailedToImplement(space.w_FloatingPointError, space.wrap("float addition")) - return W_FloatObject(z) + return W_FloatObject(x + y) def sub__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval - try: - z = x - y - except FloatingPointError: - raise FailedToImplement(space.w_FloatingPointError, space.wrap("float substraction")) - return W_FloatObject(z) + return W_FloatObject(x - y) def mul__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval - try: - z = x * y - except FloatingPointError: - raise FailedToImplement(space.w_FloatingPointError, space.wrap("float multiplication")) - return W_FloatObject(z) + return W_FloatObject(x * y) def div__Float_Float(space, w_float1, w_float2): x = w_float1.floatval y = w_float2.floatval if y == 0.0: raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float division")) - try: - z = x / y - except FloatingPointError: - raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) - # no overflow - return W_FloatObject(z) + return W_FloatObject(x / y) truediv__Float_Float = div__Float_Float @@ -295,12 +278,9 @@ y = w_float2.floatval if y == 0.0: raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float modulo")) - try: - mod = math.fmod(x, y) - if (mod and ((y < 0.0) != (mod < 0.0))): - mod += y - except FloatingPointError: - raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) + mod = math.fmod(x, y) + if (mod and ((y < 0.0) != (mod < 0.0))): + mod += y return W_FloatObject(mod) @@ -309,38 +289,35 @@ y = w_float2.floatval if y == 0.0: raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float modulo")) - try: - mod = math.fmod(x, y) - # fmod is typically exact, so vx-mod is *mathematically* an - # exact multiple of wx. But this is fp arithmetic, and fp - # vx - mod is an approximation; the result is that div may - # not be an exact integral value after the division, although - # it will always be very close to one. - div = (x - mod) / y - if (mod): - # ensure the remainder has the same sign as the denominator - if ((y < 0.0) != (mod < 0.0)): - mod += y - div -= 1.0 - else: - # the remainder is zero, and in the presence of signed zeroes - # fmod returns different results across platforms; ensure - # it has the same sign as the denominator; we'd like to do - # "mod = wx * 0.0", but that may get optimized away - mod *= mod # hide "mod = +0" from optimizer - if y < 0.0: - mod = -mod - # snap quotient to nearest integral value - if div: - floordiv = math.floor(div) - if (div - floordiv > 0.5): - floordiv += 1.0 - else: - # div is zero - get the same sign as the true quotient - div *= div # hide "div = +0" from optimizers - floordiv = div * x / y # zero w/ sign of vx/wx - except FloatingPointError: - raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) + mod = math.fmod(x, y) + # fmod is typically exact, so vx-mod is *mathematically* an + # exact multiple of wx. But this is fp arithmetic, and fp + # vx - mod is an approximation; the result is that div may + # not be an exact integral value after the division, although + # it will always be very close to one. + div = (x - mod) / y + if (mod): + # ensure the remainder has the same sign as the denominator + if ((y < 0.0) != (mod < 0.0)): + mod += y + div -= 1.0 + else: + # the remainder is zero, and in the presence of signed zeroes + # fmod returns different results across platforms; ensure + # it has the same sign as the denominator; we'd like to do + # "mod = wx * 0.0", but that may get optimized away + mod *= mod # hide "mod = +0" from optimizer + if y < 0.0: + mod = -mod + # snap quotient to nearest integral value + if div: + floordiv = math.floor(div) + if (div - floordiv > 0.5): + floordiv += 1.0 + else: + # div is zero - get the same sign as the true quotient + div *= div # hide "div = +0" from optimizers + floordiv = div * x / y # zero w/ sign of vx/wx return [W_FloatObject(floordiv), W_FloatObject(mod)] From afa at codespeak.net Tue Mar 3 13:31:04 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 3 Mar 2009 13:31:04 +0100 (CET) Subject: [pypy-svn] r62462 - pypy/trunk/pypy/config Message-ID: <20090303123104.706CC168507@codespeak.net> Author: afa Date: Tue Mar 3 13:31:03 2009 New Revision: 62462 Modified: pypy/trunk/pypy/config/pypyoption.py Log: No need to special-case bz2 on windows: bz2 will be skipped if header files cannot be found Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Tue Mar 3 13:31:03 2009 @@ -45,8 +45,6 @@ del working_modules["fcntl"] del working_modules["termios"] del working_modules["_minimal_curses"] - # XXX this is temporary, hopefully - del working_modules["bz2"] if sys.platform == "sunos5": del working_modules['mmap'] # depend on ctypes, can't get at c-level 'errono' From cfbolz at codespeak.net Tue Mar 3 13:32:22 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 3 Mar 2009 13:32:22 +0100 (CET) Subject: [pypy-svn] r62463 - pypy/trunk/pypy/module/sys Message-ID: <20090303123222.0434C168536@codespeak.net> Author: cfbolz Date: Tue Mar 3 13:32:22 2009 New Revision: 62463 Modified: pypy/trunk/pypy/module/sys/__init__.py pypy/trunk/pypy/module/sys/vm.py Log: kill some commented out things and an unused function Modified: pypy/trunk/pypy/module/sys/__init__.py ============================================================================== --- pypy/trunk/pypy/module/sys/__init__.py (original) +++ pypy/trunk/pypy/module/sys/__init__.py Tue Mar 3 13:32:22 2009 @@ -70,8 +70,6 @@ 'setdefaultencoding' : 'interp_encoding.setdefaultencoding', } appleveldefs = { - #'displayhook' : 'app.displayhook', - #'__displayhook__' : 'app.__displayhook__', 'excepthook' : 'app.excepthook', '__excepthook__' : 'app.excepthook', 'exit' : 'app.exit', Modified: pypy/trunk/pypy/module/sys/vm.py ============================================================================== --- pypy/trunk/pypy/module/sys/vm.py (original) +++ pypy/trunk/pypy/module/sys/vm.py Tue Mar 3 13:32:22 2009 @@ -97,21 +97,6 @@ if operror is not None: operror.clear(space) -def pypy_getudir(space): - """NOT_RPYTHON""" - from pypy.tool.udir import udir - return space.wrap(str(udir)) - -## def getrefcount(space, w_obj): -## """getrefcount(object) -> integer -## Return the reference count of object. The count returned is generally -## one higher than you might expect, because it includes the (temporary) -## reference as an argument to getrefcount(). -## """ -## # From the results i get when using this i need to apply a fudge -## # value of 6 to get results comparable to cpythons. /Arre -## return space.wrap(sys.getrefcount(w_obj) - 6) - def settrace(space, w_func): """Set the global debug tracing function. It will be called on each function call. See the debugger chapter in the library manual.""" From fijal at codespeak.net Tue Mar 3 13:37:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 13:37:52 +0100 (CET) Subject: [pypy-svn] r62464 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090303123752.7E18116850A@codespeak.net> Author: fijal Date: Tue Mar 3 13:37:47 2009 New Revision: 62464 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: reorder operations, in order to do efficient comparison detection (not implemented yet) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Tue Mar 3 13:37:47 2009 @@ -98,26 +98,28 @@ INT_MUL = 32 INT_FLOORDIV = 33 INT_MOD = 34 - INT_LT = 35 - INT_LE = 36 - INT_EQ = 37 - INT_NE = 38 - INT_GT = 39 - INT_GE = 40 - INT_AND = 41 - INT_OR = 42 - INT_XOR = 43 - INT_RSHIFT = 44 - INT_LSHIFT = 45 - UINT_ADD = 46 - UINT_SUB = 47 - UINT_MUL = 48 - UINT_LT = 49 - UINT_LE = 50 - UINT_EQ = 51 - UINT_NE = 52 - UINT_GT = 53 - UINT_GE = 54 + INT_AND = 35 + INT_OR = 36 + INT_XOR = 37 + INT_RSHIFT = 38 + INT_LSHIFT = 39 + UINT_ADD = 40 + UINT_SUB = 41 + UINT_MUL = 42 + _COMPARISON_FIRST = 43 + INT_LT = 44 + INT_LE = 45 + INT_EQ = 46 + INT_NE = 47 + INT_GT = 48 + INT_GE = 49 + UINT_LT = 50 + UINT_LE = 51 + UINT_EQ = 52 + UINT_NE = 53 + UINT_GT = 54 + UINT_GE = 55 + _COMPARISON_LAST = 56 # INT_IS_TRUE = 60 INT_NEG = 61 From fijal at codespeak.net Tue Mar 3 13:55:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 13:55:29 +0100 (CET) Subject: [pypy-svn] r62466 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090303125529.9F13216857C@codespeak.net> Author: fijal Date: Tue Mar 3 13:55:29 2009 New Revision: 62466 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/executor.py (contents, props changed) Log: oops, missing file Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/executor.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/executor.py Tue Mar 3 13:55:29 2009 @@ -0,0 +1,27 @@ + +""" This is a simple class for executing operations directly, without +trying too hard to have execute_operation run +""" + +from pypy.rlib.rarithmetic import ovfcheck +from pypy.jit.metainterp.history import BoxInt +from pypy.jit.metainterp.resoperation import rop + +class Executor(object): + @staticmethod + def int_add_ovf(args): + return BoxInt(ovfcheck(args[0].getint() + args[1].getint())) + + @staticmethod + def int_sub_ovf(args): + return BoxInt(ovfcheck(args[0].getint() - args[1].getint())) + + @staticmethod + def int_mul_ovf(args): + return BoxInt(ovfcheck(args[0].getint() * args[1].getint())) + +execute = [None] * rop._LAST + +for key in Executor.__dict__: + if not key.startswith('_'): + execute[getattr(rop, key.upper())] = getattr(Executor, key) From arigo at codespeak.net Tue Mar 3 13:57:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 3 Mar 2009 13:57:14 +0100 (CET) Subject: [pypy-svn] r62467 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090303125714.217DE169DB2@codespeak.net> Author: arigo Date: Tue Mar 3 13:57:11 2009 New Revision: 62467 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Log: Do the right thing for negative list indices, and (correctly) skip optimizing at all list operations that could raise IndexError. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 3 13:57:11 2009 @@ -1,5 +1,6 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype, llmemory, rstr +from pypy.rpython import rlist from pypy.objspace.flow.model import Variable, Constant, Link, c_last_exception from pypy.rlib import objectmodel from pypy.rlib.objectmodel import we_are_translated @@ -737,20 +738,24 @@ # if (oopspec_name == 'list.getitem' or oopspec_name == 'list.getitem_foldable'): # <- XXX do better here - # XXX check if index < 0, and check IndexError, both only if needed + index = self.prepare_list_getset(op, arraydescr, args) + if index is None: + return False self.emit('getarrayitem_gc') self.emit(self.var_position(args[0])) self.emit(self.const_position(arraydescr)) - self.emit(self.var_position(args[1])) + self.emit(self.var_position(index)) self.register_var(op.result) return True # if oopspec_name == 'list.setitem': - # XXX check if index < 0, and check IndexError, both only if needed + index = self.prepare_list_getset(op, arraydescr, args) + if index is None: + return False self.emit('setarrayitem_gc') self.emit(self.var_position(args[0])) self.emit(self.const_position(arraydescr)) - self.emit(self.var_position(args[1])) + self.emit(self.var_position(index)) self.emit(self.var_position(args[2])) self.register_var(op.result) return True @@ -765,6 +770,27 @@ # return False + def prepare_list_getset(self, op, arraydescr, args): + func = op.args[0].value._obj._callable # xxx break of abstraction + non_negative = '_nonneg' in func.__name__ + tag = op.args[1].value + assert tag in (rlist.dum_nocheck, rlist.dum_checkidx) + can_raise = tag != rlist.dum_nocheck + # + if can_raise: + return None + if non_negative: + v_posindex = args[1] + else: + self.emit('check_neg_index') + self.emit(self.var_position(args[0])) + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(args[1])) + v_posindex = Variable('posindex') + v_posindex.concretetype = lltype.Signed + self.register_var(v_posindex) + return v_posindex + def serialize_op_indirect_call(self, op): self.minimize_variables() targets = self.codewriter.policy.graphs_from(op) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 3 13:57:11 2009 @@ -334,7 +334,20 @@ @arguments("box", "constbox") def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') + self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int', True) + + @arguments("orgpc", "box", "constbox", "box") + def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): + negbox = self.metainterp.history.execute_and_record( + rop.INT_LT, [indexbox, ConstInt(0)], 'int', True) + negbox = self.implement_guard_value(pc, negbox) + if negbox.getint(): + # the index is < 0; add the array length to it + lenbox = self.metainterp.history.execute_and_record( + rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int', True) + indexbox = self.metainterp.history.execute_and_record( + rop.INT_ADD, [indexbox, lenbox], 'int', True) + self.make_result_box(indexbox) @arguments("box") def opimpl_ptr_nonzero(self, box): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Tue Mar 3 13:57:11 2009 @@ -83,6 +83,20 @@ # two levels of list operations removed from the loop self.check_loops(call_void=0, call__4=0) + def test_lazy_getitem_4(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'lst']) + def f(n): + lst = [0] + while n > 0: + myjitdriver.can_enter_jit(n=n, lst=lst) + myjitdriver.jit_merge_point(n=n, lst=lst) + lst[-1] += 2 + n -= 1 + return lst[0] + res = self.meta_interp(f, [21], listops=True) + assert res == 42 + py.test.skip("not virtualized away so far") + class TestOOtype(ListTests, OOJitMixin): pass From fijal at codespeak.net Tue Mar 3 14:01:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 14:01:56 +0100 (CET) Subject: [pypy-svn] r62468 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090303130156.61E7116850A@codespeak.net> Author: fijal Date: Tue Mar 3 14:01:55 2009 New Revision: 62468 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: Tests that I would like to pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Tue Mar 3 14:01:55 2009 @@ -124,12 +124,46 @@ class Frame(object): _virtualizable2_ = True + + _virtualizable_desc_ = {'virtuals' : 'l'} + def __init__(self, l, s): self.l = l self.s = s - def f(n): - frame = Frame([1,2,3,4], 0) + def f(n, a): + frame = Frame([a,a+1,a+2,a+3], 0) + x = 0 + while n > 0: + myjitdriver.can_enter_jit(frame=frame, n=n, x=x) + myjitdriver.jit_merge_point(frame=frame, n=n, x=x) + frame.s = hint(frame.s, promote=True) + n -= 1 + x += frame.l[frame.s] + frame.s += 1 + x += frame.l[frame.s] + frame.s -= 1 + return x + + res = self.meta_interp(f, [10, 1], listops=True) + assert res == f(10, 1) + self.check_loops(getarrayitem_gc=0) + + + def test_virtualizable_with_list(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'x'], + virtualizables = ['frame']) + + + class Frame(object): + _virtualizable2_ = True + + def __init__(self, l, s): + self.l = l + self.s = s + + def f(n, a): + frame = Frame([a,a+1,a+2,a+3], 0) x = 0 while n > 0: myjitdriver.can_enter_jit(frame=frame, n=n, x=x) @@ -142,8 +176,9 @@ frame.s -= 1 return x - res = self.meta_interp(f, [10], listops=True) - assert res == f(10) + res = self.meta_interp(f, [10, 1], listops=True) + assert res == f(10, 1) + self.check_loops(getarrayitem_gc=2) def test_virtual_on_virtualizable(self): myjitdriver = JitDriver(greens = [], reds = ['frame', 'n'], @@ -158,11 +193,14 @@ class Frame(object): _virtualizable2_ = True + + _virtualizable_desc_ = {'virtuals' : 'stuff'} + def __init__(self, x): self.stuff = Stuff(x) def f(n): - frame = Frame(3) + frame = Frame(n/10) while n > 0: myjitdriver.can_enter_jit(frame=frame, n=n) myjitdriver.jit_merge_point(frame=frame, n=n) @@ -175,6 +213,38 @@ assert res == f(30) self.check_loops(getfield_gc=0) + + def test_no_virtual_on_virtualizable(self): + myjitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Stuff(object): + def __init__(self, x): + self.x = x + + class Stuff2(Stuff): + pass + + class Frame(object): + _virtualizable2_ = True + + def __init__(self, x): + self.stuff = Stuff(x) + + def f(n): + frame = Frame(n/10) + while n > 0: + myjitdriver.can_enter_jit(frame=frame, n=n) + myjitdriver.jit_merge_point(frame=frame, n=n) + if isinstance(frame.stuff, Stuff2): + return 2 + n -= frame.stuff.x + return n + + res = self.meta_interp(f, [30]) + assert res == f(30) + self.check_loops(getfield_gc=1) + def test_unequal_list_lengths_cannot_be_virtual(self): jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) From fijal at codespeak.net Tue Mar 3 14:06:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 14:06:49 +0100 (CET) Subject: [pypy-svn] r62469 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090303130649.6B92B168565@codespeak.net> Author: fijal Date: Tue Mar 3 14:06:48 2009 New Revision: 62469 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: oops, beaten by my own optimization. this is how the test should look like Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Tue Mar 3 14:06:48 2009 @@ -173,12 +173,13 @@ x += frame.l[frame.s] frame.s += 1 x += frame.l[frame.s] + frame.l[frame.s] += 1 frame.s -= 1 return x res = self.meta_interp(f, [10, 1], listops=True) assert res == f(10, 1) - self.check_loops(getarrayitem_gc=2) + self.check_loops(setarrayitem_gc=1) def test_virtual_on_virtualizable(self): myjitdriver = JitDriver(greens = [], reds = ['frame', 'n'], From arigo at codespeak.net Tue Mar 3 14:14:20 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 3 Mar 2009 14:14:20 +0100 (CET) Subject: [pypy-svn] r62470 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090303131420.D1940169E09@codespeak.net> Author: arigo Date: Tue Mar 3 14:14:18 2009 New Revision: 62470 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Add opimpl_getarrayitem_foldable_gc. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 3 14:14:18 2009 @@ -736,17 +736,13 @@ self.register_var(op.result) return True # - if (oopspec_name == 'list.getitem' or - oopspec_name == 'list.getitem_foldable'): # <- XXX do better here - index = self.prepare_list_getset(op, arraydescr, args) - if index is None: - return False - self.emit('getarrayitem_gc') - self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) - self.emit(self.var_position(index)) - self.register_var(op.result) - return True + if oopspec_name == 'list.getitem': + return self.handle_list_getitem(op, arraydescr, args, + 'getarrayitem_gc') + # + if oopspec_name == 'list.getitem_foldable': + return self.handle_list_getitem(op, arraydescr, args, + 'getarrayitem_foldable_gc') # if oopspec_name == 'list.setitem': index = self.prepare_list_getset(op, arraydescr, args) @@ -770,6 +766,17 @@ # return False + def handle_list_getitem(self, op, arraydescr, args, opname): + index = self.prepare_list_getset(op, arraydescr, args) + if index is None: + return False + self.emit(opname) + self.emit(self.var_position(args[0])) + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(index)) + self.register_var(op.result) + return True + def prepare_list_getset(self, op, arraydescr, args): func = op.args[0].value._obj._callable # xxx break of abstraction non_negative = '_nonneg' in func.__name__ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 3 14:14:18 2009 @@ -327,6 +327,12 @@ tp = self.metainterp.cpu.typefor(arraydesc.getint()) self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox], tp) + @arguments("box", "constbox", "box") + def opimpl_getarrayitem_foldable_gc(self, arraybox, arraydesc, indexbox): + tp = self.metainterp.cpu.typefor(arraydesc.getint()) + self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox], tp, + True) + @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): self.execute(rop.SETARRAYITEM_GC, [arraybox, arraydesc, From fijal at codespeak.net Tue Mar 3 14:37:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 14:37:58 +0100 (CET) Subject: [pypy-svn] r62471 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090303133758.48B9D168565@codespeak.net> Author: fijal Date: Tue Mar 3 14:37:57 2009 New Revision: 62471 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Log: propagate an _always_virtual_ attribute to hints Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Tue Mar 3 14:37:57 2009 @@ -64,6 +64,10 @@ self.top_of_virtualizable_hierarchy = True else: self.top_of_virtualizable_hierarchy = False + try: + self.virtuals = tuple(classdesc.classdict['_always_virtual_'].value) + except KeyError: + self.virtuals = () self.accessor = VirtualizableAccessor() def _setup_repr(self): @@ -72,7 +76,8 @@ llfields.append(('vable_base', llmemory.Address)) llfields.append(('vable_rti', VABLERTIPTR)) InstanceRepr._setup_repr(self, llfields, - hints = {'virtualizable2': True}, + hints = {'virtualizable2': True, + 'virtuals' : self.virtuals}, adtmeths = {'access': self.accessor}) if self.top_of_virtualizable_hierarchy: my_redirected_fields = [] From afa at codespeak.net Tue Mar 3 14:38:47 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 3 Mar 2009 14:38:47 +0100 (CET) Subject: [pypy-svn] r62472 - pypy/trunk/pypy/translator/cli Message-ID: <20090303133847.37687168565@codespeak.net> Author: afa Date: Tue Mar 3 14:38:46 2009 New Revision: 62472 Modified: pypy/trunk/pypy/translator/cli/function.py pypy/trunk/pypy/translator/cli/opcodes.py Log: cli backend: the "class" keywords seems mandatory for the Microsoft compiler Modified: pypy/trunk/pypy/translator/cli/function.py ============================================================================== --- pypy/trunk/pypy/translator/cli/function.py (original) +++ pypy/trunk/pypy/translator/cli/function.py Tue Mar 3 14:38:46 2009 @@ -131,7 +131,9 @@ if isinstance(link.last_exception, flowmodel.Variable): self.ilasm.opcode('dup') self.store(link.last_exc_value) - self.ilasm.call_method('[mscorlib]System.Type object::GetType()', virtual=True) + self.ilasm.call_method( + 'class [mscorlib]System.Type object::GetType()', + virtual=True) self.store(link.last_exception) else: self.store(link.last_exc_value) Modified: pypy/trunk/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/trunk/pypy/translator/cli/opcodes.py (original) +++ pypy/trunk/pypy/translator/cli/opcodes.py Tue Mar 3 14:38:46 2009 @@ -49,7 +49,7 @@ 'cli_fieldinfo_for_const': [FieldInfoForConst], 'oois': 'ceq', 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not, - 'classof': [PushAllArgs, 'callvirt instance [mscorlib]System.Type object::GetType()'], + 'classof': [PushAllArgs, 'callvirt instance class [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 fijal at codespeak.net Tue Mar 3 14:45:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 14:45:58 +0100 (CET) Subject: [pypy-svn] r62473 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090303134558.11945168565@codespeak.net> Author: fijal Date: Tue Mar 3 14:45:58 2009 New Revision: 62473 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Log: Actually use a hint for _always_virtual_ on top of virtualizables. Fix tests Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Mar 3 14:45:58 2009 @@ -124,6 +124,7 @@ self.dirtyfields = {} self.expanded_fields = {} self.cursize = -1 + self.vdesc = None # for virtualizables def is_nonzero(self): return self.cls is not None or self.nonzero @@ -140,6 +141,15 @@ if not self.virtualized: for node in self.curfields.values(): node.escape_if_startbox(memo) + else: + for key, node in self.curfields.items(): + if key not in self.vdesc.virtuals: + node.escape_if_startbox(memo) + # we also need to escape fields that are only read, never written, + # if they're not marked specifically as ones that does not escape + for key, node in self.origfields.items(): + if key not in self.vdesc.virtuals and key not in self.curfields: + node.escape_if_startbox(memo) def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) @@ -293,9 +303,7 @@ self.dependency_graph.append((instnode, fieldnode)) instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode - if (self.first_escaping_op and - instnode.cls and - 1): ##not isinstance(instnode.cls.source, ListDescr)): + if (self.first_escaping_op and instnode.cls): instnode.expanded_fields[field] = None ## def find_nodes_insert(self, instnode, field, fieldnode): @@ -501,6 +509,7 @@ instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) + instnode.vdesc = op.desc continue elif op.is_always_pure(): for arg in op.args: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 3 14:45:58 2009 @@ -9,7 +9,8 @@ from pypy.jit.metainterp.optimize import (PerfectSpecializer, VirtualizableSpecNode, VirtualInstanceSpecNode, - NotSpecNode) + NotSpecNode, + DelayedSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, equaloplists, Loop, @@ -26,7 +27,8 @@ ('x', lltype.Signed), ('l', lltype.Ptr(lltype.GcArray(lltype.Signed))), ('node', lltype.Ptr(NODE)), - hints = {'virtualizable2': True}, + hints = {'virtualizable2': True, + 'virtuals':()}, adtmeths = {'access': VirtualizableAccessor()}) XY._adtmeths['access'].initialize(XY, ['x', 'node', 'l']) @@ -95,7 +97,7 @@ ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], None), ResOperation('jump', [sum2, fr], None), ] - ops[1].vdesc = xy_desc + ops[1].desc = xy_desc def test_A_find_nodes(): spec = PerfectSpecializer(Loop(A.ops)) @@ -146,7 +148,7 @@ ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), ResOperation('jump', [fr], None), ] - ops[1].vdesc = xy_desc + ops[1].desc = xy_desc def test_B_intersect_input_and_output(): spec = PerfectSpecializer(Loop(B.ops)) @@ -154,7 +156,7 @@ spec.intersect_input_and_output() assert spec.nodes[B.fr].escaped assert spec.nodes[B.fr].virtualized - assert not spec.nodes[B.n1].escaped + assert spec.nodes[B.n1].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == B.ofs_node @@ -183,7 +185,7 @@ # ResOperation('jump', [fr], None), ] - ops[1].vdesc = xy_desc + ops[1].desc = xy_desc def test_C_intersect_input_and_output(): spec = PerfectSpecializer(Loop(C.ops)) @@ -191,12 +193,12 @@ spec.intersect_input_and_output() assert spec.nodes[C.fr].escaped assert spec.nodes[C.fr].virtualized - assert not spec.nodes[C.n1].escaped - assert not spec.nodes[C.n2].escaped + assert spec.nodes[C.n1].escaped + assert spec.nodes[C.n2].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == C.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], VirtualInstanceSpecNode) + assert isinstance(spec.specnodes[0].fields[0][1], DelayedSpecNode) # ____________________________________________________________ @@ -222,7 +224,7 @@ ResOperation('setitem', [None, l, ConstInt(0), v2], None), ResOperation('jump', [fr], None), ] - ops[1].vdesc = xy_desc + ops[1].desc = xy_desc def test_D_intersect_input_and_output(): py.test.skip("XXX") Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Tue Mar 3 14:45:58 2009 @@ -125,7 +125,7 @@ class Frame(object): _virtualizable2_ = True - _virtualizable_desc_ = {'virtuals' : 'l'} + _always_virtual_ = ['l'] def __init__(self, l, s): self.l = l @@ -195,7 +195,7 @@ class Frame(object): _virtualizable2_ = True - _virtualizable_desc_ = {'virtuals' : 'stuff'} + _always_virtual_ = ['stuff'] def __init__(self, x): self.stuff = Stuff(x) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Tue Mar 3 14:45:58 2009 @@ -10,6 +10,8 @@ def __init__(self, cpu, TOPSTRUCT): "NOT_RPYTHON" + self.virtuals = [cpu.fielddescrof(TOPSTRUCT, 'inst_' + name) for + name in TOPSTRUCT._hints['virtuals']] initialize_virtualizable(cpu, TOPSTRUCT.access) self.vable_base = cpu.fielddescrof(TOPSTRUCT, 'vable_base') self.vable_rti = cpu.fielddescrof(TOPSTRUCT, 'vable_rti') From fijal at codespeak.net Tue Mar 3 14:46:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 14:46:23 +0100 (CET) Subject: [pypy-svn] r62474 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090303134623.73DCB169DB7@codespeak.net> Author: fijal Date: Tue Mar 3 14:46:17 2009 New Revision: 62474 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Log: use the hint (this makes test pass) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Tue Mar 3 14:46:17 2009 @@ -12,6 +12,8 @@ class Stack(object): _virtualizable2_ = True + + _always_virtual_ = ['stack'] def __init__(self, size): self.stack = [0] * size From fijal at codespeak.net Tue Mar 3 14:49:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 14:49:52 +0100 (CET) Subject: [pypy-svn] r62475 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090303134952.C3B9B168565@codespeak.net> Author: fijal Date: Tue Mar 3 14:49:51 2009 New Revision: 62475 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Grr, fix the translation Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Mar 3 14:49:51 2009 @@ -143,12 +143,13 @@ node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - if key not in self.vdesc.virtuals: + if self.vdesc and key not in self.vdesc.virtuals: node.escape_if_startbox(memo) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): - if key not in self.vdesc.virtuals and key not in self.curfields: + if (self.vdesc and key not in self.vdesc.virtuals and + key not in self.curfields): node.escape_if_startbox(memo) def add_to_dependency_graph(self, other, dep_graph): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Tue Mar 3 14:49:51 2009 @@ -14,6 +14,9 @@ storage_info = None liveboxes = None + # for 'guard_nonvirtualizable' + desc = None + def __init__(self, opnum, args, result): assert isinstance(opnum, int) self.opnum = opnum From fijal at codespeak.net Tue Mar 3 16:35:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 16:35:29 +0100 (CET) Subject: [pypy-svn] r62477 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090303153529.95FA9169E15@codespeak.net> Author: fijal Date: Tue Mar 3 16:35:27 2009 New Revision: 62477 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: fix Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 3 16:35:27 2009 @@ -780,6 +780,8 @@ def prepare_list_getset(self, op, arraydescr, args): func = op.args[0].value._obj._callable # xxx break of abstraction non_negative = '_nonneg' in func.__name__ + if isinstance(op.args[1], Variable): + return None tag = op.args[1].value assert tag in (rlist.dum_nocheck, rlist.dum_checkidx) can_raise = tag != rlist.dum_nocheck From fijal at codespeak.net Tue Mar 3 16:35:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 16:35:49 +0100 (CET) Subject: [pypy-svn] r62478 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090303153549.C3FC2169E16@codespeak.net> Author: fijal Date: Tue Mar 3 16:35:48 2009 New Revision: 62478 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: add ability to debug a compilation problem Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Tue Mar 3 16:35:48 2009 @@ -27,6 +27,7 @@ def run_child(glob, loc): + import sys, pdb interp = loc['interp'] graph = loc['graph'] interp.malloc_check = False @@ -38,4 +39,9 @@ print 'warmspot.jittify_and_run() started...' policy = PyPyJitPolicy(interp.typer.annotator.translator) option.view = True - warmspot.jittify_and_run(interp, graph, [], policy=policy) + try: + warmspot.jittify_and_run(interp, graph, [], policy=policy, + listops=True) + except Exception, e: + print '%s: %s' % (e.__class__, e) + pdb.post_mortem(sys.exc_info()[2]) From fijal at codespeak.net Tue Mar 3 16:44:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 16:44:14 +0100 (CET) Subject: [pypy-svn] r62480 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090303154414.36B2F169E16@codespeak.net> Author: fijal Date: Tue Mar 3 16:44:13 2009 New Revision: 62480 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Log: allow for searching also in parent structures. I *hope* this is the correct thing to do Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Tue Mar 3 16:44:13 2009 @@ -5,12 +5,22 @@ from pypy.annotation.model import lltype_to_annotation from pypy.rlib.objectmodel import we_are_translated +def get_field(cpu, STRUCT, fieldname): + s = STRUCT + while True: + if fieldname in s._flds: + return cpu.fielddescrof(s, fieldname) + if 'super' in s._flds: + s = s.super + else: + raise AttributeError("%r has no attribute %s" % (STRUCT, fieldname)) + class VirtualizableDesc(history.AbstractValue): hash = 0 def __init__(self, cpu, TOPSTRUCT): "NOT_RPYTHON" - self.virtuals = [cpu.fielddescrof(TOPSTRUCT, 'inst_' + name) for + self.virtuals = [get_field(cpu, TOPSTRUCT, 'inst_' + name) for name in TOPSTRUCT._hints['virtuals']] initialize_virtualizable(cpu, TOPSTRUCT.access) self.vable_base = cpu.fielddescrof(TOPSTRUCT, 'vable_base') From tverwaes at codespeak.net Tue Mar 3 16:55:35 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 16:55:35 +0100 (CET) Subject: [pypy-svn] r62481 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090303155535.DEE7616857C@codespeak.net> Author: tverwaes Date: Tue Mar 3 16:55:35 2009 New Revision: 62481 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: fixed one cycle overhead. Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 3 16:55:35 2009 @@ -209,6 +209,8 @@ def execute(self, op_code): + if self.instruction_counter > 61120: + print "PYTHON EXECUTING: ", op_code self.instruction_counter += 1 self.last_op_code = op_code OP_CODES[op_code](self) @@ -304,9 +306,10 @@ self.load(CPUFetchCaller(self), setCaller) def add_a(self, getCaller, setCaller=None): + # TODO: Test overflow -> carry flag data = getCaller.get() # ALU, 1 cycle - added = (self.a.get() + data) & 0xFF + added = self.a.get() + data self.add_sub_flag_finish(added, data) def add_hl(self, register): @@ -336,7 +339,7 @@ self.flag.reset() # set the h flag if the 0x10 bit was affected self.flag.is_half_carry = (((s ^ self.a.get() ^ data) & 0x10) != 0) - self.flag.is_carry = (s >= 0x100 or s < 0) + self.flag.is_carry = (s > 0xFF or s < 0) self.flag.zero_check(s) self.a.set(s & 0xFF) # 1 cycle @@ -373,7 +376,8 @@ self.a.set(self.a.get() & getCaller.get()) # 1 cycle self.flag.reset() self.flag.zero_check(self.a.get()) - self.flag.is_half_carry = True + # I don't see any reason for this? + # self.flag.is_half_carry = True def xor_a(self, getCaller, setCaller=None): # 1 cycle @@ -415,7 +419,7 @@ data = getCaller.get() s = ((data << 1) & 0xFF) + ((data & 0x80) >> 7) self.flags_and_setter_finish(s, data, setCaller, 0x80) - #self.cycles -= 1 + # self.cycles -= 1 def rotate_left_circular_a(self): # RLCA rotate_left_circular_a 1 cycle @@ -484,15 +488,14 @@ setCaller.set(s) # 1 cycle def swap(self, getCaller, setCaller): - data = getCaller.get() # 1 cycle + data = getCaller.get() s = ((data << 4) + (data >> 4)) & 0xFF self.flag.zero_check(s, reset=True) setCaller.set(s) - def test_bit(self, getCaller, setCaller, n): - # 2 cycles + # 1 cycle self.flag.partial_reset(keep_is_carry=True) self.flag.is_half_carry = True self.flag.is_zero = ((getCaller.get() & (1 << n)) == 0) @@ -699,11 +702,11 @@ else: self.cycles -= 2 - def return_form_interrupt(self): + def return_from_interrupt(self): # RETI 4 cycles self.ret() # 4 cycles - self.enable_interrupts() # 1 cycle + others - #self.cycles += 1 + self.cycles += 1 + self.enable_interrupts() def restart(self, nn): # RST nn 4 cycles @@ -717,7 +720,7 @@ def enable_interrupts(self): # 1 cycle self.ime = True - self.execute(self.fetch()) # 1 + self.execute(self.fetch()) self.handle_pending_interrupts() def halt(self): @@ -900,7 +903,7 @@ (0xFA, CPU.store_fetched_memory_in_a), (0xC3, CPU.jump), (0xC9, CPU.ret), - (0xD9, CPU.return_form_interrupt), + (0xD9, CPU.return_from_interrupt), (0xDD, CPU.debug), (0xE9, CPU.store_hl_in_pc), (0xF9, CPU.store_hl_in_sp), Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Tue Mar 3 16:55:35 2009 @@ -107,7 +107,8 @@ def get(self, use_cycles=True): if not use_cycles: self.cpu.cycles += 1 - return self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 + result = self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 + return result # ------------------------------------------------------------------------------ From fijal at codespeak.net Tue Mar 3 17:35:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 17:35:23 +0100 (CET) Subject: [pypy-svn] r62483 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090303163523.B3666169DB3@codespeak.net> Author: fijal Date: Tue Mar 3 17:35:21 2009 New Revision: 62483 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Log: pass around original struct type for offsets. Also a test for virtualizable inheritance Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 3 17:35:21 2009 @@ -826,7 +826,7 @@ except KeyError: from pypy.jit.metainterp import virtualizable virtualizabledesc = virtualizable.VirtualizableDesc( - self.cpu, TOPSTRUCT) + self.cpu, TOPSTRUCT, STRUCTTYPE) virtualizabledesc.hash = len(metainterp._virtualizabledescs) metainterp._virtualizabledescs[TOPSTRUCT] = virtualizabledesc metainterp._can_have_virtualizables = virtualizabledesc Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 3 17:35:21 2009 @@ -60,7 +60,7 @@ # ____________________________________________________________ -xy_desc = VirtualizableDesc(cpu, XY) +xy_desc = VirtualizableDesc(cpu, XY, XY) # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Tue Mar 3 17:35:21 2009 @@ -270,6 +270,38 @@ res = self.meta_interp(f, [20]) assert res == f(20) + def test_virtualizable_hierarchy(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n']) + + class BaseFrame(object): + _virtualizable2_ = True + + _always_virtual_ = ['x'] + + def __init__(self, x): + self.x = x + + class Frame(BaseFrame): + pass + + class Stuff(object): + def __init__(self, x): + self.x = x + + def f(n): + frame = Frame(Stuff(3)) + + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n) + jitdriver.jit_merge_point(n=n, frame=frame) + frame.x = Stuff(frame.x.x + 1) + n -= 1 + return frame.x.x + + res = self.meta_interp(f, [20]) + assert res == f(20) + self.check_loops(getfield_gc=0, setfield_gc=0) + def test_external_read(self): py.test.skip("Fails") class Frame(object): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Tue Mar 3 17:35:21 2009 @@ -5,22 +5,12 @@ from pypy.annotation.model import lltype_to_annotation from pypy.rlib.objectmodel import we_are_translated -def get_field(cpu, STRUCT, fieldname): - s = STRUCT - while True: - if fieldname in s._flds: - return cpu.fielddescrof(s, fieldname) - if 'super' in s._flds: - s = s.super - else: - raise AttributeError("%r has no attribute %s" % (STRUCT, fieldname)) - class VirtualizableDesc(history.AbstractValue): hash = 0 - def __init__(self, cpu, TOPSTRUCT): + def __init__(self, cpu, TOPSTRUCT, STRUCTTYPE): "NOT_RPYTHON" - self.virtuals = [get_field(cpu, TOPSTRUCT, 'inst_' + name) for + self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for name in TOPSTRUCT._hints['virtuals']] initialize_virtualizable(cpu, TOPSTRUCT.access) self.vable_base = cpu.fielddescrof(TOPSTRUCT, 'vable_base') From fijal at codespeak.net Tue Mar 3 17:35:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 17:35:53 +0100 (CET) Subject: [pypy-svn] r62484 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090303163553.F0124169DB5@codespeak.net> Author: fijal Date: Tue Mar 3 17:35:51 2009 New Revision: 62484 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Log: I *think* this is what should be instead of 'xxx'. unsure, since it comes with no tests for accessors Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Tue Mar 3 17:35:51 2009 @@ -79,14 +79,15 @@ hints = {'virtualizable2': True, 'virtuals' : self.virtuals}, adtmeths = {'access': self.accessor}) + my_redirected_fields = [] + for _, (mangled_name, _) in self.fields.items(): + my_redirected_fields.append(mangled_name) + self.my_redirected_fields = dict.fromkeys(my_redirected_fields) if self.top_of_virtualizable_hierarchy: - my_redirected_fields = [] - for _, (mangled_name, _) in self.fields.items(): - my_redirected_fields.append(mangled_name) - self.my_redirected_fields = dict.fromkeys(my_redirected_fields) self.accessor.initialize(self.object_type, my_redirected_fields) else: - xxx + self.accessor.initialize(self.object_type, my_redirected_fields, + self.rbase.lowleveltype.TO) def set_vable(self, llops, vinst, force_cast=False): if self.top_of_virtualizable_hierarchy: From tverwaes at codespeak.net Tue Mar 3 18:39:07 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 18:39:07 +0100 (CET) Subject: [pypy-svn] r62486 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090303173907.8A5E516850E@codespeak.net> Author: tverwaes Date: Tue Mar 3 18:39:07 2009 New Revision: 62486 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/interrupt.py pypy/trunk/pypy/lang/gameboy/video.py Log: checked with java code. The overlapping regions were actually correct. the 2 tile_arrays share half of their data space. vram_a = 2kb + 2kb shared = 4kb vram_b = 2kb shared + 2kb = 4kb vram_a + vram_b = 6kb vmap_a = 1kb vmap_b = 1kb vram_a + vram_b + vmap_a + vmap_b = 8kb Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Tue Mar 3 18:39:07 2009 @@ -125,18 +125,17 @@ VRAM_SIZE = 0x2000 # VRAM Tile Data/Maps Addresses -TILE_DATA_SIZE = 0x00C0 # 1/4th of 0x2000; 2 data maps with 2 bytes per tile - # line and 8 lines +TILE_DATA_SIZE = 0x0100 # 4kb / (16bytes per tile) TILE_DATA_ADDR = 0x8000 -VRAM_DATA_A = 0x0000 # 3KB Tile Data (8000..8BFF) -VRAM_DATA_B = 0x0C00 # 3KB Tile Data (8C00..97FF) +VRAM_DATA_A = 0x0000 # 4KB Tile Data (8000..8FFF) # Notice there is a 2kb +VRAM_DATA_B = 0x0800 # 4KB Tile Data (8800..97FF) # overlap! TILE_MAP_ADDR = 0x9800 TILE_MAP_SIZE = 32 # 32 Groups TILE_GROUP_SIZE = 32 # of 32 addresses -VRAM_MAP_A = 0x1800 # 1KB BG Tile Map 0 (9800..9BFF) +VRAM_MAP_A = 0x1800 # 1KB BG Tile Map 0 (9000..9BFF) VRAM_MAP_B = 0x1C00 # 1KB BG Tile Map 1 (9C00..9FFF) Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 3 18:39:07 2009 @@ -209,8 +209,6 @@ def execute(self, op_code): - if self.instruction_counter > 61120: - print "PYTHON EXECUTING: ", op_code self.instruction_counter += 1 self.last_op_code = op_code OP_CODES[op_code](self) Modified: pypy/trunk/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/interrupt.py (original) +++ pypy/trunk/pypy/lang/gameboy/interrupt.py Tue Mar 3 18:39:07 2009 @@ -82,7 +82,6 @@ for flag in self.interrupt_flags: flag.reset() - def write(self, address, data): if address == constants.IE: self.set_enable_mask(data) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Tue Mar 3 18:39:07 2009 @@ -55,7 +55,7 @@ # ----------------------------------------------------------------------- def create_tile_maps(self): - # create the maxumal possible sprites + # create the maximal possible sprites self.tile_map_0 = self.create_tile_map() self.tile_map_1 = self.create_tile_map() self.tile_maps = [self.tile_map_0, self.tile_map_1] @@ -67,12 +67,13 @@ return [0x00 for i in range(TILE_GROUP_SIZE)] def create_tiles(self): - self.tile_data_0 = self.create_tile_data() - self.tile_data_1 = self.create_tile_data() + tile_data_overlap = self.create_tile_data() + self.tile_data_0 = self.create_tile_data() + tile_data_overlap + self.tile_data_1 = tile_data_overlap + self.create_tile_data() self.tile_data = [self.tile_data_0, self.tile_data_1] def create_tile_data(self): - return [Tile(i, self) for i in range(TILE_DATA_SIZE)] + return [Tile(i, self) for i in range(TILE_DATA_SIZE / 2)] def update_tile(self, address, data): self.get_tile(address).set_data_at(address, data); @@ -517,6 +518,9 @@ tile_index = tile_group[group_index % TILE_GROUP_SIZE] if not self.control.background_and_window_lower_tile_data_selected: tile_index ^= 0x80 + if tile_index >= len(tile_data): + import pdb + pdb.set_trace() tile = tile_data[tile_index] tile.draw(x, y) group_index += 1 From fijal at codespeak.net Tue Mar 3 18:45:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 18:45:18 +0100 (CET) Subject: [pypy-svn] r62488 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090303174518.E5CEA168473@codespeak.net> Author: fijal Date: Tue Mar 3 18:45:18 2009 New Revision: 62488 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: a test and a partial fix (it exploded before). We still need some optimizations for this test to pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 3 18:45:18 2009 @@ -779,12 +779,16 @@ def prepare_list_getset(self, op, arraydescr, args): func = op.args[0].value._obj._callable # xxx break of abstraction + # XXX what if the type is called _nonneg or _fast??? non_negative = '_nonneg' in func.__name__ - if isinstance(op.args[1], Variable): - return None - tag = op.args[1].value - assert tag in (rlist.dum_nocheck, rlist.dum_checkidx) - can_raise = tag != rlist.dum_nocheck + fast = '_fast' in func.__name__ + if fast: + can_raise = False + non_negative = True + else: + tag = op.args[1].value + assert tag in (rlist.dum_nocheck, rlist.dum_checkidx) + can_raise = tag != rlist.dum_nocheck # if can_raise: return None Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Tue Mar 3 18:45:18 2009 @@ -60,6 +60,24 @@ # one setitem should be gone by now self.check_loops(call_ptr=1, setarrayitem_gc=1, getarrayitem_gc=1) + def test_ll_fixed_setitem_fast(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'l']) + + def f(n): + l = [1, 2, 3] + + while n > 0: + jitdriver.can_enter_jit(n=n, l=l) + jitdriver.jit_merge_point(n=n, l=l) + l = l[:] + n -= 1 + return l[0] + + res = self.meta_interp(f, [10], listops=True) + assert res == 1 + py.test.skip("Constant propagation of length missing") + self.check_loops(setarrayitem_gc=0, call_ptr=0, call__4=0) + def test_vlist_with_default_read(self): py.test.skip("for now, more support in codewriter needed") jitdriver = JitDriver(greens = [], reds = ['n']) From tverwaes at codespeak.net Tue Mar 3 18:51:10 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 18:51:10 +0100 (CET) Subject: [pypy-svn] r62490 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090303175110.DC3A71684B4@codespeak.net> Author: tverwaes Date: Tue Mar 3 18:51:10 2009 New Revision: 62490 Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py pypy/trunk/pypy/lang/gameboy/video.py Log: fixing writing start in VRAM_B to take overlap into account. McDonaldland now shows up nicely! Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Tue Mar 3 18:51:10 2009 @@ -13,7 +13,7 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" # filename = ROM_PATH + "/rom9/rom9.gb" -filename = "/home/tverwaes/roms/KirbysDreamLand.gb" +filename = "/home/tverwaes/roms/McDonaldland.gb" SOCKET_PORT = 55682 skip_count = 22545 Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Tue Mar 3 18:51:10 2009 @@ -83,7 +83,7 @@ if tile_index < TILE_DATA_SIZE: return self.tile_data_0[tile_index] else: - return self.tile_data_1[tile_index - TILE_DATA_SIZE] + return self.tile_data_1[tile_index - TILE_DATA_SIZE / 2] def select_tile_group_for(self, address): tile_map_index = address - TILE_MAP_ADDR #) >> 1 From afa at codespeak.net Tue Mar 3 19:21:31 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 3 Mar 2009 19:21:31 +0100 (CET) Subject: [pypy-svn] r62493 - pypy/trunk/pypy/rpython/ootypesystem Message-ID: <20090303182131.E2E571684E4@codespeak.net> Author: afa Date: Tue Mar 3 19:21:29 2009 New Revision: 62493 Modified: pypy/trunk/pypy/rpython/ootypesystem/ootype.py Log: in oosupport/constant.py, the constants cache store objects of different types in a dictionary: all keys should be comparable. I was unlucky enough to have two objects with the same hash. but this can be explained if one was a _view of the other. Change a bit the __hash__ function to reduce collisions. Modified: pypy/trunk/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/ootype.py Tue Mar 3 19:21:29 2009 @@ -913,13 +913,13 @@ return not (self == other) def __eq__(self, other): - assert isinstance(other, _view) + assert isinstance(other, (_view, _callable)) a = self._inst b = other._inst return a.__class__ == b.__class__ and a == b def __hash__(self): - return hash(self._inst) + return hash(self._inst) + 1 def __nonzero__(self): return bool(self._inst) From afa at codespeak.net Tue Mar 3 19:27:31 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 3 Mar 2009 19:27:31 +0100 (CET) Subject: [pypy-svn] r62494 - in pypy/trunk/pypy/module: _codecs _file Message-ID: <20090303182731.5492E1684F3@codespeak.net> Author: afa Date: Tue Mar 3 19:27:30 2009 New Revision: 62494 Modified: pypy/trunk/pypy/module/_codecs/__init__.py pypy/trunk/pypy/module/_file/__init__.py Log: Remove from the cli translation function and methods that are implemented with rffi Modified: pypy/trunk/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/__init__.py (original) +++ pypy/trunk/pypy/module/_codecs/__init__.py Tue Mar 3 19:27:30 2009 @@ -46,9 +46,16 @@ 'readbuffer_encode': 'interp_codecs.buffer_encode', } - if hasattr(runicode, 'str_decode_mbcs'): - interpleveldefs['mbcs_encode'] = 'interp_codecs.mbcs_encode' - interpleveldefs['mbcs_decode'] = 'interp_codecs.mbcs_decode' + def __init__(self, space, *args): + "NOT_RPYTHON" + + # mbcs codec is Windows specific, and based on rffi. + if (hasattr(runicode, 'str_decode_mbcs') and + space.config.translation.type_system != 'ootype'): + self.interpleveldefs['mbcs_encode'] = 'interp_codecs.mbcs_encode' + self.interpleveldefs['mbcs_decode'] = 'interp_codecs.mbcs_decode' + + MixedModule.__init__(self, space, *args) def setup_after_space_initialization(self): "NOT_RPYTHON" Modified: pypy/trunk/pypy/module/_file/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_file/__init__.py (original) +++ pypy/trunk/pypy/module/_file/__init__.py Tue Mar 3 19:27:30 2009 @@ -1,6 +1,7 @@ # Package initialisation from pypy.interpreter.mixedmodule import MixedModule +import sys class Module(MixedModule): appleveldefs = { @@ -10,6 +11,18 @@ "file": "interp_file.W_File", } + def __init__(self, space, *args): + "NOT_RPYTHON" + + # on windows with oo backends, remove file.truncate, + # because the implementation is based on rffi + if (sys.platform == 'win32' and + space.config.translation.type_system == 'ootype'): + from pypy.module._file.interp_file import W_File + del W_File.typedef.rawdict['truncate'] + + MixedModule.__init__(self, space, *args) + def shutdown(self, space): # at shutdown, flush all open streams from pypy.module._file.interp_file import getopenstreams From afa at codespeak.net Tue Mar 3 19:40:36 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 3 Mar 2009 19:40:36 +0100 (CET) Subject: [pypy-svn] r62495 - in pypy/trunk/pypy: rpython/module translator/cli/src translator/jvm/src/pypy Message-ID: <20090303184036.015931684F2@codespeak.net> Author: afa Date: Tue Mar 3 19:40:36 2009 New Revision: 62495 Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py pypy/trunk/pypy/translator/cli/src/pypylib.cs pypy/trunk/pypy/translator/jvm/src/pypy/StatResult.java pypy/trunk/pypy/translator/jvm/src/pypy/ll_os.java Log: It seems that oo backends can't insert a int into a float struct member: The specific implementation of structures (in C# and Java) must match the STAT_FIELDS description. (I considered changing rpython.module.r_os_stat.specialize_make_stat_result, but I could not get it to work) So: - st_mtime is a lltype.Float all the time. - we turn it into a lltype.Signed to build the "struct stat" for the C backend - structures in C# and Java now hold float times. Tested with the cli backend, I hope I did not break Java. Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Tue Mar 3 19:40:36 2009 @@ -26,11 +26,6 @@ else: TIMESPEC = None -if sys.platform == 'win32' or TIMESPEC is not None: - ModTime = lltype.Float -else: - ModTime = lltype.Signed - # all possible fields - some of them are not available on all platforms ALL_STAT_FIELDS = [ ("st_mode", lltype.Signed), @@ -40,15 +35,15 @@ ("st_uid", lltype.Signed), ("st_gid", lltype.Signed), ("st_size", lltype.SignedLongLong), - ("st_atime", ModTime), - ("st_mtime", ModTime), - ("st_ctime", ModTime), + ("st_atime", lltype.Float), + ("st_mtime", lltype.Float), + ("st_ctime", lltype.Float), ("st_blksize", lltype.Signed), ("st_blocks", lltype.Signed), ("st_rdev", lltype.Signed), ("st_flags", lltype.Signed), #("st_gen", lltype.Signed), -- new in CPy 2.5, not implemented - #("st_birthtime", ModTime), -- new in CPy 2.5, not implemented + #("st_birthtime", lltype.Float), -- new in CPy 2.5, not implemented ] N_INDEXABLE_FIELDS = 10 @@ -169,7 +164,14 @@ _expand(LL_STAT_FIELDS, 'st_ctime', 'st_ctim') del _expand - + else: + # Replace float fields with integers + for name in ('st_atime', 'st_mtime', 'st_ctime', 'st_birthtime'): + for i, (_name, _TYPE) in enumerate(LL_STAT_FIELDS): + if _name == name: + LL_STAT_FIELDS[i] = (_name, lltype.Signed) + break + class CConfig: _compilation_info_ = compilation_info STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS) Modified: pypy/trunk/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/trunk/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/trunk/pypy/translator/cli/src/pypylib.cs Tue Mar 3 19:40:36 2009 @@ -712,8 +712,9 @@ } public class Record_Stat_Result { - public int item0, item3, item4, item5, item7, item8, item9; + public int item0, item3, item4, item5; public long item1, item2, item6; + public double item7, item8, item9; public override string ToString() { return string.Format("({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9},)", Modified: pypy/trunk/pypy/translator/jvm/src/pypy/StatResult.java ============================================================================== --- pypy/trunk/pypy/translator/jvm/src/pypy/StatResult.java (original) +++ pypy/trunk/pypy/translator/jvm/src/pypy/StatResult.java Tue Mar 3 19:40:36 2009 @@ -9,10 +9,11 @@ *

The actual stat() function is defined in PyPy.java. */ class StatResult { - public int item0, item3, item4, item5, item7, item8, item9; + public int item0, item3, item4, item5; public long item1, item2, item6; + public double item7, item8, item9; public void setMode(int value) { item0 = value; } public void setSize(long value) { item6 = value; } - public void setMtime(int value) { item8 = value; } + public void setMtime(double value) { item8 = value; } } Modified: pypy/trunk/pypy/translator/jvm/src/pypy/ll_os.java ============================================================================== --- pypy/trunk/pypy/translator/jvm/src/pypy/ll_os.java (original) +++ pypy/trunk/pypy/translator/jvm/src/pypy/ll_os.java Tue Mar 3 19:40:36 2009 @@ -496,7 +496,7 @@ else { res.setMode(S_IFREG); res.setSize(f.length()); - res.setMtime((int)f.lastModified()); + res.setMtime((double)f.lastModified()); } return res; } From tverwaes at codespeak.net Tue Mar 3 21:31:35 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 21:31:35 +0100 (CET) Subject: [pypy-svn] r62496 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090303203135.6D709168453@codespeak.net> Author: tverwaes Date: Tue Mar 3 21:31:33 2009 New Revision: 62496 Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/joypad.py pypy/trunk/pypy/lang/gameboy/video.py Log: fixed a bug in the joypad. the joypad uses 1 for off and 0 for on rather than the other way around. Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Tue Mar 3 21:31:33 2009 @@ -13,7 +13,7 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" # filename = ROM_PATH + "/rom9/rom9.gb" -filename = "/home/tverwaes/roms/McDonaldland.gb" +filename = "/home/tverwaes/roms/SuperMarioLand.gb" SOCKET_PORT = 55682 skip_count = 22545 Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Tue Mar 3 21:31:33 2009 @@ -123,9 +123,10 @@ def write(self, address, data): receiver = self.get_receiver(address) - if receiver is None: - raise Exception(("invalid write address given: ",address," ",data)) - receiver.write(address, data) + if receiver is not None: + receiver.write(address, data) + # else: + # raise Exception(("invalid write address given: ",address," ",data)) if address == constants.STAT or address == 0xFFFF: self.cpu.handle_pending_interrupts() @@ -141,6 +142,8 @@ pass def get_receiver(self, address): + if self.cpu.instruction_counter > 81500: + print "Getting receiver at: ", address """ General Memory Map 0000-3FFF 16KB ROM Bank 00 (in cartridge, fixed at bank 00) Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Tue Mar 3 21:31:33 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = False +use_rsdl = True if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/trunk/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/joypad.py (original) +++ pypy/trunk/pypy/lang/gameboy/joypad.py Tue Mar 3 21:31:33 2009 @@ -48,7 +48,7 @@ def write(self, address, data): if address == constants.JOYP: - self.read_control = (self.read_control & 0xC) + ((data & 0x30)>>4) + self.read_control = (self.read_control & 0xC) + ((data>>4) & 0x3) self.update() def read(self, address): @@ -58,13 +58,18 @@ def update(self): old_buttons = self.button_code - if self.read_control & 0x3 == 1: + control = (self.read_control & 0x3) + if control == 1: self.button_code = self.driver.get_button_code() - elif self.read_control & 0x3 == 2: + elif control == 2: self.button_code = self.driver.get_direction_code() - elif self.read_control & 0x3 == 3: - self.button_code = 0xF + import pdb + pdb.set_trace() + elif control == 3: + self.button_code = 0xF if old_buttons != self.button_code: + print "CONTROL: ", control + print "CHANGED BUTTONS: ", old_buttons, " new: ", self.button_code self.joypad_interrupt_flag.set_pending() @@ -116,13 +121,13 @@ code = 0 for button in self.buttons: code |= button.get_code() - return code + return code ^ 0xF # 0 means on, 1 means off def get_direction_code(self): code = 0 for button in self.directions: code |= button.get_code() - return code + return code ^ 0xF # 0 means on, 1 means off def is_raised(self): raised = self.raised Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Tue Mar 3 21:31:33 2009 @@ -518,9 +518,6 @@ tile_index = tile_group[group_index % TILE_GROUP_SIZE] if not self.control.background_and_window_lower_tile_data_selected: tile_index ^= 0x80 - if tile_index >= len(tile_data): - import pdb - pdb.set_trace() tile = tile_data[tile_index] tile.draw(x, y) group_index += 1 From tverwaes at codespeak.net Tue Mar 3 21:32:28 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 21:32:28 +0100 (CET) Subject: [pypy-svn] r62497 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090303203228.3F56216846A@codespeak.net> Author: tverwaes Date: Tue Mar 3 21:32:27 2009 New Revision: 62497 Modified: pypy/trunk/pypy/lang/gameboy/joypad.py Log: removing trace call Modified: pypy/trunk/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/joypad.py (original) +++ pypy/trunk/pypy/lang/gameboy/joypad.py Tue Mar 3 21:32:27 2009 @@ -63,8 +63,6 @@ self.button_code = self.driver.get_button_code() elif control == 2: self.button_code = self.driver.get_direction_code() - import pdb - pdb.set_trace() elif control == 3: self.button_code = 0xF if old_buttons != self.button_code: From tverwaes at codespeak.net Tue Mar 3 21:35:18 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 21:35:18 +0100 (CET) Subject: [pypy-svn] r62498 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090303203518.BEEBF168466@codespeak.net> Author: tverwaes Date: Tue Mar 3 21:35:18 2009 New Revision: 62498 Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/joypad.py Log: removing prints Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Tue Mar 3 21:35:18 2009 @@ -142,8 +142,6 @@ pass def get_receiver(self, address): - if self.cpu.instruction_counter > 81500: - print "Getting receiver at: ", address """ General Memory Map 0000-3FFF 16KB ROM Bank 00 (in cartridge, fixed at bank 00) Modified: pypy/trunk/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/joypad.py (original) +++ pypy/trunk/pypy/lang/gameboy/joypad.py Tue Mar 3 21:35:18 2009 @@ -66,8 +66,6 @@ elif control == 3: self.button_code = 0xF if old_buttons != self.button_code: - print "CONTROL: ", control - print "CHANGED BUTTONS: ", old_buttons, " new: ", self.button_code self.joypad_interrupt_flag.set_pending() From fijal at codespeak.net Tue Mar 3 22:03:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 22:03:21 +0100 (CET) Subject: [pypy-svn] r62499 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090303210321.6B87C168543@codespeak.net> Author: fijal Date: Tue Mar 3 22:03:19 2009 New Revision: 62499 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: Make PyFrame a virtualizable2. Also promote a position on valuestack and make valuestack_w always virtual Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Tue Mar 3 22:03:19 2009 @@ -6,7 +6,7 @@ import sys from pypy.tool.pairtype import extendabletype from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.rlib.jit import JitDriver +from pypy.rlib.jit import JitDriver, hint import pypy.interpreter.pyopcode # for side-effects from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace, Arguments @@ -17,11 +17,13 @@ from pypy.interpreter.pyopcode import ExitFrame -#Frame._virtualizable2_ = True +PyFrame._virtualizable2_ = True +PyFrame._always_virtual_ = ['valuestack_w'] class PyPyJitDriver(JitDriver): reds = ['frame', 'ec'] greens = ['next_instr', 'pycode'] + virtualizables = ['frame'] ## def compute_invariants(self, reds, next_instr, pycode): ## # compute the information that really only depends on next_instr @@ -42,6 +44,7 @@ pypyjitdriver.jit_merge_point( frame=self, ec=ec, next_instr=next_instr, pycode=pycode) co_code = pycode.co_code + self.valuestackdepth = hint(self.valuestackdepth, promote=True) next_instr = self.handle_bytecode(co_code, next_instr, ec) except ExitFrame: return self.popvalue() From tverwaes at codespeak.net Tue Mar 3 22:23:10 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 3 Mar 2009 22:23:10 +0100 (CET) Subject: [pypy-svn] r62500 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090303212310.2FF3816851A@codespeak.net> Author: tverwaes Date: Tue Mar 3 22:23:08 2009 New Revision: 62500 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: removing PaintSprites. Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Tue Mar 3 22:23:08 2009 @@ -169,33 +169,6 @@ # ----------------------------------------------------------------------------- -class PaintSprite(Sprite): - - def __init__(self, line_position, sprite, video): - Sprite.__init__(self) - self.line_position = line_position - self.extract_attributes(sprite, video) - self.update_position(sprite) - - def extract_attributes(self, sprite, video): - self.x = sprite.x - self.y = video.line_y - sprite.y + 2 * SPRITE_SIZE - self.tile = sprite.tile - self.object_behind_background = sprite.object_behind_background - self.x_flipped = sprite.x_flipped - self.y_flipped = sprite.y_flipped - self.tile_number = sprite.tile_number - self.hidden = sprite.hidden - self.rest_attributes_and_flags = sprite.rest_attributes_and_flags - - def update_position(sprite): - if sprite.y < 0 or sprite.y >= self.get_height(): return - if sprite.y_flipped: - self.y = self.get_height() - 1 - self.y - -# ----------------------------------------------------------------------------- - - class Tile(object): def __init__(self, number, video): From fijal at codespeak.net Tue Mar 3 22:42:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Mar 2009 22:42:23 +0100 (CET) Subject: [pypy-svn] r62501 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090303214223.DB3AC16851A@codespeak.net> Author: fijal Date: Tue Mar 3 22:42:23 2009 New Revision: 62501 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: make fastlocals_w also an always_virtual Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Tue Mar 3 22:42:23 2009 @@ -16,9 +16,8 @@ from pypy.interpreter.function import Function from pypy.interpreter.pyopcode import ExitFrame - PyFrame._virtualizable2_ = True -PyFrame._always_virtual_ = ['valuestack_w'] +PyFrame._always_virtual_ = ['valuestack_w', 'fastlocals_w'] class PyPyJitDriver(JitDriver): reds = ['frame', 'ec'] From fijal at codespeak.net Wed Mar 4 08:10:55 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 08:10:55 +0100 (CET) Subject: [pypy-svn] r62505 - pypy/branch/pyjitpl5/pypy/module/_pickle_support Message-ID: <20090304071055.889B116850D@codespeak.net> Author: fijal Date: Wed Mar 4 08:10:54 2009 New Revision: 62505 Modified: pypy/branch/pyjitpl5/pypy/module/_pickle_support/maker.py Log: Grrrr. I'm pretty sure we don't want fastlocals_w to be a resizable list Modified: pypy/branch/pyjitpl5/pypy/module/_pickle_support/maker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/_pickle_support/maker.py (original) +++ pypy/branch/pyjitpl5/pypy/module/_pickle_support/maker.py Wed Mar 4 08:10:54 2009 @@ -105,7 +105,8 @@ def slp_from_tuple_with_nulls(space, w_tup): tup_w = space.unpackiterable(w_tup) - nulls = space.unpackiterable(tup_w.pop(0)) + nulls = space.unpackiterable(tup_w[0]) + tup_w = tup_w[1:] for w_p in nulls: p = space.int_w(w_p) tup_w[p] = None From fijal at codespeak.net Wed Mar 4 08:37:02 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 08:37:02 +0100 (CET) Subject: [pypy-svn] r62506 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090304073702.1B01516855D@codespeak.net> Author: fijal Date: Wed Mar 4 08:37:00 2009 New Revision: 62506 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Reuse got length of an array for future uses. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Mar 4 08:37:00 2009 @@ -69,13 +69,10 @@ ad = ConstInt(ld.arraydescr) if instnode.cursize == -1: # fish fish fish - res = cpu.execute_operation(rop.ARRAYLEN_GC, - [instnode.source, ad], - 'int') - size = res.getint() - else: - size = instnode.cursize - self.list_allocations.append((ad, size)) + instnode.cursize= cpu.execute_operation(rop.ARRAYLEN_GC, + [instnode.source, ad], + 'int').getint() + self.list_allocations.append((ad, instnode.cursize)) res = (alloc_offset + 1) << 16 else: alloc_offset = len(self.allocations) From fijal at codespeak.net Wed Mar 4 09:12:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 09:12:15 +0100 (CET) Subject: [pypy-svn] r62507 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090304081215.24EB916856B@codespeak.net> Author: fijal Date: Wed Mar 4 09:12:14 2009 New Revision: 62507 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: More debug support. This allows to show how the particular loop was created giving full (followed) call stack Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py Wed Mar 4 09:12:14 2009 @@ -85,7 +85,6 @@ def __repr__(self): return self.s - def dump_bytecode(jitcode, file=None): # XXX this is not really a disassembler, but just a pretty-printer # for the '_source' attribute that codewriter.py attaches @@ -134,3 +133,21 @@ if src.pc != len(jitcode.code): print >> file, 'WARNING: the pc column is bogus! fix dump.py!' + +def dump_call_history(call_history): + indent = 0 + for ev, code, args in call_history: + if ev == 'enter': + if args is not None: + args_s = [str(a) for a in args] + else: + args_s = [] + print "%s%s(%s)" % (" "*indent, code.name, ','.join(args_s)) + indent += 2 + elif ev.startswith('leave'): + indent -= 2 + elif ev == 'guard_failure': + break + else: + raise NotImplementedError(ev) + Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Mar 4 09:12:14 2009 @@ -613,6 +613,8 @@ check_args(*argboxes) self.pc = 0 self.env = argboxes + if not we_are_translated(): + self.metainterp._debug_history[-1][-1] = argboxes #self.starts_with_greens() #assert len(argboxes) == len(self.graph.getargs()) @@ -742,6 +744,7 @@ self.class_sizes = populate_type_cache(graphs, self.cpu) self._virtualizabledescs = {} + self._debug_history = [] def generate_bytecode(self, policy): self._codewriter = codewriter.CodeWriter(self, policy) @@ -754,12 +757,16 @@ return not we_are_translated() def newframe(self, jitcode): + if not we_are_translated(): + self._debug_history.append(['enter', jitcode, None]) f = MIFrame(self, jitcode) self.framestack.append(f) return f def finishframe(self, resultbox): - self.framestack.pop() + frame = self.framestack.pop() + if not we_are_translated(): + self._debug_history.append(['leave', frame.jitcode, None]) if self.framestack: if resultbox is not None: self.framestack[-1].make_result_box(resultbox) @@ -776,6 +783,8 @@ frame.exception_box = exceptionbox frame.exc_value_box = excvaluebox return True + if not we_are_translated(): + self._debug_history.append(['leave_exc', frame.jitcode, None]) self.framestack.pop() raise self.ExitFrameWithException(exceptionbox, excvaluebox) @@ -862,6 +871,9 @@ live_arg_boxes[num_green_args:]) if not loop: raise self.ContinueRunningNormally(live_arg_boxes) + if not we_are_translated(): + loop._call_history = self._debug_history + self.debug_history = [] return loop def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes): @@ -879,6 +891,9 @@ live_arg_boxes[num_green_args:]) if bridge is None: raise self.ContinueRunningNormally(live_arg_boxes) + if not we_are_translated(): + bridge._call_history = self._debug_history + self.debug_history = [] guard_failure.guard_op.jump_target = bridge.operations[0] return bridge @@ -971,7 +986,9 @@ return False def rebuild_state_after_failure(self, key, newboxes): - self.framestack = [] + if not we_are_translated(): + self._debug_history.append(['guard_failure', None, None]) + self.framestack = [] nbindex = 0 for jitcode, pc, envlength, exception_target in key: f = self.newframe(jitcode) Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py Wed Mar 4 09:12:14 2009 @@ -0,0 +1,43 @@ + +from pypy.jit.metainterp.test.test_basic import LLJitMixin +from pypy.rlib.jit import JitDriver +from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.metainterp.warmspot import get_stats +from pypy.jit.metainterp.dump import dump_call_history + +class TestDebug(LLJitMixin): + def test_callstack(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + + def x(n): + pass + + def z(n): + x(n) + + def g(n): + z(n) + + def f(n): + while n > 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + g(n) + n -= 1 + return n + + res = self.meta_interp(f, [10], policy=StopAtXPolicy(x)) + assert res == 0 + ch = get_stats().loops[0]._call_history + cmp = [(i, getattr(j, 'name', 'gf')) for i, j, _ in ch] + assert cmp == [ + ('enter', 'f'), + ('enter', 'g'), + ('enter', 'z'), + ('leave', 'z'), + ('leave', 'g'), + ('guard_failure', 'gf'), + ('enter', 'f'), + ('leave', 'f'), + ] + dump_call_history(ch) From arigo at codespeak.net Wed Mar 4 09:22:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 4 Mar 2009 09:22:27 +0100 (CET) Subject: [pypy-svn] r62508 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090304082227.C9799168572@codespeak.net> Author: arigo Date: Wed Mar 4 09:22:25 2009 New Revision: 62508 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Adapt the style of the "_" constants Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Wed Mar 4 09:22:25 2009 @@ -109,7 +109,8 @@ UINT_ADD = 40 UINT_SUB = 41 UINT_MUL = 42 - _COMPARISON_FIRST = 43 + # + _COMPARISON_FIRST = 44 INT_LT = 44 INT_LE = 45 INT_EQ = 46 @@ -122,7 +123,7 @@ UINT_NE = 53 UINT_GT = 54 UINT_GE = 55 - _COMPARISON_LAST = 56 + _COMPARISON_LAST = 55 # INT_IS_TRUE = 60 INT_NEG = 61 @@ -162,12 +163,12 @@ CALL_PTR = _CALL + typ.PTR CALL_VOID = _CALL + typ.VOID # - _OVF_FIRST = 109 + _OVF_FIRST = 110 INT_ADD_OVF = 110 INT_SUB_OVF = 111 INT_MUL_OVF = 112 INT_NEG_OVF = 113 - _OVF_LAST = 114 + _OVF_LAST = 113 _CANRAISE_LAST = 119 # ----- end of can_raise operations ----- _LAST = 119 # for the backend to add more internal operations From hpk at codespeak.net Wed Mar 4 09:29:43 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 4 Mar 2009 09:29:43 +0100 (CET) Subject: [pypy-svn] r62509 - pypy/trunk/pypy/tool/test Message-ID: <20090304082943.8361216851F@codespeak.net> Author: hpk Date: Wed Mar 4 09:29:43 2009 New Revision: 62509 Modified: pypy/trunk/pypy/tool/test/test_conftest1.py Log: fix test to work with py/trunk correctly Modified: pypy/trunk/pypy/tool/test/test_conftest1.py ============================================================================== --- pypy/trunk/pypy/tool/test/test_conftest1.py (original) +++ pypy/trunk/pypy/tool/test/test_conftest1.py Wed Mar 4 09:29:43 2009 @@ -2,38 +2,31 @@ import py innertest = py.magic.autopath().dirpath('conftest1_innertest.py') -from py.__.test.testing import suptest +pytest_plugins = "pytest_pytester" -class TestPyPyTests(suptest.InlineSession): - def test_select_interplevel(self): - sorter = self.parse_and_run("-k", "interplevel", innertest) +class TestPyPyTests: + def test_select_interplevel(self, testdir): + sorter = testdir.inline_run("-k", "interplevel", innertest) passed, skipped, failed = sorter.listoutcomes() assert len(passed) == 2 assert not skipped and not failed for repevent in passed: assert repevent.colitem.name in ('test_something', 'test_method') - def test_select_applevel(self): - sorter = self.parse_and_run("-k", "applevel", innertest) + def test_select_applevel(self, testdir): + sorter = testdir.inline_run("-k", "applevel", innertest) passed, skipped, failed = sorter.listoutcomes() assert len(passed) == 2 assert not skipped and not failed for repevent in passed: assert repevent.colitem.name in ('app_test_something', 'test_method_app') - def XXX_test_appdirect(self): - config = py.test.config._reparse([innertest, - '-k', 'applevel', '--appdirect']) - session = TerminalSession(config, py.std.sys.stdout) - session.main() - l = session.getitemoutcomepairs(Passed) - assert len(l) == 2 - for item in l: - assert item[0].name in ('app_test_something', 'test_method_app') - #item = l[0][0] - #assert item.name == 'test_one' - l = session.getitemoutcomepairs(Skipped) - assert len(l) == 2 - for item in l: - assert item[0].name in ('test_something', 'test_method') + def test_appdirect(self, testdir): + sorter = testdir.inline_run(innertest, '-k', 'applevel', '--runappdirect') + passed, skipped, failed = sorter.listoutcomes() + assert len(passed) == 2 + print passed + names = [x.colitem.name for x in passed] + assert 'app_test_something' in names + assert 'test_method_app' in names From fijal at codespeak.net Wed Mar 4 10:47:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 10:47:39 +0100 (CET) Subject: [pypy-svn] r62510 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090304094739.CB9F216855D@codespeak.net> Author: fijal Date: Wed Mar 4 10:47:37 2009 New Revision: 62510 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py Log: Add a possibility to dump to a stream Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py Wed Mar 4 10:47:37 2009 @@ -1,5 +1,5 @@ from pypy.jit.metainterp import codewriter - +import sys class SourceIterator: @@ -134,7 +134,9 @@ if src.pc != len(jitcode.code): print >> file, 'WARNING: the pc column is bogus! fix dump.py!' -def dump_call_history(call_history): +def dump_call_history(call_history, outfile=None): + if outfile is None: + outfile = sys.stderr indent = 0 for ev, code, args in call_history: if ev == 'enter': @@ -142,7 +144,7 @@ args_s = [str(a) for a in args] else: args_s = [] - print "%s%s(%s)" % (" "*indent, code.name, ','.join(args_s)) + print >>outfile, "%s%s(%s)" % (" "*indent, code.name, ','.join(args_s)) indent += 2 elif ev.startswith('leave'): indent -= 2 From fijal at codespeak.net Wed Mar 4 10:48:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 10:48:46 +0100 (CET) Subject: [pypy-svn] r62511 - in pypy/branch/pyjitpl5/pypy: annotation interpreter rlib Message-ID: <20090304094846.91437168568@codespeak.net> Author: fijal Date: Wed Mar 4 10:48:45 2009 New Revision: 62511 Modified: pypy/branch/pyjitpl5/pypy/annotation/listdef.py pypy/branch/pyjitpl5/pypy/interpreter/pycode.py pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py pypy/branch/pyjitpl5/pypy/rlib/debug.py Log: A new hint for making sure that consts_w of code object is never modified Modified: pypy/branch/pyjitpl5/pypy/annotation/listdef.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/listdef.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/listdef.py Wed Mar 4 10:48:45 2009 @@ -192,6 +192,10 @@ raise TooLateForChange() self.listitem.dont_resize = True + def never_mutate(self): + if self.listitem.resized or self.listitem.mutated: + raise TooLateForChange() + self.listitem.dont_change_any_more = True MOST_GENERAL_LISTDEF = ListDef(None, SomeObject()) Modified: pypy/branch/pyjitpl5/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/pycode.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/pycode.py Wed Mar 4 10:48:45 2009 @@ -11,7 +11,7 @@ from pypy.interpreter.gateway import NoneNotWrapped from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.rlib.rarithmetic import intmask -from pypy.rlib.debug import make_sure_not_resized +from pypy.rlib.debug import make_sure_not_resized, make_sure_not_modified # helper @@ -67,6 +67,7 @@ self.co_stacksize = stacksize self.co_flags = flags self.co_code = code + #self.co_consts_w = make_sure_not_modified(consts) self.co_consts_w = make_sure_not_resized(consts) self.co_names_w = [space.new_interned_str(aname) for aname in names] self.co_varnames = varnames Modified: pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py Wed Mar 4 10:48:45 2009 @@ -9,6 +9,7 @@ import opcode from pypy.rlib.objectmodel import we_are_translated, instantiate from pypy.rlib.jit import we_are_jitted, hint +from pypy.rlib.debug import make_sure_not_resized # Define some opcodes used g = globals() @@ -59,6 +60,7 @@ # class bodies only have CO_NEWLOCALS. self.initialize_frame_scopes(closure) self.fastlocals_w = [None]*self.numlocals + make_sure_not_resized(self.fastlocals_w) self.f_lineno = self.pycode.co_firstlineno def get_builtin(self): Modified: pypy/branch/pyjitpl5/pypy/rlib/debug.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/debug.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/debug.py Wed Mar 4 10:48:45 2009 @@ -122,3 +122,28 @@ def specialize_call(self, hop): hop.exception_cannot_occur() return hop.inputarg(hop.args_r[0], arg=0) + +def make_sure_not_modified(arg): + """ Function checking whether annotation of SomeList is never resized + and never modified, useful for debugging. Does nothing when run directly + """ + return arg + +class Entry(ExtRegistryEntry): + _about_ = make_sure_not_modified + + def compute_result_annotation(self, s_arg): + from pypy.annotation.model import SomeList + assert isinstance(s_arg, SomeList) + # the logic behind it is that we try not to propagate + # make_sure_not_resized, when list comprehension is not on + if self.bookkeeper.annotator.translator.config.translation.list_comprehension_operations: + s_arg.listdef.never_mutate() + else: + from pypy.annotation.annrpython import log + log.WARNING('make_sure_not_modified called, but has no effect since list_comprehension is off') + return s_arg + + def specialize_call(self, hop): + hop.exception_cannot_occur() + return hop.inputarg(hop.args_r[0], arg=0) From afa at codespeak.net Wed Mar 4 11:02:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Mar 2009 11:02:10 +0100 (CET) Subject: [pypy-svn] r62512 - pypy/trunk/pypy/rpython/module Message-ID: <20090304100210.C8CC416855D@codespeak.net> Author: afa Date: Wed Mar 4 11:02:10 2009 New Revision: 62512 Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py Log: Correct the implementation of the fake implementation of os.stat: it should return a STAT_STRUCT, not a LL_STAT_STRUCT which is used to call the libc stat() function. This fixes the tests in rlib/test/test_rmmap.py Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Wed Mar 4 11:02:10 2009 @@ -242,12 +242,15 @@ def posix_fakeimpl(arg): st = getattr(os, name)(arg) - fields = [TYPE for fieldname, TYPE in LL_STAT_FIELDS] + fields = [TYPE for fieldname, TYPE in STAT_FIELDS] TP = TUPLE_TYPE(fields) ll_tup = lltype.malloc(TP.TO) - for i, (fieldname, TYPE) in enumerate(LL_STAT_FIELDS): + for i, (fieldname, TYPE) in enumerate(STAT_FIELDS): val = getattr(st, fieldname) - rffi.setintfield(ll_tup, 'item%d' % i, int(val)) + if isinstance(TYPE, lltype.Number): + rffi.setintfield(ll_tup, 'item%d' % i, int(val)) + else: + setattr(ll_tup, 'item%d' % i, val) return ll_tup if arg_is_path: From fijal at codespeak.net Wed Mar 4 11:16:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 11:16:38 +0100 (CET) Subject: [pypy-svn] r62513 - in pypy/branch/pyjitpl5/pypy: interpreter objspace/std Message-ID: <20090304101638.D9BFC16853A@codespeak.net> Author: fijal Date: Wed Mar 4 11:16:37 2009 New Revision: 62513 Modified: pypy/branch/pyjitpl5/pypy/interpreter/pycode.py pypy/branch/pyjitpl5/pypy/objspace/std/marshal_impl.py Log: make sure the consts_w is not modified after creation Modified: pypy/branch/pyjitpl5/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/pycode.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/pycode.py Wed Mar 4 11:16:37 2009 @@ -67,8 +67,7 @@ self.co_stacksize = stacksize self.co_flags = flags self.co_code = code - #self.co_consts_w = make_sure_not_modified(consts) - self.co_consts_w = make_sure_not_resized(consts) + self.co_consts_w = make_sure_not_modified(consts) self.co_names_w = [space.new_interned_str(aname) for aname in names] self.co_varnames = varnames self.co_freevars = freevars @@ -138,7 +137,7 @@ code.co_stacksize, code.co_flags, code.co_code, - newconsts_w, + newconsts_w[:], list(code.co_names), list(code.co_varnames), code.co_filename, @@ -157,9 +156,9 @@ hidden_applevel=False): """Initialize a new code objects from parameters given by the pypy compiler""" - return PyCode(space, argcount, nlocals, stacksize, flags, code, consts, - names, varnames, filename, name, firstlineno, lnotab, - freevars, cellvars, hidden_applevel) + return PyCode(space, argcount, nlocals, stacksize, flags, code, + consts[:], names, varnames, filename, name, firstlineno, + lnotab, freevars, cellvars, hidden_applevel) _code_new_w = staticmethod(_code_new_w) @@ -245,7 +244,7 @@ dis.dis(co) def fget_co_consts(space, self): - return space.newtuple(self.co_consts_w) + return space.newtuple(self.co_consts_w[:]) def fget_co_names(space, self): return space.newtuple(self.co_names_w) @@ -342,7 +341,7 @@ else: cellvars = [] code = space.allocate_instance(PyCode, w_subtype) - PyCode.__init__(code, space, argcount, nlocals, stacksize, flags, codestring, consts_w, names, + PyCode.__init__(code, space, argcount, nlocals, stacksize, flags, codestring, consts_w[:], names, varnames, filename, name, firstlineno, lnotab, freevars, cellvars, magic=magic) return space.wrap(code) descr_code__new__.unwrap_spec = unwrap_spec @@ -359,7 +358,7 @@ w(self.co_stacksize), w(self.co_flags), w(self.co_code), - space.newtuple(self.co_consts_w), + space.newtuple(self.co_consts_w[:]), space.newtuple(self.co_names_w), space.newtuple([w(v) for v in self.co_varnames]), w(self.co_filename), Modified: pypy/branch/pyjitpl5/pypy/objspace/std/marshal_impl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/objspace/std/marshal_impl.py (original) +++ pypy/branch/pyjitpl5/pypy/objspace/std/marshal_impl.py Wed Mar 4 11:16:37 2009 @@ -376,7 +376,7 @@ m.put_int(x.co_stacksize) m.put_int(x.co_flags) m.atom_str(TYPE_STRING, x.co_code) - m.put_tuple_w(TYPE_TUPLE, x.co_consts_w) + m.put_tuple_w(TYPE_TUPLE, x.co_consts_w[:]) m.atom_strlist(TYPE_TUPLE, TYPE_INTERNED, [space.str_w(w_name) for w_name in x.co_names_w]) m.atom_strlist(TYPE_TUPLE, TYPE_INTERNED, x.co_varnames) m.atom_strlist(TYPE_TUPLE, TYPE_INTERNED, x.co_freevars) From hpk at codespeak.net Wed Mar 4 11:16:43 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 4 Mar 2009 11:16:43 +0100 (CET) Subject: [pypy-svn] r62514 - pypy/trunk/pypy/tool/test Message-ID: <20090304101643.E7305168568@codespeak.net> Author: hpk Date: Wed Mar 4 11:16:43 2009 New Revision: 62514 Modified: pypy/trunk/pypy/tool/test/test_pytestsupport.py Log: fixing tests to use the "testdir" object which helps to test pytest extensions Modified: pypy/trunk/pypy/tool/test/test_pytestsupport.py ============================================================================== --- pypy/trunk/pypy/tool/test/test_pytestsupport.py (original) +++ pypy/trunk/pypy/tool/test/test_pytestsupport.py Wed Mar 4 11:16:43 2009 @@ -10,6 +10,10 @@ from pypy.tool.udir import udir import os import sys +import pypy +conftestpath = py.path.local(pypy.__file__).dirpath("conftest.py") + +pytest_plugins = "pytest_pytester" def somefunc(x): print x @@ -103,23 +107,16 @@ def test_values_arrive2(self): assert self.some1 == 42 -def test_expectcollect(): - try: - import pexpect - except ImportError: - py.test.skip("pexpect not found") - source = py.code.Source(""" - class ExpectTestOne: - def test_one(self): - pass +def test_expectcollect(testdir): + py.test.importorskip("pexpect") + conftestpath.copy(testdir.tmpdir) + sorter = testdir.inline_runsource(""" + class ExpectTestOne: + def test_one(self): + pass """) - from pypy import conftest - tdir = udir.ensure("t", dir=True) - dest = tdir.join("test_expect.py") - dest.write(source) - col = conftest.Module(dest, config="dummy") - result = col.run() - assert len(result) == 1 + passed, skipped, failed = sorter.countoutcomes() + assert passed == 1 def test_safename(): from pypy.conftest import ExpectTestMethod @@ -129,21 +126,18 @@ 'ExpectTest', '()', 'test_one']) == \ 'pypy_tool_test_test_pytestsupport_ExpectTest_paren_test_one' -def test_safe_filename(): - source = py.code.Source(""" - class ExpectTestOne: - def test_one(self): - pass +def test_safe_filename(testdir): + conftestpath.copy(testdir.tmpdir) + sorter = testdir.inline_runsource(""" + class ExpectTestOne: + def test_one(self): + pass """) - dest = udir.join("test_expect_safefilename.py") - dest.write(source) - from pypy import conftest - col = conftest.Module(dest, config="dummy") - methcol = col.join('ExpectTestOne').join('()').join('test_one') - name = 'test_expect_safefilename_ExpectTestOne_paren_test_one.py' - assert methcol.safe_filename() == name - udir.ensure(name) - assert methcol.safe_filename() == name[:-3] + '_1.py' + ev, = sorter.getnamed("itemtestreport") + assert ev.passed + sfn = ev.colitem.safe_filename() + print sfn + assert sfn == 'test_safe_filename_test_safe_filename_ExpectTestOne_paren_test_one_1.py' class ExpectTest: def test_one(self): From hpk at codespeak.net Wed Mar 4 11:22:10 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 4 Mar 2009 11:22:10 +0100 (CET) Subject: [pypy-svn] r62515 - pypy/trunk/pypy/tool/test Message-ID: <20090304102210.58E62168556@codespeak.net> Author: hpk Date: Wed Mar 4 11:22:07 2009 New Revision: 62515 Modified: pypy/trunk/pypy/tool/test/test_pytestsupport.py Log: fix in case of missing pexpect Modified: pypy/trunk/pypy/tool/test/test_pytestsupport.py ============================================================================== --- pypy/trunk/pypy/tool/test/test_pytestsupport.py (original) +++ pypy/trunk/pypy/tool/test/test_pytestsupport.py Wed Mar 4 11:22:07 2009 @@ -127,6 +127,7 @@ 'pypy_tool_test_test_pytestsupport_ExpectTest_paren_test_one' def test_safe_filename(testdir): + py.test.importorskip("pexpect") conftestpath.copy(testdir.tmpdir) sorter = testdir.inline_runsource(""" class ExpectTestOne: From fijal at codespeak.net Wed Mar 4 11:29:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 11:29:23 +0100 (CET) Subject: [pypy-svn] r62516 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090304102923.B1FE516856B@codespeak.net> Author: fijal Date: Wed Mar 4 11:29:23 2009 New Revision: 62516 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py Log: Improve debug info Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py Wed Mar 4 11:29:23 2009 @@ -141,11 +141,14 @@ for ev, code, args in call_history: if ev == 'enter': if args is not None: - args_s = [str(a) for a in args] + args_s = [repr(a) for a in args] else: args_s = [] - print >>outfile, "%s%s(%s)" % (" "*indent, code.name, ','.join(args_s)) + print >>outfile, "%s%s(%s)" % (" "*indent, code.name, ', '.join(args_s)) indent += 2 + elif ev == 'call': + args_s = [repr(a) for a in args] + print >>outfile, "%sCALL %r(%s)" % (" "*indent, code, ', '.join(args_s)) elif ev.startswith('leave'): indent -= 2 elif ev == 'guard_failure': Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Mar 4 11:29:23 2009 @@ -717,6 +717,9 @@ if not self.metainterp.history.generate_anything_since(old_index): assert pure return False + if not we_are_translated(): + self.metainterp._debug_history.append(['call', + argboxes[0], argboxes[1:]]) etype = lltype.nullptr(rclass.OBJECT_VTABLE) evalue = lltype.nullptr(rclass.OBJECT) type_as_int = self.metainterp.cpu.cast_adr_to_int( Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_debug.py Wed Mar 4 11:29:23 2009 @@ -29,14 +29,15 @@ res = self.meta_interp(f, [10], policy=StopAtXPolicy(x)) assert res == 0 ch = get_stats().loops[0]._call_history - cmp = [(i, getattr(j, 'name', 'gf')) for i, j, _ in ch] + cmp = [(i, getattr(j, 'name', None)) for i, j, _ in ch] assert cmp == [ ('enter', 'f'), ('enter', 'g'), ('enter', 'z'), + ('call', None), ('leave', 'z'), ('leave', 'g'), - ('guard_failure', 'gf'), + ('guard_failure', None), ('enter', 'f'), ('leave', 'f'), ] From fijal at codespeak.net Wed Mar 4 12:09:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 12:09:56 +0100 (CET) Subject: [pypy-svn] r62517 - in pypy/branch/pyjitpl5/pypy: jit/tl module/pypyjit Message-ID: <20090304110956.39A4116851F@codespeak.net> Author: fijal Date: Wed Mar 4 12:09:54 2009 New Revision: 62517 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: check in (a bit broken) attempt to use binary shortcuts Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Wed Mar 4 12:09:54 2009 @@ -18,6 +18,7 @@ config.objspace.usemodules.pypyjit = True set_pypy_opt_level(config, level='0') config.objspace.std.multimethods = 'mrd' +config.objspace.std.builtinshortcut = True multimethod.Installer = multimethod.InstallerVersion2 print config Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Wed Mar 4 12:09:54 2009 @@ -98,10 +98,10 @@ pypy.objspace.std.Space.is_w) self.seegraph(pypy.interpreter.pyframe.PyFrame.execute_frame, False) # -------------------- - self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, - pypy.objspace.std.Space.is_true) - self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, - pypy.objspace.std.Space.is_true) + #self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, + # pypy.objspace.std.Space.is_true) + #self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, + # pypy.objspace.std.Space.is_true) # #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, From cfbolz at codespeak.net Wed Mar 4 13:25:34 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 13:25:34 +0100 (CET) Subject: [pypy-svn] r62518 - pypy/branch/spy-graphic/pypy/translator/goal Message-ID: <20090304122534.0A910169DB1@codespeak.net> Author: cfbolz Date: Wed Mar 4 13:25:32 2009 New Revision: 62518 Modified: pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py Log: Give the image name to the interpreter Modified: pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py ============================================================================== --- pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py (original) +++ pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py Wed Mar 4 13:25:32 2009 @@ -7,8 +7,8 @@ from pypy.lang.smalltalk import squeakimage from pypy.lang.smalltalk import constants -def tinyBenchmarks(space, image): - interp = interpreter.Interpreter(space) +def tinyBenchmarks(space, image_name): + interp = interpreter.Interpreter(space, image_name=image_name) w_object = model.W_SmallInteger(0) @@ -54,7 +54,7 @@ reader.initialize() image = squeakimage.SqueakImage() image.from_reader(space, reader) - interp = tinyBenchmarks(space, image) + interp = tinyBenchmarks(space, filename) run_benchmarks(interp) return 0 From cfbolz at codespeak.net Wed Mar 4 13:28:40 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 13:28:40 +0100 (CET) Subject: [pypy-svn] r62519 - pypy/branch/spy-graphic/pypy/lang/smalltalk Message-ID: <20090304122840.562DB169DB6@codespeak.net> Author: cfbolz Date: Wed Mar 4 13:28:39 2009 New Revision: 62519 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Log: Fix bug in cloning: When the cloned object has a shadow, we need to be careful. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py Wed Mar 4 13:28:39 2009 @@ -99,7 +99,7 @@ False means swapping failed""" return False - def clone(self): + def clone(self, space): raise NotImplementedError class W_SmallInteger(W_Object): @@ -139,7 +139,7 @@ def __hash__(self): return self.value - def clone(self): + def clone(self, space): return self class W_Float(W_Object): @@ -177,7 +177,7 @@ def __hash__(self): return hash(self.value) - def clone(self): + def clone(self, space): return self class W_AbstractObjectWithIdentityHash(W_Object): @@ -352,9 +352,9 @@ W_AbstractObjectWithClassReference._become(self, w_other) return True - def clone(self): + def clone(self, space): w_result = W_PointersObject(self.w_class, len(self._vars)) - w_result._vars[:] = self._vars + w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result class W_BytesObject(W_AbstractObjectWithClassReference): @@ -401,9 +401,9 @@ return False return self.bytes == other.bytes - def clone(self): + def clone(self, space): w_result = W_BytesObject(self.w_class, len(self.bytes)) - w_result.bytes[:] = self.bytes + w_result.bytes = list(self.bytes) return w_result class W_WordsObject(W_AbstractObjectWithClassReference): @@ -432,9 +432,9 @@ return (W_AbstractObjectWithClassReference.invariant(self) and isinstance(self.words, list)) - def clone(self): + def clone(self, space): w_result = W_WordsObject(self.w_class, len(self.words)) - w_result.words[:] = self.words + w_result.words = list(self.words) return w_result # XXX Shouldn't compiledmethod have class reference for subclassed compiled Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Wed Mar 4 13:28:39 2009 @@ -614,7 +614,7 @@ @expose_primitive(CLONE, unwrap_spec=[object]) def func(interp, w_arg): - return w_arg.clone() + return w_arg.clone(interp.space) #____________________________________________________________________________ # Time Primitives From cfbolz at codespeak.net Wed Mar 4 13:31:42 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 13:31:42 +0100 (CET) Subject: [pypy-svn] r62520 - pypy/branch/spy-graphic/pypy/lang/smalltalk Message-ID: <20090304123142.823D6169DB1@codespeak.net> Author: cfbolz Date: Wed Mar 4 13:31:42 2009 New Revision: 62520 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Log: Rewrite the bytecode dispatcher that is used when SPy is translated. This reduces the size of the executable by 50 kb! There was a duplicate copy of all the bytecode implementations that have more than one bytecode assigned. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Wed Mar 4 13:31:42 2009 @@ -51,7 +51,8 @@ return option.prim_trace def step(self): - next = self.s_active_context().getNextBytecode() + s_active_context = self.s_active_context() + next = s_active_context.getNextBytecode() # we_are_translated returns false on top of CPython and true when # translating the interpreter if not objectmodel.we_are_translated(): @@ -72,23 +73,16 @@ print "%sStack=%s" % ( self._last_indent, - repr(self.s_active_context().stack()),) + repr(s_active_context.stack()),) print "%sBytecode at %d (%d:%s):" % ( self._last_indent, - self.s_active_context().pc(), + s_active_context.pc(), next, bytecodeimpl.__name__,) - bytecodeimpl(self.s_active_context(), self) + bytecodeimpl(s_active_context, self) else: - # this is a performance optimization: when translating the - # interpreter, the bytecode dispatching is not implemented as a - # list lookup and an indirect call but as a switch. The for loop - # below produces the switch (by being unrolled). - for code, bytecodeimpl in unrolling_bytecode_table: - if code == next: - bytecodeimpl(self.s_active_context(), self) - break + bytecode_dispatch_translated(self, s_active_context, next) class ReturnFromTopLevel(Exception): @@ -549,4 +543,30 @@ return result BYTECODE_TABLE = initialize_bytecode_table() -unrolling_bytecode_table = unroll.unrolling_iterable(enumerate(BYTECODE_TABLE)) + + +def make_bytecode_dispatch_translated(): + # this is a performance optimization: when translating the + # interpreter, the bytecode dispatching is not implemented as a + # list lookup and an indirect call but as a switch. + + code = ["def bytecode_dispatch_translated(self, context, bytecode):"] + prefix = "" + for entry in BYTECODE_RANGES: + if len(entry) == 2: + numbers = [entry[0]] + else: + numbers = range(entry[0], entry[1]+1) + cond = " or ".join(["bytecode == %s" % (i, ) + for i in numbers]) + code.append(" %sif %s:" % (prefix, cond, )) + code.append(" context.%s(self)" % (entry[-1], )) + prefix = "el" + code.append("bytecode_dispatch_translated._always_inline_ = True") + source = py.code.Source("\n".join(code)) + print source + miniglob = {} + exec source.compile() in miniglob + return miniglob["bytecode_dispatch_translated"] + +bytecode_dispatch_translated = make_bytecode_dispatch_translated() From fijal at codespeak.net Wed Mar 4 14:27:02 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 14:27:02 +0100 (CET) Subject: [pypy-svn] r62521 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090304132702.05C8716851F@codespeak.net> Author: fijal Date: Wed Mar 4 14:26:59 2009 New Revision: 62521 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: for now use normal int addition instead of inplace addition Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Wed Mar 4 14:26:59 2009 @@ -4,7 +4,8 @@ i = 0 while i < 100: - i += 3 + # XXX implement inplace_add method for ints + i = i + 3 print i # should print 102 f() From fijal at codespeak.net Wed Mar 4 14:28:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 14:28:33 +0100 (CET) Subject: [pypy-svn] r62522 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090304132833.46A7A16851F@codespeak.net> Author: fijal Date: Wed Mar 4 14:28:32 2009 New Revision: 62522 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: correct seepath Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Wed Mar 4 14:28:32 2009 @@ -98,10 +98,10 @@ pypy.objspace.std.Space.is_w) self.seegraph(pypy.interpreter.pyframe.PyFrame.execute_frame, False) # -------------------- - #self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, - # pypy.objspace.std.Space.is_true) - #self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, - # pypy.objspace.std.Space.is_true) + self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, + pypy.objspace.std.boolobject.nonzero__Bool) + self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, + pypy.objspace.std.boolobject.nonzero__Bool) # #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, From afa at codespeak.net Wed Mar 4 14:51:35 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Mar 2009 14:51:35 +0100 (CET) Subject: [pypy-svn] r62523 - in pypy/trunk/pypy/translator/cli: . test Message-ID: <20090304135135.05E5D16857C@codespeak.net> Author: afa Date: Wed Mar 4 14:51:35 2009 New Revision: 62523 Modified: pypy/trunk/pypy/translator/cli/support.py pypy/trunk/pypy/translator/cli/test/test_string.py Log: cli backend: Don't add an extra zero when embedding a rstring literal. only strings containing non-pritable chars where concerned. this fixes many problems: - the interactive interpreter did not work at all (SyntaxError at end of line) - crash when printing an exception when a applevel function is in the traceback, i.e always (out of bound access in lnotab), - ord('\a') failed when loaded from a .pyc file (string of length 2 found) Modified: pypy/trunk/pypy/translator/cli/support.py ============================================================================== --- pypy/trunk/pypy/translator/cli/support.py (original) +++ pypy/trunk/pypy/translator/cli/support.py Wed Mar 4 14:51:35 2009 @@ -28,7 +28,7 @@ def line_repr(s): return ''.join([char_repr(c) for c in s]) def array_repr(s): - return ' '.join(['%x 00' % ord(c) for c in s]+['00']) + return ' '.join(['%x 00' % ord(c) for c in s]) try: return '"%s"' % line_repr(s) Modified: pypy/trunk/pypy/translator/cli/test/test_string.py ============================================================================== --- pypy/trunk/pypy/translator/cli/test/test_string.py (original) +++ pypy/trunk/pypy/translator/cli/test/test_string.py Wed Mar 4 14:51:35 2009 @@ -31,3 +31,10 @@ def fn(i, j): return strings[i] < strings[j] assert self.interpret(fn, [0, 1], backendopt=False) == fn(0, 1) + + def test_literal_length(self): + strings = ['aa', 'a\x01', 'a\x00'] + def fn(): + for s in strings: + assert len(s) == 2 + self.interpret(fn, [], backendopt=False) From tverwaes at codespeak.net Wed Mar 4 15:23:10 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 15:23:10 +0100 (CET) Subject: [pypy-svn] r62524 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304142310.A38DC16855D@codespeak.net> Author: tverwaes Date: Wed Mar 4 15:23:08 2009 New Revision: 62524 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: removed object writing to tile class, and fixed reversed bug Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Wed Mar 4 15:23:08 2009 @@ -12,27 +12,6 @@ from pypy.lang.gameboy.video_mode import Mode0, Mode1, Mode2, Mode3 # ----------------------------------------------------------------------------- -class VideoCallWraper(object): - def call(self, pos, color, mask): - pass - - -class set_overlapped_object_line_call_wrapper(VideoCallWraper): - def __init__(self, video): - self.video = video - - def call(self, pos, color, mask): - self.video.set_overlapped_object_line(pos, color, mask) - - -class set_tile_line_call_wrapper(VideoCallWraper): - def __init__(self, video): - self.video = video - - def call(self, pos, color, mask): - self.video.set_tile_line(pos, color, mask) - -# ----------------------------------------------------------------------------- class Video(iMemory): @@ -77,13 +56,16 @@ def update_tile(self, address, data): self.get_tile(address).set_data_at(address, data); - - def get_tile(self, address): - tile_index = (address - TILE_DATA_ADDR) / (SPRITE_SIZE*2) + + def get_tile_at(self, tile_index): if tile_index < TILE_DATA_SIZE: return self.tile_data_0[tile_index] else: return self.tile_data_1[tile_index - TILE_DATA_SIZE / 2] + + def get_tile(self, address): + tile_index = (address - TILE_DATA_ADDR) >> 4 + return self.get_tile_at(tile_index) def select_tile_group_for(self, address): tile_map_index = address - TILE_MAP_ADDR #) >> 1 @@ -482,10 +464,7 @@ lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): sprite = self.shown_sprites[index] - if (sprite.x + SPRITE_SIZE <= lastx): - sprite.draw(self) - else: - sprite.draw_overlapped(self) + sprite.draw(lastx) lastx = sprite.x def scan_sprites(self): @@ -523,54 +502,6 @@ group_index += 1 x += SPRITE_SIZE - def get_pattern(self, address): - # TODO: remove method! - return self.get_vram(VRAM_ADDR + address) + (self.get_vram(VRAM_ADDR + address + 1) << 8) - - def draw_object_tile(self, sprite): - self.draw_object(set_tile_line_call_wrapper(self), sprite) - - def set_tile_line(self, pos, color, mask): - self.line[pos] |= color | mask - - def draw_overlapped_object_tile(self, sprite): - self.draw_object(set_overlapped_object_line_call_wrapper(self), sprite) - - def set_overlapped_object_line(self, pos, color, mask): - self.line[pos] = (self.line[pos] & 0x0101) | color | mask - - def draw_object(self, caller, sprite): - pattern = self.get_pattern(sprite.get_tile_address(self)) - mask = 0 - # priority - if sprite.object_behind_background: - mask |= 0x0008 - # palette - if sprite.palette_number: - mask |= 0x0004 - if sprite.y_flipped: - self.draw_object_flipped(sprite.x, pattern, mask, caller) - else: - self.draw_object_normal(sprite.x, pattern, mask, caller) - - def draw_object_flipped(self, x, pattern, mask, caller): - color = (pattern << 1) & 0x0202 - if color != 0: - caller.call(x, color, mask) - for i in range(0, 7): - color = (pattern >> i) & 0x0202 - if color != 0: - caller.call(x + i + 1, color, mask) - - def draw_object_normal(self, x, pattern, mask, caller): - for i in range(0, 7): - color = (pattern >> (6-i)) & 0x0202 - if color != 0: - caller.call(x + i, color, mask) - color = (pattern << 1) & 0x0202 - if color != 0: - caller.call(x+7, color, mask) - def draw_pixels_line(self): self.update_palette() pixels = self.driver.get_pixels() Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 15:23:08 2009 @@ -89,21 +89,24 @@ extracts the Attributes/Flags: Bit7 OBJ-to-BG Priority (0=OBJ Above BG, 1=OBJ Behind BG color 1-3) (Used for both BG and Window. BG color 0 is always behind OBJ) - Bit6 Y flip (0=Normal, 1=Vertically mirrored) - Bit5 X flip (0=Normal, 1=Horizontally mirrored) + Bit6 X flip (0=Normal, 1=Vertically mirrored) + Bit5 Y flip (0=Normal, 1=Horizontally mirrored) Bit4 Palette number **Non CGB Mode Only** (0=OBP0, 1=OBP1) """ - self.object_behind_background = bool(data & (1 << 7)) - self.x_flipped = bool(data & (1 << 6)) - self.y_flipped = bool(data & (1 << 5)) - self.palette_number = bool(data & (1 << 4)) - self.rest_attributes_and_flags = data & (1+2+4+8) + self.object_behind_background = bool(data & (1 << 7)) + self.y_flipped = bool(data & (1 << 6)) + self.x_flipped = bool(data & (1 << 5)) + self.palette_number = bool(data & (1 << 4)) + self.rest_attributes_and_flags = data & ((1<<3) + + (1<<2) + + (1<<1) + + (1<<0)) def get_attributes_and_flags(self): value = 0 value += int(self.object_behind_background) << 7 - value += int(self.x_flipped) << 6 - value += int(self.y_flipped) << 5 + value += int(self.y_flipped) << 6 + value += int(self.x_flipped) << 5 value += int(self.palette_number) << 4 value += self.rest_attributes_and_flags return value @@ -146,14 +149,11 @@ def current_line_y(self, video): return video.line_y - self.y + 2 * SPRITE_SIZE - def get_tile(self, video): - if video.control.big_sprites: - return self.get_tile_number() & 0xFE - else: - return self.get_tile_number() - - def get_tile_address(self, video): - return (self.get_tile(video) << 4) + (self.get_draw_y(video) << 1) + def get_tile(self): + address = self.get_tile_number() + if self.video.control.big_sprites: + address &= 0xFE + return self.video.get_tile_at(address) def get_draw_y(self, video): y = self.current_line_y(video) @@ -161,12 +161,9 @@ y = self.get_tile_size() - y return y - def draw(self, video): - video.draw_object_tile(self) - - def draw_overlapped(self, video): - video.draw_overlapped_object_tile(self) - + def draw(self, lastx): + self.get_tile().draw_for_sprite(self, lastx) + # ----------------------------------------------------------------------------- class Tile(object): @@ -201,7 +198,27 @@ def get_pattern_at(self, address): return self.get_data_at(address) +\ (self.get_data_at(address + 1) << 8) - + + def draw_for_sprite(self, sprite, lastx): + if sprite.x_flipped: + convert, offset = 1, 0 # 0-7 + else: + convert, offset = -1, SPRITE_SIZE # 7-0 + + y = sprite.get_draw_y(self.video) << 1 + pattern = self.get_pattern_at(y) << 1 + mask = (sprite.palette_number << 2) +\ + (sprite.object_behind_background << 3) + + for i in range(SPRITE_SIZE): + color = (pattern >> i) & 0x0202 + x = sprite.x + offset + i*convert + if bool(color): + if sprite.x + SPRITE_SIZE > lastx: + # Overlapped. + self.video.line[x] &= 0x0101 + self.video.line[x] |= color | mask + # ----------------------------------------------------------------------------- class Drawable(object): From fijal at codespeak.net Wed Mar 4 15:38:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 15:38:23 +0100 (CET) Subject: [pypy-svn] r62525 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090304143823.0BA901684DE@codespeak.net> Author: fijal Date: Wed Mar 4 15:38:22 2009 New Revision: 62525 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: get*_pure operations Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Wed Mar 4 15:38:22 2009 @@ -68,10 +68,10 @@ _prev = Box._extended_display try: Box._extended_display = False - #if len(self.graphs) > 1: - # graphs = self.graphs[1:] - #else: - graphs = self.graphs + if len(self.graphs) > 1: + graphs = self.graphs[1:] + else: + graphs = self.graphs for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Wed Mar 4 15:38:22 2009 @@ -138,11 +138,14 @@ ARRAYLEN_GC = 77 STRLEN = 78 STRGETITEM = 79 - _ALWAYS_PURE_LAST = 79 # ----- end of always_pure operations ----- + GETFIELD_GC_PURE = 80 + GETFIELD_RAW_PURE = 81 + GETARRAYITEM_GC_PURE = 82 + _ALWAYS_PURE_LAST = 82 # ----- end of always_pure operations ----- - GETARRAYITEM_GC = 80 - GETFIELD_GC = 81 - GETFIELD_RAW = 82 + GETARRAYITEM_GC = 83 + GETFIELD_GC = 84 + GETFIELD_RAW = 85 _NOSIDEEFFECT_LAST = 89 # ----- end of no_side_effect operations ----- NEW = 90 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Mar 4 15:38:22 2009 @@ -168,6 +168,9 @@ res = self.meta_interp(f, [20]) assert res == 9 + def test_immutable_constant_getfield(self): + xxx + ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) From fijal at codespeak.net Wed Mar 4 15:39:05 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 15:39:05 +0100 (CET) Subject: [pypy-svn] r62526 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090304143905.AF458168517@codespeak.net> Author: fijal Date: Wed Mar 4 15:39:05 2009 New Revision: 62526 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: oops oops, this was not meant to go inside Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Wed Mar 4 15:39:05 2009 @@ -68,10 +68,10 @@ _prev = Box._extended_display try: Box._extended_display = False - if len(self.graphs) > 1: - graphs = self.graphs[1:] - else: - graphs = self.graphs + #if len(self.graphs) > 1: + # graphs = self.graphs[1:] + #else: + graphs = self.graphs for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Mar 4 15:39:05 2009 @@ -168,9 +168,6 @@ res = self.meta_interp(f, [20]) assert res == 9 - def test_immutable_constant_getfield(self): - xxx - ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) From tverwaes at codespeak.net Wed Mar 4 15:44:05 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 15:44:05 +0100 (CET) Subject: [pypy-svn] r62527 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304144405.884091684F9@codespeak.net> Author: tverwaes Date: Wed Mar 4 15:44:05 2009 New Revision: 62527 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: removing unnecessary arguments from functions Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Wed Mar 4 15:44:05 2009 @@ -471,7 +471,7 @@ # search active shown_sprites count = 0 for sprite in self.sprites: - if sprite.is_shown_on_current_line(self): + if sprite.is_shown_on_current_line(): self.shown_sprites[count] = sprite count += 1 if count >= SPRITES_PER_LINE: Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 15:44:05 2009 @@ -25,11 +25,19 @@ self.rest_attributes_and_flags = 0 def get_data_at(self, address): - return self.get_data()[address % 4] - - def get_data(self): - return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] + address %= 4 + if id == 0: + return self.y + if id == 1: + return self.x + if id == 2: + return self.tile_number + if id == 3: + return self.get_attributes_and_flags() + # Making PyPy happy... + raise Exception("Cannot happen") + def set_data(self, y, x, tile_number, flags): """ extracts the sprite data from an oam entry @@ -139,15 +147,15 @@ else: return 7 - def intersects_current_line(self, video): - y = self.current_line_y(video) + def intersects_current_line(self): + y = self.current_line_y() return y >= 0 and y <= self.get_tile_size() - def is_shown_on_current_line(self, video): - return not self.hidden and self.intersects_current_line(video) + def is_shown_on_current_line(self): + return not self.hidden and self.intersects_current_line() - def current_line_y(self, video): - return video.line_y - self.y + 2 * SPRITE_SIZE + def current_line_y(self): + return self.video.line_y - self.y + 2 * SPRITE_SIZE def get_tile(self): address = self.get_tile_number() @@ -155,8 +163,8 @@ address &= 0xFE return self.video.get_tile_at(address) - def get_draw_y(self, video): - y = self.current_line_y(video) + def get_draw_y(self): + y = self.current_line_y() if self.y_flipped: y = self.get_tile_size() - y return y @@ -171,7 +179,6 @@ def __init__(self, number, video): self.video = video self.number = number - self.reset() self.data = [0x00 for i in range(2*SPRITE_SIZE)] def draw(self, x, y): @@ -180,9 +187,6 @@ value = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 self.video.line[x + i] = value - def reset(self): - pass - def set_tile_data(self, data): self.data = data @@ -205,7 +209,7 @@ else: convert, offset = -1, SPRITE_SIZE # 7-0 - y = sprite.get_draw_y(self.video) << 1 + y = sprite.get_draw_y() << 1 pattern = self.get_pattern_at(y) << 1 mask = (sprite.palette_number << 2) +\ (sprite.object_behind_background << 3) From tverwaes at codespeak.net Wed Mar 4 15:47:52 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 15:47:52 +0100 (CET) Subject: [pypy-svn] r62528 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304144752.BCADF168517@codespeak.net> Author: tverwaes Date: Wed Mar 4 15:47:52 2009 New Revision: 62528 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: cleanup Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Wed Mar 4 15:47:52 2009 @@ -553,7 +553,7 @@ return self.width def get_height(self): - return selg.height + return self.height def get_pixels(self): return self.pixels Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 15:47:52 2009 @@ -141,15 +141,9 @@ else: return SPRITE_SIZE - def get_tile_size(self): - if self.big_size: - return 15 - else: - return 7 - def intersects_current_line(self): y = self.current_line_y() - return y >= 0 and y <= self.get_tile_size() + return 0 <= y and y < self.get_height() def is_shown_on_current_line(self): return not self.hidden and self.intersects_current_line() @@ -166,7 +160,7 @@ def get_draw_y(self): y = self.current_line_y() if self.y_flipped: - y = self.get_tile_size() - y + y = self.get_height() - 1 - y return y def draw(self, lastx): From fijal at codespeak.net Wed Mar 4 16:00:30 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 16:00:30 +0100 (CET) Subject: [pypy-svn] r62529 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090304150030.A6657168543@codespeak.net> Author: fijal Date: Wed Mar 4 16:00:30 2009 New Revision: 62529 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: a strangely failing test Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Mar 4 16:00:30 2009 @@ -168,6 +168,26 @@ res = self.meta_interp(f, [20]) assert res == 9 + def test_immutable_constant_getfield(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + + class Stuff(object): + _immutable_ = True + def __init__(self, x): + self.x = x + + def f(n): + stuff = Stuff(1) + while n > 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + n -= stuff.x + return n + + res = self.meta_interp(f, [10]) + assert n == 0 + self.check_loops(getfield_gc=0) + ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) From fijal at codespeak.net Wed Mar 4 16:07:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 16:07:38 +0100 (CET) Subject: [pypy-svn] r62530 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090304150738.7AA8F168042@codespeak.net> Author: fijal Date: Wed Mar 4 16:07:36 2009 New Revision: 62530 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: a test (passes, but should not) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Mar 4 16:07:36 2009 @@ -1,5 +1,5 @@ import py -from pypy.rlib.jit import JitDriver +from pypy.rlib.jit import JitDriver, hint from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass @@ -169,23 +169,25 @@ assert res == 9 def test_immutable_constant_getfield(self): - myjitdriver = JitDriver(greens = [], reds = ['n']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'i']) class Stuff(object): _immutable_ = True def __init__(self, x): self.x = x + + stuff = [Stuff(1), Stuff(3)] - def f(n): - stuff = Stuff(1) + def f(n, i): while n > 0: - myjitdriver.can_enter_jit(n=n) - myjitdriver.jit_merge_point(n=n) - n -= stuff.x + myjitdriver.can_enter_jit(n=n, i=i) + myjitdriver.jit_merge_point(n=n, i=i) + i = hint(i, promote=True) + n -= stuff[i].x return n - res = self.meta_interp(f, [10]) - assert n == 0 + res = self.meta_interp(f, [10, 0]) + assert res == 0 self.check_loops(getfield_gc=0) ##class TestOOtype(VirtualTests, OOJitMixin): From fijal at codespeak.net Wed Mar 4 16:14:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 16:14:28 +0100 (CET) Subject: [pypy-svn] r62531 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090304151428.4CF301684DA@codespeak.net> Author: fijal Date: Wed Mar 4 16:14:27 2009 New Revision: 62531 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: (fijal, arigo) good, test finally fails for a good reason Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Mar 4 16:14:27 2009 @@ -169,24 +169,24 @@ assert res == 9 def test_immutable_constant_getfield(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'i']) + myjitdriver = JitDriver(greens = ['stuff'], reds = ['n', 'i']) class Stuff(object): _immutable_ = True def __init__(self, x): self.x = x - stuff = [Stuff(1), Stuff(3)] - - def f(n, i): + def f(n, a, i): + stuff = [Stuff(a), Stuff(3)] while n > 0: - myjitdriver.can_enter_jit(n=n, i=i) - myjitdriver.jit_merge_point(n=n, i=i) + myjitdriver.can_enter_jit(n=n, i=i, stuff=stuff) + myjitdriver.jit_merge_point(n=n, i=i, stuff=stuff) i = hint(i, promote=True) - n -= stuff[i].x + v = Stuff(i) + n -= stuff[v.x].x return n - res = self.meta_interp(f, [10, 0]) + res = self.meta_interp(f, [10, 1, 0], listops=True) assert res == 0 self.check_loops(getfield_gc=0) From tverwaes at codespeak.net Wed Mar 4 16:39:02 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 16:39:02 +0100 (CET) Subject: [pypy-svn] r62532 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304153902.604FE1684D3@codespeak.net> Author: tverwaes Date: Wed Mar 4 16:39:00 2009 New Revision: 62532 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/timer.py Log: hardwiring the clock in the gameboy_implementation Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 16:39:00 2009 @@ -6,6 +6,7 @@ from pypy.lang.gameboy.sound import SoundDriver from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants +import time use_rsdl = True if use_rsdl: @@ -49,10 +50,20 @@ def emulate_cycle(self): # self.joypad_driver.button_up(True) + X = 1<<5 + start_time = time.time() self.handle_events() - self.emulate(constants.GAMEBOY_CLOCK >> 2) + # Come back to this cycle every 1/X seconds + self.emulate(constants.GAMEBOY_CLOCK / X) if use_rsdl: RSDL.Delay(1) + spent = time.time() - start_time + left = (1.0/X) - spent + if left >= 0: + time.sleep(left) + else: + print "WARNING: Going to slow: ", spent, " ", left + def handle_execution_error(self, error): if use_rsdl: Modified: pypy/trunk/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/timer.py (original) +++ pypy/trunk/pypy/lang/gameboy/timer.py Wed Mar 4 16:39:00 2009 @@ -156,5 +156,4 @@ pass def get_time(self): - return int(time.time()*1000) - + return int(time.time()) From santagada at codespeak.net Wed Mar 4 16:58:11 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Wed, 4 Mar 2009 16:58:11 +0100 (CET) Subject: [pypy-svn] r62533 - pypy/trunk/pypy/rlib/rsdl Message-ID: <20090304155811.4724E16845F@codespeak.net> Author: santagada Date: Wed Mar 4 16:58:10 2009 New Revision: 62533 Modified: pypy/trunk/pypy/rlib/rsdl/eci.py Log: quick fix for not using the framework paramenters when linking... a proper fix is comming today Modified: pypy/trunk/pypy/rlib/rsdl/eci.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/eci.py (original) +++ pypy/trunk/pypy/rlib/rsdl/eci.py Wed Mar 4 16:58:10 2009 @@ -11,13 +11,15 @@ #'SDLMain.m' #'SDLMain.h'*/ ], - include_dirs = ['/Library/Frameworks/SDL.framework/Versions/A/Headers', + include_dirs = ['/Library/Frameworks/SDL.framework/Headers', #str(py.magic.autopath().dirpath().join('macosx-sdl-main')) ], link_extra = [ str(py.magic.autopath().dirpath().join('macosx-sdl-main/SDLMain.m')), #'macosx-sdl-main/SDLMain.m', - '-I', '/Library/Frameworks/SDL.framework/Versions/A/Headers', + '-I', '/Library/Frameworks/SDL.framework/Headers', + '-framework', 'Cocoa', + '-framework', 'SD', ], frameworks = ['SDL', 'Cocoa'] ) From cami at codespeak.net Wed Mar 4 17:10:18 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 4 Mar 2009 17:10:18 +0100 (CET) Subject: [pypy-svn] r62534 - pypy/trunk/pypy/rlib/rsdl Message-ID: <20090304161018.046CE168518@codespeak.net> Author: cami Date: Wed Mar 4 17:10:17 2009 New Revision: 62534 Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py pypy/trunk/pypy/rlib/rsdl/eci.py Log: fixing RSDL hide AppKit call during translation Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RSDL.py Wed Mar 4 17:10:17 2009 @@ -227,7 +227,7 @@ # ------------------------------------------------------------------------------ -if sys.platform == 'darwin': +if sys.platform == 'darwin' and we_are_translated(): def Init(flags): if not we_are_translated(): from AppKit import NSApplication Modified: pypy/trunk/pypy/rlib/rsdl/eci.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/eci.py (original) +++ pypy/trunk/pypy/rlib/rsdl/eci.py Wed Mar 4 17:10:17 2009 @@ -19,7 +19,7 @@ #'macosx-sdl-main/SDLMain.m', '-I', '/Library/Frameworks/SDL.framework/Headers', '-framework', 'Cocoa', - '-framework', 'SD', + '-framework', 'SDL', ], frameworks = ['SDL', 'Cocoa'] ) From afa at codespeak.net Wed Mar 4 17:17:41 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Mar 2009 17:17:41 +0100 (CET) Subject: [pypy-svn] r62535 - in pypy/trunk/pypy: . translator/cli translator/js translator/jvm Message-ID: <20090304161741.BA200168518@codespeak.net> Author: afa Date: Wed Mar 4 17:17:41 2009 New Revision: 62535 Modified: pypy/trunk/pypy/conftest.py pypy/trunk/pypy/translator/cli/conftest.py pypy/trunk/pypy/translator/cli/option.py pypy/trunk/pypy/translator/js/conftest.py pypy/trunk/pypy/translator/jvm/conftest.py pypy/trunk/pypy/translator/jvm/option.py Log: My turn to remove some py.test deprecation warnings: turn all these files into ConfestPlugins. It seems that the test collection scans too many conftests: python test_all.py translator/c/test will process all test plugins from translator/cli, translator/js and translator/jvm. Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Wed Mar 4 17:17:41 2009 @@ -30,7 +30,7 @@ class PyPyTestPlugin: def pytest_addoption(self, parser): - group = parser.addgroup("pypy option") + group = parser.addgroup("pypy options") group.addoption('--view', action="store_true", dest="view", default=False, help="view translation tests' flow graphs with Pygame") group.addoption('-A', '--runappdirect', action="store_true", Modified: pypy/trunk/pypy/translator/cli/conftest.py ============================================================================== --- pypy/trunk/pypy/translator/cli/conftest.py (original) +++ pypy/trunk/pypy/translator/cli/conftest.py Wed Mar 4 17:17:41 2009 @@ -1,34 +1,19 @@ -import py - -Option = py.test.config.Option - -option = py.test.config.addoptions\ - ("pypy-cli options", - - Option('--source', action="store_true", dest="source", default=False, - help="only generate IL source, don't compile"), - - Option('--wd', action="store_true", dest="wd", default=False, - help="store temporary files in the working directory"), - - Option('--stdout', action="store_true", dest="stdout", default=False, - help="print the generated IL code to stdout, too"), - - Option('--nostop', action="store_true", dest="nostop", default=False, - help="don't stop on warning. The generated IL code could not compile"), - - Option('--nowrap', action="store_true", dest="nowrap", default=False, - help="don't wrap exceptions but let them to flow out of the entry point"), - - Option('--verify', action="store_true", dest="verify", default=False, - help="check that compiled executables are verifiable"), - - Option('--norun', action='store_true', dest="norun", default=False, - help="don't run the compiled executable"), - - Option('--trace', action='store_true', dest='trace', default=False, - help='Trace execution of generated code'), - ) - - - +class ConftestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypy-cli options") + group.addoption('--source', action="store_true", dest="source", default=False, + help="only generate IL source, don't compile") + group.addoption('--wd', action="store_true", dest="wd", default=False, + help="store temporary files in the working directory") + group.addoption('--stdout', action="store_true", dest="stdout", default=False, + help="print the generated IL code to stdout, too") + group.addoption('--nostop', action="store_true", dest="nostop", default=False, + help="don't stop on warning. The generated IL code could not compile") + group.addoption('--nowrap', action="store_true", dest="nowrap", default=False, + help="don't wrap exceptions but let them to flow out of the entry point") + group.addoption('--verify', action="store_true", dest="verify", default=False, + help="check that compiled executables are verifiable") + group.addoption('--norun', action='store_true', dest="norun", default=False, + help="don't run the compiled executable") + group.addoption('--trace', action='store_true', dest='trace', default=False, + help='Trace execution of generated code') Modified: pypy/trunk/pypy/translator/cli/option.py ============================================================================== --- pypy/trunk/pypy/translator/cli/option.py (original) +++ pypy/trunk/pypy/translator/cli/option.py Wed Mar 4 17:17:41 2009 @@ -1,4 +1,4 @@ -from pypy.translator.cli.conftest import option +from pypy.conftest import option _defaultopt = dict(wd = False, source = False, nostop = False, stdout = False) Modified: pypy/trunk/pypy/translator/js/conftest.py ============================================================================== --- pypy/trunk/pypy/translator/js/conftest.py (original) +++ pypy/trunk/pypy/translator/js/conftest.py Wed Mar 4 17:17:41 2009 @@ -1,11 +1,7 @@ -import py - -Option = py.test.config.Option - -option = py.test.config.addoptions("pypy-ojs options", - Option('--use-browser', action="store", dest="browser", type="string", - default="", help="run Javascript tests in your default browser"), - - Option('--tg', action="store_true", dest="tg", default=False, - help="Use TurboGears machinery for testing") - ) +class ConftestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypy-ojs options") + group.addoption('--use-browser', action="store", dest="browser", type="string", + default="", help="run Javascript tests in your default browser") + group.addoption('--tg', action="store_true", dest="tg", default=False, + help="Use TurboGears machinery for testing") Modified: pypy/trunk/pypy/translator/jvm/conftest.py ============================================================================== --- pypy/trunk/pypy/translator/jvm/conftest.py (original) +++ pypy/trunk/pypy/translator/jvm/conftest.py Wed Mar 4 17:17:41 2009 @@ -1,22 +1,18 @@ -import py +class ConftestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypy-jvm options") + group.addoption('--java', action='store', dest='java', default='java', + help='Define the java executable to use') + group.addoption('--javac', action='store', dest='javac', default='javac', + help='Define the javac executable to use') + group.addoption('--jasmin', action='store', dest='java', default='java', + help='Define the jasmin script to use') + group.addoption('--noassemble', action='store_true', dest="noasm", default=False, + help="don't assemble jasmin files") + group.addoption('--package', action='store', dest='package', default='pypy', + help='Package to output generated classes into') +## group.addoption('--trace', action='store_true', dest='trace', default=False, +## help='Trace execution of generated code') + group.addoption('--byte-arrays', action='store_true', dest='byte-arrays', + default=False, help='Use byte arrays rather than native strings') -Option = py.test.config.Option - -option = py.test.config.addoptions( - "pypy-jvm options", - - Option('--java', action='store', dest='java', default='java', - help='Define the java executable to use'), - Option('--javac', action='store', dest='javac', default='javac', - help='Define the javac executable to use'), - Option('--jasmin', action='store', dest='java', default='java', - help='Define the jasmin script to use'), - Option('--noassemble', action='store_true', dest="noasm", default=False, - help="don't assemble jasmin files"), - Option('--package', action='store', dest='package', default='pypy', - help='Package to output generated classes into'), -## Option('--trace', action='store_true', dest='trace', default=False, -## help='Trace execution of generated code'), - Option('--byte-arrays', action='store_true', dest='byte-arrays', - default=False, help='Use byte arrays rather than native strings'), - ) Modified: pypy/trunk/pypy/translator/jvm/option.py ============================================================================== --- pypy/trunk/pypy/translator/jvm/option.py (original) +++ pypy/trunk/pypy/translator/jvm/option.py Wed Mar 4 17:17:41 2009 @@ -1,4 +1,4 @@ -from pypy.translator.jvm.conftest import option +from pypy.conftest import option # Not sure why this is needed. Sure that it shouldn't be, even. _default_values = { From tverwaes at codespeak.net Wed Mar 4 17:36:25 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 17:36:25 +0100 (CET) Subject: [pypy-svn] r62537 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304163625.56DD31684FF@codespeak.net> Author: tverwaes Date: Wed Mar 4 17:36:24 2009 New Revision: 62537 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: removing rsdl-sleep Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 17:36:24 2009 @@ -50,16 +50,17 @@ def emulate_cycle(self): # self.joypad_driver.button_up(True) - X = 1<<5 + X = 1<<6 # About 1<<6 to make sure we have a clean distrubution of about + # 1<<6 frames per second start_time = time.time() self.handle_events() # Come back to this cycle every 1/X seconds self.emulate(constants.GAMEBOY_CLOCK / X) - if use_rsdl: - RSDL.Delay(1) + # if use_rsdl: + # RSDL.Delay(100) spent = time.time() - start_time left = (1.0/X) - spent - if left >= 0: + if left > 0: time.sleep(left) else: print "WARNING: Going to slow: ", spent, " ", left From cfbolz at codespeak.net Wed Mar 4 18:16:46 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 18:16:46 +0100 (CET) Subject: [pypy-svn] r62538 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304171646.BA16D16851C@codespeak.net> Author: cfbolz Date: Wed Mar 4 18:16:44 2009 New Revision: 62538 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: Kill some very funny code. This is one of the largest sources of allocations in the gameboy at runtime. Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 18:16:44 2009 @@ -121,9 +121,7 @@ self.draw_ascii_pixels() def draw_pixels(self): - str = "" for y in range(self.height): - str += "\n" for x in range(self.width): color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] RSDL_helper.set_pixel(self.screen, x, y, color) From cfbolz at codespeak.net Wed Mar 4 18:18:36 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 18:18:36 +0100 (CET) Subject: [pypy-svn] r62539 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304171836.7BF0416851C@codespeak.net> Author: cfbolz Date: Wed Mar 4 18:18:35 2009 New Revision: 62539 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: fix typo Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 18:18:35 2009 @@ -63,7 +63,7 @@ if left > 0: time.sleep(left) else: - print "WARNING: Going to slow: ", spent, " ", left + print "WARNING: Going too slow: ", spent, " ", left def handle_execution_error(self, error): From cfbolz at codespeak.net Wed Mar 4 18:20:22 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 18:20:22 +0100 (CET) Subject: [pypy-svn] r62540 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304172022.6FD6A16851E@codespeak.net> Author: cfbolz Date: Wed Mar 4 18:20:21 2009 New Revision: 62540 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: kill unused and wrong method Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 18:20:21 2009 @@ -143,12 +143,7 @@ else: return self.pixels[x+self.width*y] - def pixel_to_byte(self, int_number): - return struct.pack("B", (int_number) & 0xFF, - (int_number >> 8) & 0xFF, - (int_number >> 16) & 0xFF) - - + # JOYPAD DRIVER ---------------------------------------------------------------- class JoypadDriverImplementation(JoypadDriver): From tverwaes at codespeak.net Wed Mar 4 18:48:14 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 18:48:14 +0100 (CET) Subject: [pypy-svn] r62541 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304174814.ED518168516@codespeak.net> Author: tverwaes Date: Wed Mar 4 18:48:12 2009 New Revision: 62541 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: we have to select the lower tile in case we draw a y intersecting with a bigtile Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 18:48:12 2009 @@ -151,20 +151,33 @@ def current_line_y(self): return self.video.line_y - self.y + 2 * SPRITE_SIZE - def get_tile(self): + def get_tile_address(self): address = self.get_tile_number() - if self.video.control.big_sprites: + if self.big_size: address &= 0xFE - return self.video.get_tile_at(address) + return address + + def get_tile(self): + return self.video.get_tile_at(self.get_tile_address()) + + def get_lower_tile(self): + return self.video.get_tile_at(self.get_tile_address()+1) def get_draw_y(self): y = self.current_line_y() if self.y_flipped: y = self.get_height() - 1 - y return y - + + def get_tile_for_current_line(self): + lower = self.current_line_y() < SPRITE_SIZE + if lower ^ (self.big_size and self.y_flipped): + return self.get_tile() + else: + return self.get_lower_tile() + def draw(self, lastx): - self.get_tile().draw_for_sprite(self, lastx) + self.get_tile_for_current_line().draw_for_sprite(self, lastx) # ----------------------------------------------------------------------------- From cfbolz at codespeak.net Wed Mar 4 18:50:05 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Mar 2009 18:50:05 +0100 (CET) Subject: [pypy-svn] r62542 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304175005.E60AA168516@codespeak.net> Author: cfbolz Date: Wed Mar 4 18:50:05 2009 New Revision: 62542 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: make string drawing not completely brain-dead Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 18:50:05 2009 @@ -127,19 +127,18 @@ RSDL_helper.set_pixel(self.screen, x, y, color) def draw_ascii_pixels(self): - str = "" + str = [] for y in range(self.height): - str += "\n" + str.append("\n") for x in range(self.width): if y%2 == 0 or True: - str += self.get_pixel_color(x, y, string=True) - pass - print str; + str.append(self.get_pixel_color(x, y, string=True)) + print "".join(str) @specialize.arg(3) def get_pixel_color(self, x, y, string=False): if string: - return ["#", "%", "+", " ", " "][self.get_pixel_color(x, y)] + return ["#", "%", "+", ".", " "][self.get_pixel_color(x, y)] else: return self.pixels[x+self.width*y] From tverwaes at codespeak.net Wed Mar 4 18:56:54 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 18:56:54 +0100 (CET) Subject: [pypy-svn] r62543 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304175654.C4B87168516@codespeak.net> Author: tverwaes Date: Wed Mar 4 18:56:54 2009 New Revision: 62543 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: woops Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 18:56:54 2009 @@ -26,17 +26,17 @@ def get_data_at(self, address): address %= 4 - if id == 0: + if address == 0: return self.y - if id == 1: + if address == 1: return self.x - if id == 2: + if address == 2: return self.tile_number - if id == 3: + if address == 3: return self.get_attributes_and_flags() # Making PyPy happy... - raise Exception("Cannot happen") + raise Exception(("Cannot happen: ", address)) def set_data(self, y, x, tile_number, flags): """ From fijal at codespeak.net Wed Mar 4 19:36:37 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 19:36:37 +0100 (CET) Subject: [pypy-svn] r62544 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090304183637.9CB98168518@codespeak.net> Author: fijal Date: Wed Mar 4 19:36:35 2009 New Revision: 62544 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Optimization - use _pure versions of operations when possible. optimize.py gets rid of it if it can prove that args are constant Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Wed Mar 4 19:36:35 2009 @@ -68,10 +68,10 @@ _prev = Box._extended_display try: Box._extended_display = False - #if len(self.graphs) > 1: - # graphs = self.graphs[1:] - #else: - graphs = self.graphs + if len(self.graphs) > 1: + graphs = self.graphs[1:] + else: + graphs = self.graphs for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Mar 4 19:36:35 2009 @@ -304,6 +304,20 @@ if (self.first_escaping_op and instnode.cls): instnode.expanded_fields[field] = None + def find_nodes_getarrayitem(self, op): + instnode = self.getnode(op.args[0]) + if instnode.cls is None: + instnode.cls = InstanceNode(FixedList(op.args[1].getint())) + fieldbox = op.args[2] + if self.getnode(fieldbox).const: + item = self.getsource(fieldbox).getint() + assert item >= 0 # XXX + self.find_nodes_getfield(instnode, item, op.result) + else: + instnode.escaped = True + self.nodes[op.result] = InstanceNode(op.result, + escaped=True) + ## def find_nodes_insert(self, instnode, field, fieldnode): ## for ofs, node in instnode.curfields.items(): ## if ofs >= field: @@ -369,19 +383,13 @@ ## instnode.origsize = size ## continue elif opnum == rop.GETARRAYITEM_GC: - instnode = self.getnode(op.args[0]) - if instnode.cls is None: - instnode.cls = InstanceNode(FixedList(op.args[1].getint())) - fieldbox = op.args[2] - if self.getnode(fieldbox).const: - item = self.getsource(fieldbox).getint() - assert item >= 0 # XXX - self.find_nodes_getfield(instnode, item, op.result) - else: - instnode.escaped = True - self.nodes[op.result] = InstanceNode(op.result, - escaped=True) + self.find_nodes_getarrayitem(op) continue + elif opnum == rop.GETARRAYITEM_GC_PURE: + instnode = self.getnode(op.args[0]) + if not instnode.const or not self.getnode(op.args[2]).const: + self.find_nodes_getarrayitem(op) + continue elif opnum == rop.SETARRAYITEM_GC: instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -413,6 +421,15 @@ box = op.result self.find_nodes_getfield(instnode, field, box) continue + elif opnum == rop.GETFIELD_GC_PURE: + instnode = self.getnode(op.args[0]) + fieldbox = op.args[1] + assert isinstance(fieldbox, ConstInt) + field = fieldbox.getint() + if not instnode.const: + box = op.result + self.find_nodes_getfield(instnode, field, box) + continue ## elif opname == 'getitem': ## instnode = self.getnode(op.args[1]) ## fieldbox = op.args[2] @@ -767,6 +784,12 @@ continue # otherwise we need this getfield, but it does not # invalidate caches + elif opnum == rop.GETFIELD_GC_PURE: + instnode = self.nodes[op.args[0]] + if not instnode.const: + ofs = op.args[1].getint() + if self.optimize_getfield(instnode, ofs, op.result): + continue elif opnum == rop.GETARRAYITEM_GC: instnode = self.nodes[op.args[0]] ofsbox = self.getsource(op.args[2]) @@ -774,6 +797,15 @@ ofs = ofsbox.getint() if self.optimize_getfield(instnode, ofs, op.result): continue + elif opnum == rop.GETARRAYITEM_GC_PURE: + instnode = self.nodes[op.args[0]] + ofsbox = self.getsource(op.args[2]) + if not instnode.const: + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() + if self.optimize_getfield(instnode, ofs, op.result): + continue + ## elif opname == 'getitem': ## instnode = self.nodes[op.args[1]] ## ofsbox = self.getsource(op.args[2]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Mar 4 19:36:35 2009 @@ -330,8 +330,8 @@ @arguments("box", "constbox", "box") def opimpl_getarrayitem_foldable_gc(self, arraybox, arraydesc, indexbox): tp = self.metainterp.cpu.typefor(arraydesc.getint()) - self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox], tp, - True) + self.execute(rop.GETARRAYITEM_GC_PURE, + [arraybox, arraydesc, indexbox], tp, True) @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): @@ -379,7 +379,7 @@ @arguments("box", "constbox") def opimpl_getfield_pure_gc(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_GC, [box, fielddesc], tp, True) + self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc], tp, True) @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_GC, [box, fielddesc, valuebox], From fijal at codespeak.net Wed Mar 4 20:01:50 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 20:01:50 +0100 (CET) Subject: [pypy-svn] r62545 - pypy/branch/pyjitpl5/pypy/objspace/std Message-ID: <20090304190150.85DE4168464@codespeak.net> Author: fijal Date: Wed Mar 4 20:01:49 2009 New Revision: 62545 Modified: pypy/branch/pyjitpl5/pypy/objspace/std/boolobject.py pypy/branch/pyjitpl5/pypy/objspace/std/intobject.py Log: reintroduce _immutable_ hint on Int and Bool. I think it was gone because previous JIT was unable to cope with it Modified: pypy/branch/pyjitpl5/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/objspace/std/boolobject.py (original) +++ pypy/branch/pyjitpl5/pypy/objspace/std/boolobject.py Wed Mar 4 20:01:49 2009 @@ -5,6 +5,8 @@ class W_BoolObject(W_Object): from pypy.objspace.std.booltype import bool_typedef as typedef + _immutable_ = True + def __init__(w_self, boolval): w_self.boolval = not not boolval Modified: pypy/branch/pyjitpl5/pypy/objspace/std/intobject.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/objspace/std/intobject.py (original) +++ pypy/branch/pyjitpl5/pypy/objspace/std/intobject.py Wed Mar 4 20:01:49 2009 @@ -13,6 +13,9 @@ class W_IntObject(W_Object): __slots__ = 'intval' + + _immutable_ = True + from pypy.objspace.std.inttype import int_typedef as typedef def __init__(w_self, intval): From fijal at codespeak.net Wed Mar 4 20:38:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Mar 2009 20:38:35 +0100 (CET) Subject: [pypy-svn] r62546 - in pypy/branch/pyjitpl5/pypy/jit/backend: llgraph x86 Message-ID: <20090304193835.1E4A51684B6@codespeak.net> Author: fijal Date: Wed Mar 4 20:38:33 2009 New Revision: 62546 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Implement missing ops in backends Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Wed Mar 4 20:38:33 2009 @@ -90,10 +90,13 @@ 'ooisnot' : (('ptr', 'ptr'), 'bool'), 'setfield_gc' : (('ptr', 'fieldname', 'intorptr'), None), 'getfield_gc' : (('ptr', 'fieldname'), 'intorptr'), + 'getfield_gc_pure': (('ptr', 'fieldname'), 'intorptr'), 'setfield_raw' : (('ptr', 'fieldname', 'intorptr'), None), 'getfield_raw' : (('ptr', 'fieldname'), 'intorptr'), + 'getfield_raw_pure': (('ptr', 'fieldname'), 'intorptr'), 'setarrayitem_gc' : (('ptr', 'int', 'int', 'intorptr'), None), 'getarrayitem_gc' : (('ptr', 'int', 'int'), 'intorptr'), + 'getarrayitem_gc_pure' : (('ptr', 'int', 'int'), 'intorptr'), 'arraylen_gc' : (('ptr', 'int'), 'int'), 'call_ptr' : (('ptr', 'varargs'), 'ptr'), 'call__4' : (('ptr', 'varargs'), 'int'), @@ -723,12 +726,16 @@ ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) return getattr(ptr, fieldname) + op_getfield_gc_pure = op_getfield_gc + def op_getfield_raw(self, intval, fielddesc): STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] ptr = llmemory.cast_adr_to_ptr(cast_int_to_adr(self.memocast, intval), lltype.Ptr(STRUCT)) return getattr(ptr, fieldname) + op_getfield_raw_pure = op_getfield_raw + def _cast_newvalue(self, desc, TYPE, newvalue): if desc % 2: newvalue = lltype.cast_opaque_ptr(TYPE, newvalue) @@ -760,6 +767,8 @@ array = array._obj.container return array.getitem(index) + op_getarrayitem_gc_pure = op_getarrayitem_gc + def op_arraylen_gc(self, array, arraydesc): array = array._obj.container return array.getlength() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Wed Mar 4 20:38:33 2009 @@ -358,6 +358,8 @@ else: raise NotImplementedError("getfield size = %d" % size) + genop_getfield_gc_pure = genop_getfield_gc + def genop_getarrayitem_gc(self, op, arglocs, resloc): base_loc, ofs_loc, scale, ofs = arglocs assert isinstance(ofs, IMM32) @@ -365,6 +367,7 @@ self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, ofs.value, scale.value)) genop_getfield_raw = genop_getfield_gc + genop_getarrayitem_gc_pure = genop_getarrayitem_gc def genop_setfield_gc(self, op, arglocs): base_loc, ofs_loc, size_loc, value_loc = arglocs Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Wed Mar 4 20:38:33 2009 @@ -828,6 +828,8 @@ return (ops0 + more_ops + [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) + consider_getfield_gc_pure = consider_getfield_gc + def consider_getarrayitem_gc(self, op, ignored): scale, ofs = self._unpack_arraydescr(op.args[1].getint()) args = [op.args[0], op.args[2]] @@ -840,7 +842,7 @@ result_loc)]) consider_getfield_raw = consider_getfield_gc - + consider_getarrayitem_gc_pure = consider_getarrayitem_gc def _consider_listop(self, op, ignored): return self._call(op, [self.loc(arg) for arg in op.args]) From tverwaes at codespeak.net Wed Mar 4 22:41:55 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 22:41:55 +0100 (CET) Subject: [pypy-svn] r62548 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304214155.5D190168540@codespeak.net> Author: tverwaes Date: Wed Mar 4 22:41:54 2009 New Revision: 62548 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: the background is supposed to automatically wrap around. Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 22:41:54 2009 @@ -9,6 +9,7 @@ import time use_rsdl = True +# use_rsdl = False if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi @@ -118,6 +119,7 @@ RSDL.UnlockSurface(self.screen) RSDL.Flip(self.screen) else: + print '\x1b[H\x1b[2J' self.draw_ascii_pixels() def draw_pixels(self): Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 22:41:54 2009 @@ -287,10 +287,9 @@ self.video.line[x] = 0x00 def draw_line(self, line_y): - y = self.scroll_y + line_y + y = (self.scroll_y + line_y) & 0xFF x = self.scroll_x tile_map = self.get_tile_map_space() tile_group = tile_map[y >> 3] - # print "Background" self.video.draw_tiles(8 - (x % 8), tile_group, y, x >> 3) From tverwaes at codespeak.net Wed Mar 4 23:18:32 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 23:18:32 +0100 (CET) Subject: [pypy-svn] r62549 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304221832.3DE2B168529@codespeak.net> Author: tverwaes Date: Wed Mar 4 23:18:31 2009 New Revision: 62549 Modified: pypy/trunk/pypy/lang/gameboy/constants.py Log: all times were totally off... Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Wed Mar 4 23:18:31 2009 @@ -167,7 +167,7 @@ JOYP = 0xFF00 # Joypad Poll Speed (64 Hz) -JOYPAD_CLOCK = GAMEBOY_CLOCK >> 6 +JOYPAD_CLOCK = 1<<5 BUTTON_DOWN = 0x08 BUTTON_UP = 0x04 @@ -184,10 +184,10 @@ # ___________________________________________________________________________ # Serial Clock Speed (8 x 1024 bits/sec) -SERIAL_CLOCK = GAMEBOY_CLOCK >> 16 +SERIAL_CLOCK = 1<<13 # Serial Idle Speed (128 Hz) -SERIAL_IDLE_CLOCK = GAMEBOY_CLOCK >> 7 +SERIAL_IDLE_CLOCK = 1<<7 # Serial Register Addresses SERIAL_TRANSFER_DATA = 0xFF01 @@ -198,7 +198,7 @@ # ___________________________________________________________________________ # Sound Clock (256 Hz) -SOUND_CLOCK = 256 +SOUND_CLOCK = 1<<8 # Sound Register Addresses NR10 = 0xFF10 # AUD1SWEEP @@ -236,14 +236,14 @@ # ___________________________________________________________________________ # DIV Timer Speed (16384 Hz) -DIV_CLOCK = GAMEBOY_CLOCK >> 14 +DIV_CLOCK = 1 << 14 # Timer Clock Speeds (4096, 262144, 65536 and 16384 Hz) TIMER_CLOCK = [ - GAMEBOY_CLOCK >> 12, - GAMEBOY_CLOCK >> 18, - GAMEBOY_CLOCK >> 16, - GAMEBOY_CLOCK >> 14 + 1 << 12, + 1 << 18, + 1 << 16, + 1 << 14 ] # Timer Register Addresses From tverwaes at codespeak.net Wed Mar 4 23:54:49 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 4 Mar 2009 23:54:49 +0100 (CET) Subject: [pypy-svn] r62550 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090304225449.75CD2168514@codespeak.net> Author: tverwaes Date: Wed Mar 4 23:54:48 2009 New Revision: 62550 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: propagating penalties Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 4 23:54:48 2009 @@ -23,6 +23,7 @@ def __init__(self): GameBoy.__init__(self) self.is_running = False + self.penalty = 0.0 if use_rsdl: self.init_sdl() @@ -60,11 +61,13 @@ # if use_rsdl: # RSDL.Delay(100) spent = time.time() - start_time - left = (1.0/X) - spent + left = (1.0/X) + self.penalty - spent if left > 0: time.sleep(left) + self.penalty = 0.0 else: - print "WARNING: Going too slow: ", spent, " ", left + self.penalty = left + # print "WARNING: Going too slow: ", spent, " ", left def handle_execution_error(self, error): Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Wed Mar 4 23:54:48 2009 @@ -444,7 +444,7 @@ self.driver.update_display() def clear_frame(self): - self.clear_pixels() + self.driver.clear_pixels() self.driver.update_display() def draw_line(self): @@ -490,18 +490,6 @@ self.shown_sprites[index], self.shown_sprites[highest] = \ self.shown_sprites[highest], self.shown_sprites[index] - def draw_tiles(self, x_start, tile_group, y, group_index=0): - x = x_start - tile_data = self.control.get_selected_tile_data_space() - while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: - tile_index = tile_group[group_index % TILE_GROUP_SIZE] - if not self.control.background_and_window_lower_tile_data_selected: - tile_index ^= 0x80 - tile = tile_data[tile_index] - tile.draw(x, y) - group_index += 1 - x += SPRITE_SIZE - def draw_pixels_line(self): self.update_palette() pixels = self.driver.get_pixels() @@ -509,9 +497,6 @@ for x in range(SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE): pixels[offset + x] = self.palette[self.line[x]] - def clear_pixels(self): - self.driver.clear_pixels() - def update_palette(self): if not self.dirty: return # bit 4/0 = BG color, Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Wed Mar 4 23:54:48 2009 @@ -1,7 +1,5 @@ -from pypy.lang.gameboy import constants -from pypy.lang.gameboy.constants import SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH, \ - GAMEBOY_SCREEN_HEIGHT +from pypy.lang.gameboy.constants import * # ----------------------------------------------------------------------------- @@ -51,14 +49,14 @@ """ extracts the sprite data from an oam entry """ - position = address % 4 - if position == 0: + address %= 4 + if address == 0: self.extract_y_position(data) - if position == 1: + if address == 1: self.extract_x_position(data) - if position == 2: + if address == 2: self.extract_tile_number(data) - if position == 3: + if address == 3: self.extract_attributes_and_flags(data) def extract_y_position(self, data): @@ -161,7 +159,7 @@ return self.video.get_tile_at(self.get_tile_address()) def get_lower_tile(self): - return self.video.get_tile_at(self.get_tile_address()+1) + return self.video.get_tile_at(self.get_tile_address() + 1) def get_draw_y(self): y = self.current_line_y() @@ -245,7 +243,18 @@ def reset(self): raise Exception("Not implemented") - + + def draw_tiles(self, x_start, tile_group, y, group_index=0): + x = x_start + tile_data = self.video.control.get_selected_tile_data_space() + while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: + tile_index = tile_group[group_index % TILE_GROUP_SIZE] + if not self.video.control.background_and_window_lower_tile_data_selected: + tile_index ^= 0x80 + tile = tile_data[tile_index] + tile.draw(x, y) + group_index += 1 + x += SPRITE_SIZE class Window(Drawable): @@ -267,7 +276,7 @@ tile_map = self.get_tile_map_space() tile_group = tile_map[self.line_y >> 5] - self.video.draw_tiles(self.x + 1, tile_group, self.line_y) + self.draw_tiles(self.x + 1, tile_group, self.line_y) self.line_y += 1 # ----------------------------------------------------------------------------- @@ -292,4 +301,4 @@ tile_map = self.get_tile_map_space() tile_group = tile_map[y >> 3] - self.video.draw_tiles(8 - (x % 8), tile_group, y, x >> 3) + self.draw_tiles(8 - (x % 8), tile_group, y, x >> 3) From tverwaes at codespeak.net Thu Mar 5 02:19:02 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 5 Mar 2009 02:19:02 +0100 (CET) Subject: [pypy-svn] r62552 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305011902.B79A1168540@codespeak.net> Author: tverwaes Date: Thu Mar 5 02:19:00 2009 New Revision: 62552 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_register.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: moving around some code and cleaning up. tiles don't need pointers to video if they get the line as an argument Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Thu Mar 5 02:19:00 2009 @@ -10,6 +10,8 @@ use_rsdl = True # use_rsdl = False +use_tile_screen = True + if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi @@ -109,14 +111,24 @@ def __init__(self): VideoDriver.__init__(self) self.create_screen() + #self.create_tile_screen() self.map = [] - + + #def create_tile_screen(self): + # if use_rsdl and use_tile_screen: + # self.tile_screen = RSDL.SetVideoMode(128, 128, 32, 0) + def create_screen(self): if use_rsdl: self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): if use_rsdl: + # if use_tile_screen: + # RSDL.LockSurface(self.tile_screen) + # self.draw_tile_pixels() + # RSDL.UnlockSurface(self.tile_screen) + # RSDL.Flip(self.tile_screen) RSDL.LockSurface(self.screen) self.draw_pixels() RSDL.UnlockSurface(self.screen) @@ -130,6 +142,13 @@ for x in range(self.width): color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] RSDL_helper.set_pixel(self.screen, x, y, color) + + def draw_tile_pixels(self): + for y in range(128): + for x in range(128): + #color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] + #RSDL_helper.set_pixel(self.screen, x, y, color) + pass def draw_ascii_pixels(self): str = [] Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Thu Mar 5 02:19:00 2009 @@ -52,7 +52,7 @@ self.tile_data = [self.tile_data_0, self.tile_data_1] def create_tile_data(self): - return [Tile(i, self) for i in range(TILE_DATA_SIZE / 2)] + return [Tile() for i in range(TILE_DATA_SIZE / 2)] def update_tile(self, address, data): self.get_tile(address).set_data_at(address, data); @@ -77,6 +77,12 @@ tile_group = map[tile_map_index >> 5] return tile_group, tile_map_index & 0x1F + def get_selected_tile_data_space(self): + if self.control.background_and_window_lower_tile_data_selected: + return self.tile_data_0 + else: + return self.tile_data_1 + def get_tile_map(self, address): tile_group, group_index = self.select_tile_group_for(address) return tile_group[group_index] Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Thu Mar 5 02:19:00 2009 @@ -145,9 +145,3 @@ if previous_big_sprites != self.big_sprites: self.video.update_sprite_size() - - def get_selected_tile_data_space(self): - if self.background_and_window_lower_tile_data_selected: - return self.video.tile_data_0 - else: - return self.video.tile_data_1 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Thu Mar 5 02:19:00 2009 @@ -118,16 +118,15 @@ return value def hide_check(self): - if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: + if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: self.hidden = True - elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: + elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: self.hidden = True else: self.hidden = False return self.hidden def get_tile_number(self): - #return self.tile.id return self.tile_number def get_width(self): @@ -175,22 +174,20 @@ return self.get_lower_tile() def draw(self, lastx): - self.get_tile_for_current_line().draw_for_sprite(self, lastx) + self.get_tile_for_current_line().draw_for_sprite(self, self.video.line, lastx) # ----------------------------------------------------------------------------- class Tile(object): - def __init__(self, number, video): - self.video = video - self.number = number + def __init__(self): self.data = [0x00 for i in range(2*SPRITE_SIZE)] - def draw(self, x, y): + def draw(self, line, x, y): pattern = self.get_pattern_at(y << 1) for i in range(SPRITE_SIZE): value = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 - self.video.line[x + i] = value + line[x + i] = value def set_tile_data(self, data): self.data = data @@ -208,7 +205,7 @@ return self.get_data_at(address) +\ (self.get_data_at(address + 1) << 8) - def draw_for_sprite(self, sprite, lastx): + def draw_for_sprite(self, sprite, line, lastx): if sprite.x_flipped: convert, offset = 1, 0 # 0-7 else: @@ -225,8 +222,8 @@ if bool(color): if sprite.x + SPRITE_SIZE > lastx: # Overlapped. - self.video.line[x] &= 0x0101 - self.video.line[x] |= color | mask + line[x] &= 0x0101 + line[x] |= color | mask # ----------------------------------------------------------------------------- @@ -246,13 +243,13 @@ def draw_tiles(self, x_start, tile_group, y, group_index=0): x = x_start - tile_data = self.video.control.get_selected_tile_data_space() + tile_data = self.video.get_selected_tile_data_space() while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: tile_index = tile_group[group_index % TILE_GROUP_SIZE] if not self.video.control.background_and_window_lower_tile_data_selected: tile_index ^= 0x80 tile = tile_data[tile_index] - tile.draw(x, y) + tile.draw(self.video.line, x, y) group_index += 1 x += SPRITE_SIZE From fijal at codespeak.net Thu Mar 5 08:31:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 08:31:17 +0100 (CET) Subject: [pypy-svn] r62553 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305073117.B45F3168500@codespeak.net> Author: fijal Date: Thu Mar 5 08:31:15 2009 New Revision: 62553 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: update the comment Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Thu Mar 5 08:31:15 2009 @@ -4,26 +4,24 @@ from pypy.module.pypyjit.portal import PyPyJitPolicy -# Current output: http://paste.pocoo.org/show/105784/ +# Current output: http://paste.pocoo.org/show/106540/ # # Some optimizations missing: # -# - improve the optimization: e.g. ooisnull followed by oononnull -# on the same variable -# -# - reintroduce some delayed list optimizations to remove this -# mess of push/pop on the stack -# # - remove the useless 'ec' argument (p1 and p115 in the trace) # -# - figure out who calls W_TypeObject.is_heaptype(), leading to -# the "int_and 512" (lines 48, 147, 154) -# # - the guards have very long 'liveboxes' lists containing mostly # Consts -- make sure that these Consts are not stored, or else # remove them entirely + +# Some optimizations that might help under different circumstances: +# +# - figure out who calls W_TypeObject.is_heaptype(), leading to +# the "int_and 512" (lines 48, 147, 154) +# +# - improve the optimization: e.g. ooisnull followed by oononnull +# on the same variable # -# - dead operation removal: e.g. unused 'getfield_gc' (line 158) def run_child(glob, loc): From fijal at codespeak.net Thu Mar 5 09:12:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 09:12:17 +0100 (CET) Subject: [pypy-svn] r62554 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090305081217.9857B16853B@codespeak.net> Author: fijal Date: Thu Mar 5 09:12:14 2009 New Revision: 62554 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: a passing test (just because) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Thu Mar 5 09:12:14 2009 @@ -190,6 +190,29 @@ assert res == 0 self.check_loops(getfield_gc=0) + def test_escapes(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) + + class Node(object): + def __init__(self, x): + self.x = x + + def g(x): + pass + + def f(n): + node = Node(3) + while n > 0: + myjitdriver.can_enter_jit(n=n, node=node) + myjitdriver.jit_merge_point(n=n, node=node) + g(node) + node = Node(3) + n -= 1 + return node.x + + res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) + assert res == 3 + ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) From cami at codespeak.net Thu Mar 5 09:24:30 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 09:24:30 +0100 (CET) Subject: [pypy-svn] r62555 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090305082430.731C016851C@codespeak.net> Author: cami Date: Thu Mar 5 09:24:29 2009 New Revision: 62555 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/sound.py pypy/trunk/pypy/lang/gameboy/test/test_joypad.py Log: fixing joypad tests small refactoring in sound Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Thu Mar 5 09:24:29 2009 @@ -8,8 +8,7 @@ from pypy.lang.gameboy import constants import time -use_rsdl = True -# use_rsdl = False +use_rsdl = False use_tile_screen = True if use_rsdl: Modified: pypy/trunk/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/sound.py (original) +++ pypy/trunk/pypy/lang/gameboy/sound.py Thu Mar 5 09:24:29 2009 @@ -9,130 +9,149 @@ class Channel(object): - audio_index = 0 - audio_length = 0 - audio_frequency = 0 + index = 0 + length = 0 + frequency = 0 def __init__(self, sample_rate, frequency_table): self.sample_rate = int(sample_rate) self.frequency_table = frequency_table - self.audio_length = 0 - self.audio_envelope = 0 - self.audio_frequency = 0 - self.audio_playback = 0 + self.length = 0 + self.envelope = 0 + self.frequency = 0 + self.playback = 0 self.nr0 = 0 self.nr1 = 0 self.nr2 = 0 self.nr4 = 0 self.nr3 = 0 - self.audio_index = 0 - self.audio_length = 0 - self.audio_frequency = 0 + self.index = 0 + self.length = 0 + self.frequency = 0 self.enabled = False #XXX need to push this up into the Sound class self.output_enable = False def reset(self): - self.audio_index = 0 + self.index = 0 + self.set_length(0xFF) + self.set_playback(0xBF) - def get_audio_length(self): - return self.audio_length + def get_length(self): + return self.length + + def set_length(self, length): + self.length = length - def get_audio_envelope(self): - return self.audio_envelope + def get_envelope(self): + return self.envelope - def get_audio_frequency(self): - return self.audio_frequency + def get_frequency(self): + return self.frequency - def get_audio_playback(self): - return self.audio_playback + def get_playback(self): + return self.playback + + def set_playback(self, playback): + self.playback = playback # ------------------------------------------------------------------------------ #SquareWaveGenerator -class Channel1(Channel): +class SquareWaveChannel(Channel): # Audio Channel 1 int def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) self.sample_sweep = 0 - self.audio_1_index = 0 - self.audio_1_length = 0 - self.audio_volume = 0 - self.audio_1_envelope_length = 0 + self.index = 0 + self.length = 0 + self.volume = 0 + self.envelope_length = 0 self.sample_sweep_length = 0 - self.audio_1_frequency = 0 + self.frequency = 0 + def reset(self): + Channel.reset(self) + self.set_sweep(0x80) + self.set_length(0x3F) + self.set_envelope(0x00) + self.set_frequency(0xFF) + + # Audio Channel 1 - def get_audio_sweep(self): + def get_sweep(self): return self.sample_sweep - def set_audio_sweep(self, data): + def set_sweep(self, data): self.sample_sweep = data self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) - def set_audio_length(self, data): - self.audio_length = data - self.audio_1_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) - - def set_audio_envelope(self, data): - self.audio_envelope = data - if (self.audio_playback & 0x40) != 0: - return - if (self.audio_envelope >> 4) == 0: - self.audio_volume = 0 - elif self.audio_1_envelope_length == 0 and \ - (self.audio_envelope & 0x07) == 0: - self.audio_volume = (self.audio_volume + 1) & 0x0F + def set_length(self, data): + self.length = data + self.length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.length & 0x3F)) + + def set_envelope(self, data): + self.envelope = data + if (self.playback & 0x40) != 0: + return + if (self.envelope >> 4) == 0: + self.volume = 0 + elif self.envelope_length == 0 and \ + (self.envelope & 0x07) == 0: + self.volume = (self.volume + 1) & 0x0F else: - self.audio_volume = (self.audio_volume + 2) & 0x0F + self.volume = (self.volume + 2) & 0x0F + - def set_audio_frequency(self, data): - self.audio_frequency = data - index = self.audio_frequency + ((self.audio_playback & 0x07) << 8) - self.audio_1_frequency = self.frequency_table[index] - - def set_audio_playback(self, data): - self.audio_playback = data - self.audio_1_frequency = self.frequency_table[self.audio_frequency - + ((self.audio_playback & 0x07) << 8)] - if (self.audio_playback & 0x80) != 0: + def set_frequency(self, data): + self.frequency = data + index = self.frequency + ((self.playback & 0x07) << 8) + self.frequency = self.frequency_table[index] + + + def set_playback(self, data): + self.playback = data + index = self.frequency + ((self.playback & 0x07) << 8) + self.frequency = self.frequency_table[index] + if (self.playback & 0x80) != 0: self.enabled = True - if (self.audio_playback & 0x40) != 0 and self.audio_1_length == 0: - self.audio_1_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) + if (self.playback & 0x40) != 0 and self.length == 0: + self.length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.length & 0x3F)) self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) - self.audio_volume = self.audio_envelope >> 4 - self.audio_1_envelope_length = (constants.SOUND_CLOCK / 64) * \ - (self.audio_envelope & 0x07) - + self.volume = self.envelope >> 4 + self.envelope_length = (constants.SOUND_CLOCK / 64) * \ + (self.envelope & 0x07) + def update_audio(self): self.update_enable() self.update_volume_and_envelope() self.update_frequency_and_playback() + def update_enable(self): - if (self.audio_playback & 0x40) != 0 and self.audio_1_length > 0: - self.audio_1_length-=1 - if self.audio_1_length <= 0: + if (self.playback & 0x40) != 0 and self.length > 0: + self.length-=1 + if self.length <= 0: self.enabled = False - + def update_volume_and_envelope(self): - if self.audio_1_envelope_length <= 0: + if self.envelope_length <= 0: return - self.audio_1_envelope_length -= 1 - if self.audio_1_envelope_length <= 0: - if (self.audio_envelope & 0x08) != 0: - if (self.audio_volume < 15): - self.audio_volume += 1 - elif self.audio_volume > 0: - self.audio_volume -= 1 - self.audio_1_envelope_length += (constants.SOUND_CLOCK / 64) * \ - (self.audio_envelope & 0x07) + self.envelope_length -= 1 + if self.envelope_length <= 0: + if (self.envelope & 0x08) != 0: + if (self.volume < 15): + self.volume += 1 + elif self.volume > 0: + self.volume -= 1 + self.envelope_length += (constants.SOUND_CLOCK / 64) * \ + (self.envelope & 0x07) def update_frequency_and_playback(self): if self.sample_sweep_length <= 0: @@ -142,19 +161,19 @@ return sweep_steps = (self.sample_sweep & 0x07) if sweep_steps != 0: - frequency = ((self.audio_playback & 0x07) << 8) + \ - self.audio_frequency + frequency = ((self.playback & 0x07) << 8) + \ + self.frequency if (self.sample_sweep & 0x08) != 0: frequency -= frequency >> sweep_steps else: frequency += frequency >> sweep_steps if frequency < 2048: - self.audio_1_frequency = self.frequency_table[frequency] - self.audio_frequency = frequency & 0xFF - self.audio_playback = (self.audio_playback & 0xF8) + \ + self.frequency = self.frequency_table[frequency] + self.frequency = frequency & 0xFF + self.playback = (self.playback & 0xF8) + \ ((frequency >> 8) & 0x07) else: - self.audio_1_frequency = 0 + self.frequency = 0 self.output_enable &= ~0x01 self.sample_sweep_length += (constants.SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) @@ -162,200 +181,112 @@ def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 3): - self.audio_1_index += self.audio_1_frequency - if (self.audio_1_index & (0x1F << 22)) >= wave_pattern: + self.index += self.frequency + if (self.index & (0x1F << 22)) >= wave_pattern: + # output_terminal & 0x20 for the second SquareWaveChannel if (output_terminal & 0x10) != 0: - buffer[index + 0] -= self.audio_volume + buffer[index + 0] -= self.volume if (output_terminal & 0x01) != 0: - buffer[index + 1] -= self.audio_volume + buffer[index + 1] -= self.volume else: if (output_terminal & 0x10) != 0: - buffer[index + 0] += self.audio_volume + buffer[index + 0] += self.volume if (output_terminal & 0x01) != 0: - buffer[index + 1] += self.audio_volume + buffer[index + 1] += self.volume def get_current_wave_pattern(self): wave_pattern = 0x18 - if (self.audio_length & 0xC0) == 0x00: + if (self.length & 0xC0) == 0x00: wave_pattern = 0x04 - elif (self.audio_length & 0xC0) == 0x40: + elif (self.length & 0xC0) == 0x40: wave_pattern = 0x08 - elif (self.audio_length & 0xC0) == 0x80: + elif (self.length & 0xC0) == 0x80: wave_pattern = 0x10 return wave_pattern << 22 - - -#SquareWaveGenerator -class Channel2(Channel): +# --------------------------------------------------------------------------- + +class VoluntaryWaveChannel(Channel): def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) - self.audio_2_index = 0 - self.audio_2_length = 0 - self.audio_volume = 0 - self.audio_2_envelope_length = 0 - self.audio_2_frequency = 0 - - # Audio Channel 2 - def set_audio_length(self, data): - self.audio_length = data - self.audio_2_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) - - def set_audio_envelope(self, data): - self.audio_envelope = data - if (self.audio_playback & 0x40) == 0: - if (self.audio_envelope >> 4) == 0: - self.audio_volume = 0 - elif self.audio_2_envelope_length == 0 and \ - (self.audio_envelope & 0x07) == 0: - self.audio_volume = (self.audio_volume + 1) & 0x0F - else: - self.audio_volume = (self.audio_volume + 2) & 0x0F - - def set_audio_frequency(self, data): - self.audio_frequency = data - self.audio_2_frequency = self.frequency_table[self.audio_frequency\ - + ((self.audio_playback & 0x07) << 8)] - - def set_audio_playback(self, data): - self.audio_playback = data - self.audio_2_frequency = self.frequency_table[self.audio_frequency\ - + ((self.audio_playback & 0x07) << 8)] - if (self.audio_playback & 0x80) != 0: - self.enabled = True - if (self.audio_playback & 0x40) != 0 and self.audio_2_length == 0: - self.audio_2_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) - self.audio_volume = self.audio_envelope >> 4 - self.audio_2_envelope_length = (constants.SOUND_CLOCK / 64) * \ - (self.audio_envelope & 0x07) + self.enable = 0 + self.level = 0 + self.index = 0 + self.length = 0 + self.frequency = 0 + self.wave_pattern = [0]*16 - def update_audio(self): - self.update_enable() - self.update_volume_and_envelope() + def reset(self): + Channel.reset(self) + self.set_enable(0x7F) + self.set_length(0xFF) + self.set_level(0x9F) + self.set_frequency(0xFF) + self.set_playback(0xBF) - def update_enable(self): - if (self.audio_playback & 0x40) != 0 and self.audio_2_length > 0: - self.audio_2_length-=1 - if self.audio_2_length <= 0: - self.enabled = False - - def update_volume_and_envelope(self): - if self.audio_2_envelope_length <= 0: - return - self.audio_2_envelope_length-=1 - if self.audio_2_envelope_length > 0: - return - if (self.audio_envelope & 0x08) != 0: - if self.audio_volume < 15: - self.audio_volume+=1 - elif self.audio_volume > 0: - self.audio_volume-=1 - self.audio_2_envelope_length += (constants.SOUND_CLOCK / 64) *\ - (self.audio_envelope & 0x07) - def mix_audio(self, buffer, length, output_terminal): - wave_pattern = self.get_current_wave_pattern() - for index in range(0, length): - self.audio_2_index += self.audio_2_frequency - if (self.audio_2_index & (0x1F << 22)) >= wave_pattern: - if (output_terminal & 0x20) != 0: - buffer[index + 0] -= self.audio_volume - if (output_terminal & 0x02) != 0: - buffer[index + 1] -= self.audio_volume - else: - if (output_terminal & 0x20) != 0: - buffer[index + 0] += self.audio_volume - if (output_terminal & 0x02) != 0: - buffer[index + 1] += self.audio_volume - - def get_current_wave_pattern(self): - wave_pattern = 0x18 - if (self.audio_length & 0xC0) == 0x00: - wave_pattern = 0x04 - elif (self.audio_length & 0xC0) == 0x40: - wave_pattern = 0x08 - elif (self.audio_length & 0xC0) == 0x80: - wave_pattern = 0x10 - return wave_pattern << 22 - - - -#SquareWaveGenerator -class Channel3(Channel): + def get_enable(self): + return self.enable - def __init__(self, sample_rate, frequency_table): - Channel.__init__(self, sample_rate, frequency_table) - self.audio_enable = 0 - self.audio_level = 0 - self.audio_3_index = 0 - self.audio_3_length = 0 - self.audio_3_frequency = 0 - self.audio_wave_pattern = [0]*16 - - def get_audio_enable(self): - return self.audio_enable - - def get_audio_level(self): - return self.audio_level + def get_level(self): + return self.level #FIXME strange number here - def get_audio_4_frequency(self): - return self.audio_frequency + def get_frequency(self): + return self.frequency - def set_audio_enable(self, data): - self.audio_enable = data & 0x80 - if (self.audio_enable & 0x80) == 0: + def set_enable(self, data): + self.enable = data & 0x80 + if (self.enable & 0x80) == 0: self.enabled = False - def set_audio_length(self, data): - self.audio_length = data - self.audio_3_length = (constants.SOUND_CLOCK / 256) * \ - (256 - self.audio_length) - - def set_audio_level(self, data): - self.audio_level = data - - def set_audio_frequency(self, data): - self.audio_frequency = data - index = ((self.audio_playback & 0x07) << 8) + self.audio_frequency - self.audio_3_frequency = self.frequency_table[index] >> 1 - - def set_audio_playback(self, data): - self.audio_playback = data - index = ((self.audio_playback & 0x07) << 8) + self.audio_frequency - self.audio_3_frequency = self.frequency_table[index] >> 1 - if (self.audio_playback & 0x80) != 0 and (self.audio_enable & 0x80) != 0: + def set_length(self, data): + self.length = data + self.length = (constants.SOUND_CLOCK / 256) * \ + (256 - self.length) + + def set_level(self, data): + self.level = data + + def set_frequency(self, data): + self.frequency = data + index = ((self.playback & 0x07) << 8) + self.frequency + self.frequency = self.frequency_table[index] >> 1 + + def set_playback(self, data): + self.playback = data + index = ((self.playback & 0x07) << 8) + self.frequency + self.frequency = self.frequency_table[index] >> 1 + if (self.playback & 0x80) != 0 and (self.enable & 0x80) != 0: self.enabled = True - if (self.audio_playback & 0x40) != 0 and self.audio_3_length == 0: - self.audio_3_length = (constants.SOUND_CLOCK / 256) *\ - (256 - self.audio_length) + if (self.playback & 0x40) != 0 and self.length == 0: + self.length = (constants.SOUND_CLOCK / 256) *\ + (256 - self.length) - def set_audio_wave_pattern(self, address, data): - self.audio_wave_pattern[address & 0x0F] = data + def set_wave_pattern(self, address, data): + self.wave_pattern[address & 0x0F] = data - def get_audio_wave_pattern(self, address): - return self.audio_wave_pattern[address & 0x0F] & 0xFF + def get_wave_pattern(self, address): + return self.wave_pattern[address & 0x0F] & 0xFF def update_audio(self): - if (self.audio_playback & 0x40) != 0 and self.audio_3_length > 0: - self.audio_3_length-=1 - if self.audio_3_length <= 0: + if (self.playback & 0x40) != 0 and self.length > 0: + self.length-=1 + if self.length <= 0: self.output_enable &= ~0x04 def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 2): - self.audio_3_index += self.audio_3_frequency - sample = self.audio_wave_pattern[(self.audio_3_index >> 23) & 0x0F] - if ((self.audio_3_index & (1 << 22)) != 0): + self.index += self.frequency + sample = self.wave_pattern[(self.index >> 23) & 0x0F] + if ((self.index & (1 << 22)) != 0): sample = (sample >> 0) & 0x0F else: sample = (sample >> 4) & 0x0F - sample = int(((sample - 8) << 1) >> self.audio_level) + sample = int(((sample - 8) << 1) >> self.level) if (output_terminal & 0x40) != 0: buffer[index + 0] += sample if (output_terminal & 0x04) != 0: @@ -363,30 +294,38 @@ def get_current_wave_pattern(self): wave_pattern = 2 - if (self.audio_level & 0x60) == 0x00: + if (self.level & 0x60) == 0x00: wave_pattern = 8 - elif (self.audio_level & 0x60) == 0x40: + elif (self.level & 0x60) == 0x40: wave_pattern = 0 - elif (self.audio_level & 0x60) == 0x80: + elif (self.level & 0x60) == 0x80: wave_pattern = 1 return wave_pattern - +# --------------------------------------------------------------------------- + class NoiseGenerator(Channel): def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) # Audio Channel 4 int - self.audio_length = 0 - self.audio_polynomial = 0 - self.audio_4_index = 0 - self.audio_4_length = 0 - self.audio_volume = 0 - self.audio_4_envelope_length = 0 - self.audio_4_frequency = 0 + self.length = 0 + self.polynomial = 0 + self.index = 0 + self.length = 0 + self.volume = 0 + self.envelope_length = 0 + self.frequency = 0 self.generate_noise_frequency_ratio_table() self.generate_noise_tables() + def reset(self): + Channel.reset(self) + self.set_length(0xFF) + self.set_envelope(0x00) + self.set_polynomial(0x00) + self.set_playback(0xBF) + def generate_noise_frequency_ratio_table(self): # Polynomial Noise Frequency Ratios # 4194304 Hz * 1 / 2^3 * 2 4194304 Hz * 1 / 2^3 * 1 4194304 Hz * 1 / 2^3 * @@ -431,101 +370,101 @@ (index & 31) # Audio Channel 4 - def get_audio_length(self): - return self.audio_length + def get_length(self): + return self.length - def get_audio_polynomial(self): - return self.audio_polynomial + def get_polynomial(self): + return self.polynomial - def get_audio_playback(self): - return self.audio_playback + def get_playback(self): + return self.playback - def set_audio_length(self, data): - self.audio_length = data - self.audio_4_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) - - def set_audio_envelope(self, data): - self.audio_envelope = data - if (self.audio_playback & 0x40) is not 0: - return - if (self.audio_envelope >> 4) == 0: - self.audio_volume = 0 - elif self.audio_4_envelope_length == 0 and \ - (self.audio_envelope & 0x07) == 0: - self.audio_volume = (self.audio_volume + 1) & 0x0F + def set_length(self, data): + self.length = data + self.length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.length & 0x3F)) + + def set_envelope(self, data): + self.envelope = data + if (self.playback & 0x40) is not 0: + return + if (self.envelope >> 4) == 0: + self.volume = 0 + elif self.envelope_length == 0 and \ + (self.envelope & 0x07) == 0: + self.volume = (self.volume + 1) & 0x0F else: - self.audio_volume = (self.audio_volume + 2) & 0x0F + self.volume = (self.volume + 2) & 0x0F - def set_audio_polynomial(self, data): - self.audio_polynomial = data - if (self.audio_polynomial >> 4) <= 12: - freq = self.noiseFreqRatioTable[self.audio_polynomial & 0x07] - self.audio_4_frequency = freq >> ((self.audio_polynomial >> 4) + 1) + def set_polynomial(self, data): + self.polynomial = data + if (self.polynomial >> 4) <= 12: + freq = self.noiseFreqRatioTable[self.polynomial & 0x07] + self.frequency = freq >> ((self.polynomial >> 4) + 1) else: - self.audio_4_frequency = 0 + self.frequency = 0 - def set_audio_playback(self, data): - self.audio_playback = data - if (self.audio_playback & 0x80) == 0: + def set_playback(self, data): + self.playback = data + if (self.playback & 0x80) == 0: return self.enabled = True - if (self.audio_playback & 0x40) != 0 and self.audio_4_length == 0: - self.audio_4_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) - self.audio_volume = self.audio_envelope >> 4 - self.audio_4_envelope_length = (constants.SOUND_CLOCK / 64) * \ - (self.audio_envelope & 0x07) - self.audio_4_index = 0 + if (self.playback & 0x40) != 0 and self.length == 0: + self.length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.length & 0x3F)) + self.volume = self.envelope >> 4 + self.envelope_length = (constants.SOUND_CLOCK / 64) * \ + (self.envelope & 0x07) + self.index = 0 def update_audio(self): self.update_enabled() self.update_envelope_and_volume() def update_enabled(self): - if (self.audio_playback & 0x40) != 0 and self.audio_4_length > 0: - self.audio_4_length-=1 - if self.audio_4_length <= 0: + if (self.playback & 0x40) != 0 and self.length > 0: + self.length-=1 + if self.length <= 0: self.output_enable &= ~0x08 def update_envelope_and_volume(self): - if self.audio_4_envelope_length <= 0: + if self.envelope_length <= 0: return - self.audio_4_envelope_length-=1 - if self.audio_4_envelope_length > 0: + self.envelope_length-=1 + if self.envelope_length > 0: return - if (self.audio_envelope & 0x08) != 0: - if self.audio_volume < 15: - self.audio_volume+=1 - elif self.audio_volume > 0: - self.audio_volume-=1 - self.audio_4_envelope_length += (constants.SOUND_CLOCK / 64) *\ - (self.audio_envelope & 0x07) + if (self.envelope & 0x08) != 0: + if self.volume < 15: + self.volume+=1 + elif self.volume > 0: + self.volume-=1 + self.envelope_length += (constants.SOUND_CLOCK / 64) *\ + (self.envelope & 0x07) def mix_audio(self, buffer, length, output_terminal): for index in range(0, length, 2): - self.audio_4_index += self.audio_4_frequency + self.index += self.frequency #polynomial - if (self.audio_polynomial & 0x08) != 0: + if (self.polynomial & 0x08) != 0: # 7 steps - self.audio_4_index &= 0x7FFFFF - polynomial = self.noise_step_7_table[self.audio_4_index >> 21] >>\ - ((self.audio_4_index >> 16) & 31) + self.index &= 0x7FFFFF + polynomial = self.noise_step_7_table[self.index >> 21] >>\ + ((self.index >> 16) & 31) else: # 15 steps - self.audio_4_index &= 0x7FFFFFFF - polynomial = self.noise_step_15_table[self.audio_4_index >> 21] >> \ - ((self.audio_4_index >> 16) & 31) + self.index &= 0x7FFFFFFF + polynomial = self.noise_step_15_table[self.index >> 21] >> \ + ((self.index >> 16) & 31) if (polynomial & 1) != 0: if (output_terminal & 0x80) != 0: - buffer[index + 0] -= self.audio_volume + buffer[index + 0] -= self.volume if (output_terminal & 0x08) != 0: - buffer[index + 1] -= self.audio_volume + buffer[index + 1] -= self.volume else: if (output_terminal & 0x80) != 0: - buffer[index + 0] += self.audio_volume + buffer[index + 0] += self.volume if (output_terminal & 0x08) != 0: - buffer[index + 1] += self.audio_volume + buffer[index + 1] += self.volume @@ -544,14 +483,14 @@ self.sample_rate = self.driver.get_sample_rate() self.generate_frequency_table() - self.create_audio_channels() + self.create_channels() self.reset() - def create_audio_channels(self): - self.channel1 = Channel1(self.sample_rate, self.frequency_table) - self.channel2 = Channel2(self.sample_rate, self.frequency_table) - self.channel3 = Channel3(self.sample_rate, self.frequency_table) + def create_channels(self): + self.channel1 = SquareWaveChannel(self.sample_rate, self.frequency_table) + self.channel2 = SquareWaveChannel(self.sample_rate, self.frequency_table) + self.channel3 = VoluntaryWaveChannel(self.sample_rate, self.frequency_table) self.channel4 = NoiseGenerator(self.sample_rate, self.frequency_table) @@ -573,37 +512,10 @@ self.channel2.reset() self.channel3.reset() self.channel4.reset() - - self.channel1.audio_index = 0 - self.channel2.audio_index = 0 - self.channel3.audio_index = 0 - self.channel4.audio_index = 0 - - self.write(constants.NR10, 0x80) - self.write(constants.NR11, 0x3F) # 0xBF - self.write(constants.NR12, 0x00) # 0xF3 - self.write(constants.NR13, 0xFF) - self.write(constants.NR14, 0xBF) - - self.write(constants.NR21, 0x3F) - self.write(constants.NR22, 0x00) - self.write(constants.NR23, 0xFF) - self.write(constants.NR24, 0xBF) - - self.write(constants.NR30, 0x7F) - self.write(constants.NR31, 0xFF) - self.write(constants.NR32, 0x9F) - self.write(constants.NR33, 0xFF) - self.write(constants.NR34, 0xBF) - - self.write(constants.NR41, 0xFF) - self.write(constants.NR42, 0x00) - 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.set_output_level(0x00) + self.set_output_terminal(0xF0) + self.set_output_enable(0xFF) for address in range(0xFF30, 0xFF3F): write = 0xFF @@ -639,44 +551,44 @@ def read(self, address): address = int(address) if address==constants.NR10: - return self.channel1.get_audio_sweep() + return self.channel1.get_sweep() elif address == constants.NR11: - return self.channel1.get_audio_length() + return self.channel1.get_length() elif address == constants.NR12: - return self.channel1.get_audio_envelope() + return self.channel1.get_envelope() elif address == constants.NR13: - return self.channel1.get_audio_frequency() + return self.channel1.get_frequency() elif address == constants.NR14: - return self.channel1.get_audio_playback() + return self.channel1.get_playback() elif address == constants.NR21: - return self.channel2.get_audio_length() + return self.channel2.get_length() elif address == constants.NR22: - return self.channel2.get_audio_envelope() + return self.channel2.get_envelope() elif address==constants.NR23: - return self.channel2.get_audio_frequency() + return self.channel2.get_frequency() elif address==constants.NR24: - return self.channel2.get_audio_playback() + return self.channel2.get_playback() elif address==constants.NR30: - return self.channel3.get_audio_enable() + return self.channel3.get_enable() elif address==constants.NR31: - return self.channel3.get_audio_length() + return self.channel3.get_length() elif address==constants.NR32: - return self.channel3.get_audio_level() + return self.channel3.get_level() elif address==constants.NR33: - return self.channel4.get_audio_frequency() + return self.channel4.get_frequency() elif address==constants.NR34: - return self.channel3.get_audio_playback() + return self.channel3.get_playback() elif address==constants.NR41: - return self.channel4.get_audio_length() + return self.channel4.get_length() elif address==constants.NR42: - return self.channel4.get_audio_envelope() + return self.channel4.get_envelope() elif address==constants.NR43: - return self.channel4.get_audio_polynomial() + return self.channel4.get_polynomial() elif address==constants.NR44: - return self.channel4.get_audio_playback() + return self.channel4.get_playback() elif address==constants.NR50: return self.get_output_level() @@ -687,50 +599,50 @@ elif address >= constants.AUD3WAVERAM and \ address <= constants.AUD3WAVERAM + 0x3F: - return self.channel3.get_audio_wave_pattern(address) + return self.channel3.get_wave_pattern(address) return 0xFF def write(self, address, data): address = int(address) if address==constants.NR10: - self.channel1.set_audio_sweep(data) + self.channel1.set_sweep(data) elif address == constants.NR11: - self.channel1.set_audio_length(data) + self.channel1.set_length(data) elif address == constants.NR12: - self.channel1.set_audio_envelope(data) + self.channel1.set_envelope(data) elif address == constants.NR13: - self.channel1.set_audio_frequency(data) + self.channel1.set_frequency(data) elif address == constants.NR14: - self.channel1.set_audio_playback(data) + self.channel1.set_playback(data) elif address == constants.NR21: - self.channel2.set_audio_length(data) + self.channel2.set_length(data) elif address == constants.NR22: - self.channel2.set_audio_envelope(data) + self.channel2.set_envelope(data) elif address == constants.NR23: - self.channel2.set_audio_frequency(data) + self.channel2.set_frequency(data) elif address == constants.NR24: - self.channel2.set_audio_playback(data) + self.channel2.set_playback(data) elif address == constants.NR30: - self.channel3.set_audio_enable(data) + self.channel3.set_enable(data) elif address == constants.NR31: - self.channel3.set_audio_length(data) + self.channel3.set_length(data) elif address == constants.NR32: - self.channel3.set_audio_level(data) + self.channel3.set_level(data) elif address == constants.NR33: - self.channel3.set_audio_frequency(data) + self.channel3.set_frequency(data) elif address == constants.NR34: - self.channel3.set_audio_playback(data) + self.channel3.set_playback(data) elif address == constants.NR41: - self.channel4.set_audio_length(data) + self.channel4.set_length(data) elif address == constants.NR42: - self.channel4.set_audio_envelope(data) + self.channel4.set_envelope(data) elif address == constants.NR43: - self.channel4.set_audio_polynomial(data) + self.channel4.set_polynomial(data) elif address == constants.NR44: - self.channel4.set_audio_playback(data) + self.channel4.set_playback(data) elif address == constants.NR50: self.set_output_level(data) @@ -741,7 +653,7 @@ elif address >= constants.AUD3WAVERAM and \ address <= constants.AUD3WAVERAM + 0x3F: - self.channel3.set_audio_wave_pattern(address, data) + self.channel3.set_wave_pattern(address, data) def update_audio(self): if (self.output_enable & 0x80) == 0: Modified: pypy/trunk/pypy/lang/gameboy/test/test_joypad.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_joypad.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_joypad.py Thu Mar 5 09:24:29 2009 @@ -78,8 +78,8 @@ def test_joypad_driver_ini(): driver = get_driver() assert driver.raised == False - assert driver.get_button_code() == 0 - assert driver.get_direction_code() == 0 + assert driver.get_button_code() == 0xF + assert driver.get_direction_code() == 0xF def test_joypad_driver_isRaised(): driver = get_driver() @@ -102,36 +102,36 @@ def test_joypad_driver_button_toggled_values(): driver = get_driver() driver.button_a() - assert driver.get_button_code() == 0x01 + assert driver.get_button_code() == 0xF - 0x01 driver.reset() driver.button_b() - assert driver.get_button_code() == 0x02 + assert driver.get_button_code() == 0xF - 0x02 driver.reset() driver.button_select() - assert driver.get_button_code() == 0x04 + assert driver.get_button_code() == 0xF - 0x04 driver.reset() driver.button_start() - assert driver.get_button_code() == 0x08 + assert driver.get_button_code() == 0xF - 0x08 def test_joypad_driver_direction_toggled_values(): driver = get_driver() driver.button_up() - assert driver.get_direction_code() == 0x04 + assert driver.get_direction_code() == 0xF - 0x04 driver.reset() driver.button_right() - assert driver.get_direction_code() == 0x01 + assert driver.get_direction_code() == 0xF - 0x01 driver.reset() driver.button_down() - assert driver.get_direction_code() == 0x08 + assert driver.get_direction_code() == 0xF - 0x08 driver.reset() driver.button_left() - assert driver.get_direction_code() == 0x02 + assert driver.get_direction_code() == 0xF - 0x02 def test_toggle_opposite_directions(): @@ -150,21 +150,21 @@ assert driver.raised == False assert button.is_pressed() == False assert opposite_button.is_pressed() == True - assert driver.get_direction_code() == opposite_button.code_value - assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0xF - opposite_button.code_value + assert driver.get_button_code() == 0xF toggleFunction() assert driver.raised == True assert button.is_pressed() == True assert opposite_button.is_pressed() == False - assert driver.get_direction_code() == button.code_value - assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0xF - button.code_value + assert driver.get_button_code() == 0xF toggleFunction(False) assert button.is_pressed() == False assert opposite_button.is_pressed() == False - assert driver.get_direction_code() == 0 - assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0xF + assert driver.get_button_code() == 0xF def test_toggle_buttons(): @@ -179,19 +179,19 @@ driver.reset() assert button.is_pressed() == False - assert driver.get_button_code() == 0 - assert driver.get_direction_code() == 0 + assert driver.get_button_code() == 0xF + assert driver.get_direction_code() == 0xF toggleFunction() assert driver.raised == True assert button.is_pressed() == True - assert driver.get_button_code() == button.code_value - assert driver.get_direction_code() == 0 + assert driver.get_button_code() == 0xF - button.code_value + assert driver.get_direction_code() == 0xF toggleFunction(False) assert button.is_pressed() == False - assert driver.get_button_code() == 0 - assert driver.get_direction_code() == 0 + assert driver.get_button_code() == 0xF + assert driver.get_direction_code() == 0xF def test_toggle_multiple_buttons(): @@ -225,7 +225,7 @@ else: buttons[j][0](False) assert buttons[j][1].is_pressed() == toggled[j] - assert codeGetter() == code + assert codeGetter() == 0xF - code @@ -254,7 +254,7 @@ joypad = get_joypad() joypad.read_control = 0x2 joypad.driver.button_up() - assert joypad.driver.get_direction_code() == constants.BUTTON_UP + assert joypad.driver.get_direction_code() == 0xF - constants.BUTTON_UP joypad.driver.raised = False joypad.cycles = 2 @@ -271,7 +271,7 @@ joypad.emulate(2) assert joypad.cycles == constants.JOYPAD_CLOCK assert joypad.read_control == 2 - assert joypad.button_code == constants.BUTTON_UP + assert joypad.button_code == 0xF - constants.BUTTON_UP assert joypad.joypad_interrupt_flag.is_pending() def test_read_write(): @@ -300,25 +300,25 @@ joypad = get_joypad() # toogle the buttons joypad.driver.button_select() - assert joypad.driver.get_button_code() == constants.BUTTON_SELECT + assert joypad.driver.get_button_code() == 0xF - constants.BUTTON_SELECT joypad.driver.button_up() - assert joypad.driver.get_direction_code() == constants.BUTTON_UP + assert joypad.driver.get_direction_code() == 0xF - constants.BUTTON_UP assert joypad.button_code == 0xF joypad.write(constants.JOYP, 0x10) joypad.update() - assert joypad.button_code == constants.BUTTON_SELECT + assert joypad.button_code == 0xF - constants.BUTTON_SELECT assert joypad.joypad_interrupt_flag.is_pending() joypad.joypad_interrupt_flag.set_pending(False) joypad.write(constants.JOYP, 0x10) joypad.update() - assert joypad.button_code == constants.BUTTON_SELECT + assert joypad.button_code == 0xF - constants.BUTTON_SELECT assert not joypad.joypad_interrupt_flag.is_pending() joypad.write(constants.JOYP, 0x20) joypad.update() - assert joypad.button_code == constants.BUTTON_UP + assert joypad.button_code == 0xF - constants.BUTTON_UP joypad.write(constants.JOYP, 0x30) joypad.update() From fijal at codespeak.net Thu Mar 5 09:26:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 09:26:17 +0100 (CET) Subject: [pypy-svn] r62556 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090305082617.31F0D16851C@codespeak.net> Author: fijal Date: Thu Mar 5 09:26:14 2009 New Revision: 62556 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: complicate a test, still passes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Thu Mar 5 09:26:14 2009 @@ -191,24 +191,29 @@ self.check_loops(getfield_gc=0) def test_escapes(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'parent']) class Node(object): def __init__(self, x): self.x = x + class Parent(object): + def __init__(self, node): + self.node = node + def g(x): pass def f(n): - node = Node(3) + parent = Parent(Node(3)) while n > 0: - myjitdriver.can_enter_jit(n=n, node=node) - myjitdriver.jit_merge_point(n=n, node=node) + myjitdriver.can_enter_jit(n=n, parent=parent) + myjitdriver.jit_merge_point(n=n, parent=parent) + node = parent.node g(node) - node = Node(3) + parent = Parent(Node(node.x)) n -= 1 - return node.x + return parent.node.x res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == 3 From cami at codespeak.net Thu Mar 5 09:46:38 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 09:46:38 +0100 (CET) Subject: [pypy-svn] r62557 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090305084638.8D857168514@codespeak.net> Author: cami Date: Thu Mar 5 09:46:38 2009 New Revision: 62557 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixing sprite test Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py Thu Mar 5 09:46:38 2009 @@ -1,4 +1,4 @@ -from pypy.lang.gameboy import constants +from pypy.lang.gameboy.constants import * from pypy.lang.gameboy.video_sprite import Sprite from pypy.lang.gameboy.video import Video from pypy.lang.gameboy.test.test_video import get_video @@ -58,19 +58,19 @@ sprite = get_sprite() for i in range(0xFF): sprite.set_data_at(0, i) - assert sprite.get_data()[0] == i + assert sprite.get_data_at(0) == i for i in range(0xFF): sprite.set_data_at(1, i) - assert sprite.get_data()[1] == i + assert sprite.get_data_at(1) == i for i in range(0xFF): sprite.set_data_at(2, i) - assert sprite.get_data()[2] == i + assert sprite.get_data_at(2) == i for i in range(0xFF): sprite.set_data_at(3, i) - assert sprite.get_data()[3] == i + assert sprite.get_data_at(3) == i def test_size(): sprite = get_sprite() @@ -121,33 +121,27 @@ sprite.hide_check() assert sprite.hidden -def test_set_data(): - py.test.skip("test not implemented") - sprite = get_sprite() def test_intersects_line_normal_size(): sprite = get_sprite() sprite.big_size = False - sprite.y = 1 - line_intersection_test(sprite, 8) + sprite.y = 2*SPRITE_SIZE+1 + line_intersection_test(sprite) def test_intersects_line_big_size(): sprite = get_sprite() sprite.big_size = True - sprite.y = 1 - line_intersection_test(sprite, 16) - -def line_intersection_test(sprite, height): - assert not sprite.intersects_line(0) - for i in range(height): - assert sprite.intersects_line(i+1) - assert not sprite.intersects_line(height+2) - -def test_intersects_line_normal_size_y_flipped(): - py.test.skip("not yet implemented") + sprite.y = 2*SPRITE_SIZE+1 + line_intersection_test(sprite) +def line_intersection_test(sprite): + sprite.video.line_y = 0 + assert not sprite.intersects_current_line() + for i in range(sprite.get_height()): + sprite.video.line_y = i+1 + assert sprite.intersects_current_line(), i + sprite.video.line_y = sprite.get_height()+1 + assert not sprite.intersects_current_line() -def test_intersects_big_normal_size_y_flipped(): - py.test.skip("not yet implemented") # test sprite in video --------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Thu Mar 5 09:46:38 2009 @@ -140,13 +140,13 @@ def intersects_current_line(self): y = self.current_line_y() - return 0 <= y and y < self.get_height() + return y >= 0 and y < self.get_height() def is_shown_on_current_line(self): return not self.hidden and self.intersects_current_line() def current_line_y(self): - return self.video.line_y - self.y + 2 * SPRITE_SIZE + return (self.video.line_y - self.y) + 2 * SPRITE_SIZE def get_tile_address(self): address = self.get_tile_number() From cami at codespeak.net Thu Mar 5 10:05:12 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 10:05:12 +0100 (CET) Subject: [pypy-svn] r62558 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090305090512.6130B16851A@codespeak.net> Author: cami Date: Thu Mar 5 10:05:11 2009 New Revision: 62558 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/test/test_cpu.py pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py Log: fixing tests reverted Toons changes on the h_flag in the CPU's and_a method Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Thu Mar 5 10:05:11 2009 @@ -374,8 +374,7 @@ self.a.set(self.a.get() & getCaller.get()) # 1 cycle self.flag.reset() self.flag.zero_check(self.a.get()) - # I don't see any reason for this? - # self.flag.is_half_carry = True + self.flag.is_half_carry = True def xor_a(self, getCaller, setCaller=None): # 1 cycle Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu.py Thu Mar 5 10:05:11 2009 @@ -1118,15 +1118,17 @@ # reti def test_0xD9_return_form_interrupt(): cpu = get_cpu() + cpu.ime = False cpu.interrupt.reset() value = 0x1234 cpu.sp.set(0) prepare_for_pop(cpu, value >> 8, value & 0xFF) prepare_for_fetch(cpu, 0x00) - pc = cpu.pc.get() + pc = cpu.pc.get(use_cycles=False) cycle_test(cpu, 0xD9, 4+1+1) # pc: popped value + assert_default_registers(cpu, pc=value+1, sp=2) + assert cpu.ime == True def test_handle_interrupt(): cpu = get_cpu() Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Thu Mar 5 10:05:11 2009 @@ -50,7 +50,6 @@ # assert len(video.vram) == constants.VRAM_SIZE assert len(video.oam) == constants.OAM_SIZE assert len(video.line) == 176 - assert len(video.objects) == constants.big_sprites assert len(video.palette) == 1024 assert video.frames == 0 assert video.frame_skip == 0 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py Thu Mar 5 10:05:11 2009 @@ -32,14 +32,15 @@ assert control.read() == i def test_video_control_get_selected_tile_data_space(): - # TODO: Cami's magic has to pass over here :) + py.test.skip("Strange things happening here") control = get_control_register() + video = control.video control.background_and_window_lower_tile_data_selected = False - assert control.get_selected_tile_data_space() == control.video.tile_data_1 + assert video.get_selected_tile_data_space() == video.tile_data_1 control.background_and_window_lower_tile_data_selected = True - assert control.get_selected_tile_data_space() == control.video.tile_data_0 + assert video.get_selected_tile_data_space() == video.tile_data_0 # StatusRegister --------------------------------------------------------------- From cami at codespeak.net Thu Mar 5 10:07:34 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 10:07:34 +0100 (CET) Subject: [pypy-svn] r62559 - pypy/trunk/pypy/lang/gameboy/test Message-ID: <20090305090734.EBC7216851A@codespeak.net> Author: cami Date: Thu Mar 5 10:07:31 2009 New Revision: 62559 Modified: pypy/trunk/pypy/lang/gameboy/test/test_gameboy_implementaton.py Log: added skip to gameboy_implementation test if the AppKit cant be loaded on MacOS X Modified: pypy/trunk/pypy/lang/gameboy/test/test_gameboy_implementaton.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_gameboy_implementaton.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_gameboy_implementaton.py Thu Mar 5 10:07:31 2009 @@ -16,9 +16,11 @@ # if sys.platform == 'darwin': - from AppKit import NSApplication - NSApplication.sharedApplication() - + try: + from AppKit import NSApplication + NSApplication.sharedApplication() + except: + py.test.skip("Could not load the AppKit") class TestGameBoyImplementation(object): From cami at codespeak.net Thu Mar 5 10:10:29 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 10:10:29 +0100 (CET) Subject: [pypy-svn] r62560 - pypy/trunk/pypy/lang/gameboy/test Message-ID: <20090305091029.9B7B316851A@codespeak.net> Author: cami Date: Thu Mar 5 10:10:29 2009 New Revision: 62560 Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu.py Log: skipping strange cpu test Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu.py Thu Mar 5 10:10:29 2009 @@ -1117,6 +1117,7 @@ # reti def test_0xD9_return_form_interrupt(): + py.test.skip("this needs a fix, track changes") cpu = get_cpu() cpu.ime = False cpu.interrupt.reset() From fijal at codespeak.net Thu Mar 5 10:18:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 10:18:33 +0100 (CET) Subject: [pypy-svn] r62561 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090305091833.649B016851C@codespeak.net> Author: fijal Date: Thu Mar 5 10:18:32 2009 New Revision: 62561 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: Fix some rare issues when having a non-virtual on always_virtual on a virtualizable :-) Also a test which checks a subset of cases Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 5 10:18:32 2009 @@ -129,31 +129,34 @@ def is_zero(self): return self.const and not self.source.getptr_base() - def escape_if_startbox(self, memo): + def escape_if_startbox(self, memo, escape_self=True): if self in memo: return memo[self] = None - if self.startbox: + if self.startbox and escape_self: self.escaped = True if not self.virtualized: for node in self.curfields.values(): node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - if self.vdesc and key not in self.vdesc.virtuals: - node.escape_if_startbox(memo) + esc_self = self.vdesc and key not in self.vdesc.virtuals + node.escape_if_startbox(memo, esc_self) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): - if (self.vdesc and key not in self.vdesc.virtuals and - key not in self.curfields): - node.escape_if_startbox(memo) + if key not in self.curfields: + esc_self = self.vdesc and key not in self.vdesc.virtuals + node.escape_if_startbox(memo, esc_self) def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) for ofs, node in self.origfields.items(): if ofs in other.curfields: node.add_to_dependency_graph(other.curfields[ofs], dep_graph) + if (self.virtualized and self.vdesc and + ofs in self.vdesc.virtuals): + node.add_to_dependency_graph(other.origfields[ofs], dep_graph) def intersect(self, other): if not other.cls: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Mar 5 10:18:32 2009 @@ -271,7 +271,8 @@ assert res == f(20) def test_virtualizable_hierarchy(self): - jitdriver = JitDriver(greens = [], reds = ['frame', 'n']) + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) class BaseFrame(object): _virtualizable2_ = True @@ -302,6 +303,45 @@ assert res == f(20) self.check_loops(getfield_gc=0, setfield_gc=0) + def test_non_virtual_on_always_virtual(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + _always_virtual_ = ['node'] + + def __init__(self, node): + self.node = node + + class Node(object): + def __init__(self, node): + self.node = node + + class SubNode(object): + def __init__(self, x): + self.x = x + + def g(node): + pass + + def f(n): + frame = Frame(Node(SubNode(1))) + + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n) + jitdriver.jit_merge_point(frame=frame, n=n) + node = frame.node + subnode = node.node + g(subnode) + frame.node = Node(SubNode(subnode.x + 1)) + n -= 1 + return n + + res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) + assert res == 0 + def test_external_read(self): py.test.skip("Fails") class Frame(object): From arigo at codespeak.net Thu Mar 5 10:18:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 10:18:37 +0100 (CET) Subject: [pypy-svn] r62562 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090305091837.C6D4716852D@codespeak.net> Author: arigo Date: Thu Mar 5 10:18:36 2009 New Revision: 62562 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Remove or comment out old code. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 5 10:18:36 2009 @@ -530,15 +530,15 @@ self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox]) return clsbox - @arguments("orgpc", "box", "builtin") - def opimpl_guard_builtin(self, pc, box, builtin): - self.generate_guard(pc, "guard_builtin", box, [builtin]) - - @arguments("orgpc", "box", "builtin") - def opimpl_guard_len(self, pc, box, builtin): - intbox = self.metainterp.cpu.execute_operation( - 'len', [builtin.len_func, box], 'int') - self.generate_guard(pc, "guard_len", box, [intbox]) +## @arguments("orgpc", "box", "builtin") +## def opimpl_guard_builtin(self, pc, box, builtin): +## self.generate_guard(pc, "guard_builtin", box, [builtin]) + +## @arguments("orgpc", "box", "builtin") +## def opimpl_guard_len(self, pc, box, builtin): +## intbox = self.metainterp.cpu.execute_operation( +## 'len', [builtin.len_func, box], 'int') +## self.generate_guard(pc, "guard_len", box, [intbox]) @arguments("orgpc", "box", "virtualizabledesc", "constbox") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): @@ -680,10 +680,6 @@ cls = llmemory.cast_ptr_to_adr(obj.typeptr) return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) - def follow_jump(self): - self.pc -= 3 - self.pc = self.load_3byte() - def execute(self, opnum, argboxes, result_type, pure=False): resbox = self.metainterp.history.execute_and_record(opnum, argboxes, result_type, From cami at codespeak.net Thu Mar 5 10:26:45 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 10:26:45 +0100 (CET) Subject: [pypy-svn] r62564 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305092645.7BEAA16851C@codespeak.net> Author: cami Date: Thu Mar 5 10:26:42 2009 New Revision: 62564 Modified: pypy/trunk/pypy/lang/gameboy/sound.py Log: added some comments Modified: pypy/trunk/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/sound.py (original) +++ pypy/trunk/pypy/lang/gameboy/sound.py Thu Mar 5 10:26:42 2009 @@ -4,7 +4,7 @@ Audio Processor Unit (Sharp LR35902 APU) """ -from pypy.lang.gameboy import constants +from pypy.lang.gameboy.constants import * from pypy.lang.gameboy.ram import iMemory class Channel(object): @@ -20,23 +20,36 @@ self.envelope = 0 self.frequency = 0 self.playback = 0 - self.nr0 = 0 - self.nr1 = 0 - self.nr2 = 0 - self.nr4 = 0 - self.nr3 = 0 + self.nr0 = 0 + self.nr1 = 0 + self.nr2 = 0 + self.nr4 = 0 + self.nr3 = 0 self.index = 0 self.length = 0 self.frequency = 0 - self.enabled = False - #XXX need to push this up into the Sound class - self.output_enable = False + self.enabled = False def reset(self): self.index = 0 self.set_length(0xFF) self.set_playback(0xBF) + + def update_audio(self): + self.update_enabled() + self.update_envelope_and_volume() + self.update_frequency_and_playback() + + def update_enabled(): + pass + + def update_envelope_and_volume(): + pass + + def update_frequency_and_playback(): + + def get_length(self): return self.length @@ -64,12 +77,12 @@ # Audio Channel 1 int def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) - self.sample_sweep = 0 + self.sample_sweep = 0 self.index = 0 self.length = 0 - self.volume = 0 + self.volume = 0 self.envelope_length = 0 - self.sample_sweep_length = 0 + self.sample_sweep_length = 0 self.frequency = 0 def reset(self): @@ -86,12 +99,12 @@ def set_sweep(self, data): self.sample_sweep = data - self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ + self.sample_sweep_length = (SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) def set_length(self, data): self.length = data - self.length = (constants.SOUND_CLOCK / 256) * \ + self.length = (SOUND_CLOCK / 256) * \ (64 - (self.length & 0x3F)) def set_envelope(self, data): @@ -108,6 +121,7 @@ def set_frequency(self, data): + # TODO make sure get and set frequency will work self.frequency = data index = self.frequency + ((self.playback & 0x07) << 8) self.frequency = self.frequency_table[index] @@ -120,19 +134,13 @@ if (self.playback & 0x80) != 0: self.enabled = True if (self.playback & 0x40) != 0 and self.length == 0: - self.length = (constants.SOUND_CLOCK / 256) * \ + self.length = (SOUND_CLOCK / 256) * \ (64 - (self.length & 0x3F)) - self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ + self.sample_sweep_length = (SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) self.volume = self.envelope >> 4 - self.envelope_length = (constants.SOUND_CLOCK / 64) * \ + self.envelope_length = (SOUND_CLOCK / 64) * \ (self.envelope & 0x07) - - def update_audio(self): - self.update_enable() - self.update_volume_and_envelope() - self.update_frequency_and_playback() - def update_enable(self): if (self.playback & 0x40) != 0 and self.length > 0: @@ -141,8 +149,7 @@ self.enabled = False def update_volume_and_envelope(self): - if self.envelope_length <= 0: - return + if self.envelope_length <= 0: return self.envelope_length -= 1 if self.envelope_length <= 0: if (self.envelope & 0x08) != 0: @@ -150,8 +157,7 @@ self.volume += 1 elif self.volume > 0: self.volume -= 1 - self.envelope_length += (constants.SOUND_CLOCK / 64) * \ - (self.envelope & 0x07) + self.envelope_length += (SOUND_CLOCK / 64) * (self.envelope & 0x07) def update_frequency_and_playback(self): if self.sample_sweep_length <= 0: @@ -161,38 +167,41 @@ return sweep_steps = (self.sample_sweep & 0x07) if sweep_steps != 0: - frequency = ((self.playback & 0x07) << 8) + \ - self.frequency - if (self.sample_sweep & 0x08) != 0: - frequency -= frequency >> sweep_steps - else: - frequency += frequency >> sweep_steps - if frequency < 2048: - self.frequency = self.frequency_table[frequency] - self.frequency = frequency & 0xFF - self.playback = (self.playback & 0xF8) + \ - ((frequency >> 8) & 0x07) - else: - self.frequency = 0 - self.output_enable &= ~0x01 - self.sample_sweep_length += (constants.SOUND_CLOCK / 128) * \ + self.update_frequency() + self.sample_sweep_length += (SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) - + + def update_frequency(self): + frequency = ((self.playback & 0x07) << 8) + self.frequency + if (self.sample_sweep & 0x08) != 0: + frequency -= frequency >> sweep_steps + else: + frequency += frequency >> sweep_steps + if frequency < 2048: + self.frequency = self.frequency_table[frequency] + self.frequency = frequency & 0xFF + self.playback = (self.playback & 0xF8) + \ + ((frequency >> 8) & 0x07) + else: + self.frequency = 0 + self.enabled = False + #self.output_enable &= ~0x01 + def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 3): self.index += self.frequency - if (self.index & (0x1F << 22)) >= wave_pattern: + # if (self.index & (0x1F << 22)) >= wave_pattern: # output_terminal & 0x20 for the second SquareWaveChannel if (output_terminal & 0x10) != 0: buffer[index + 0] -= self.volume if (output_terminal & 0x01) != 0: buffer[index + 1] -= self.volume - else: - if (output_terminal & 0x10) != 0: - buffer[index + 0] += self.volume - if (output_terminal & 0x01) != 0: - buffer[index + 1] += self.volume + #else: + # if (output_terminal & 0x10) != 0: + # buffer[index + 0] += self.volume + # if (output_terminal & 0x01) != 0: + # buffer[index + 1] += self.volume def get_current_wave_pattern(self): wave_pattern = 0x18 @@ -244,7 +253,7 @@ def set_length(self, data): self.length = data - self.length = (constants.SOUND_CLOCK / 256) * \ + self.length = (SOUND_CLOCK / 256) * \ (256 - self.length) def set_level(self, data): @@ -262,7 +271,7 @@ if (self.playback & 0x80) != 0 and (self.enable & 0x80) != 0: self.enabled = True if (self.playback & 0x40) != 0 and self.length == 0: - self.length = (constants.SOUND_CLOCK / 256) *\ + self.length = (SOUND_CLOCK / 256) *\ (256 - self.length) def set_wave_pattern(self, address, data): @@ -274,8 +283,8 @@ def update_audio(self): if (self.playback & 0x40) != 0 and self.length > 0: self.length-=1 - if self.length <= 0: - self.output_enable &= ~0x04 + self.enabled = self.length <= 0: + #self.output_enable &= ~0x04 def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() @@ -337,7 +346,7 @@ divider = 1 if ratio != 0: divider = 2 * ratio - self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / \ + self.noiseFreqRatioTable[ratio] = (GAMEBOY_CLOCK / \ divider) *sampleFactor def generate_noise_tables(self): @@ -381,7 +390,7 @@ def set_length(self, data): self.length = data - self.length = (constants.SOUND_CLOCK / 256) * \ + self.length = (SOUND_CLOCK / 256) * \ (64 - (self.length & 0x3F)) def set_envelope(self, data): @@ -410,23 +419,19 @@ return self.enabled = True if (self.playback & 0x40) != 0 and self.length == 0: - self.length = (constants.SOUND_CLOCK / 256) * \ + self.length = (SOUND_CLOCK / 256) * \ (64 - (self.length & 0x3F)) self.volume = self.envelope >> 4 - self.envelope_length = (constants.SOUND_CLOCK / 64) * \ + self.envelope_length = (SOUND_CLOCK / 64) * \ (self.envelope & 0x07) self.index = 0 - - def update_audio(self): - self.update_enabled() - self.update_envelope_and_volume() def update_enabled(self): if (self.playback & 0x40) != 0 and self.length > 0: self.length-=1 - if self.length <= 0: - self.output_enable &= ~0x08 - + self.enabled = self.length <= 0: + #self.output_enable &= ~0x08 + def update_envelope_and_volume(self): if self.envelope_length <= 0: return @@ -438,7 +443,7 @@ self.volume+=1 elif self.volume > 0: self.volume-=1 - self.envelope_length += (constants.SOUND_CLOCK / 64) *\ + self.envelope_length += (SOUND_CLOCK / 64) *\ (self.envelope & 0x07) def mix_audio(self, buffer, length, output_terminal): @@ -492,13 +497,14 @@ self.channel2 = SquareWaveChannel(self.sample_rate, self.frequency_table) self.channel3 = VoluntaryWaveChannel(self.sample_rate, self.frequency_table) self.channel4 = NoiseGenerator(self.sample_rate, self.frequency_table) + self.channels = [self.channel1, self.channel2, self.channel3, self.channel4] def generate_frequency_table(self): self.frequency_table = [0] * 2048 # frequency = (4194304 / 32) / (2048 - period) Hz for period in range(0, 2048): - skip = (((constants.GAMEBOY_CLOCK << 10) / \ + skip = (((GAMEBOY_CLOCK << 10) / \ self.sample_rate) << 16) / (2048 - period) if skip >= (32 << 22): self.frequency_table[period] = 0 @@ -506,7 +512,7 @@ self.frequency_table[period] = skip def reset(self): - self.cycles = int(constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK) + self.cycles = int(GAMEBOY_CLOCK / SOUND_CLOCK) self.frames = 0 self.channel1.reset() self.channel2.reset() @@ -539,145 +545,136 @@ self.update_audio() if self.driver.is_enabled(): self.mix_down_audio() - self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK + self.cycles += GAMEBOY_CLOCK / SOUND_CLOCK def mix_down_audio(self): self.frames += self.driver.get_sample_rate() - length = (self.frames / constants.SOUND_CLOCK) << 1 + length = (self.frames / SOUND_CLOCK) << 1 self.mix_audio(self.buffer, length) self.driver.write(self.buffer, length) - self.frames %= constants.SOUND_CLOCK + self.frames %= SOUND_CLOCK def read(self, address): + # TODO map the read/write in groups directly to the channels address = int(address) - if address==constants.NR10: + if address==NR10: return self.channel1.get_sweep() - elif address == constants.NR11: + elif address == NR11: return self.channel1.get_length() - elif address == constants.NR12: + elif address == NR12: return self.channel1.get_envelope() - elif address == constants.NR13: + elif address == NR13: return self.channel1.get_frequency() - elif address == constants.NR14: + elif address == NR14: return self.channel1.get_playback() - elif address == constants.NR21: + elif address == NR21: return self.channel2.get_length() - elif address == constants.NR22: + elif address == NR22: return self.channel2.get_envelope() - elif address==constants.NR23: + elif address==NR23: return self.channel2.get_frequency() - elif address==constants.NR24: + elif address==NR24: return self.channel2.get_playback() - elif address==constants.NR30: + elif address==NR30: return self.channel3.get_enable() - elif address==constants.NR31: + elif address==NR31: return self.channel3.get_length() - elif address==constants.NR32: + elif address==NR32: return self.channel3.get_level() - elif address==constants.NR33: + elif address==NR33: return self.channel4.get_frequency() - elif address==constants.NR34: + elif address==NR34: return self.channel3.get_playback() - elif address==constants.NR41: + elif address==NR41: return self.channel4.get_length() - elif address==constants.NR42: + elif address==NR42: return self.channel4.get_envelope() - elif address==constants.NR43: + elif address==NR43: return self.channel4.get_polynomial() - elif address==constants.NR44: + elif address==NR44: return self.channel4.get_playback() - elif address==constants.NR50: + elif address==NR50: return self.get_output_level() - elif address==constants.NR51: + elif address==NR51: return self.get_output_terminal() - elif address==constants.NR52: + elif address==NR52: return self.get_output_enable() - elif address >= constants.AUD3WAVERAM and \ - address <= constants.AUD3WAVERAM + 0x3F: + elif address >= AUD3WAVERAM and \ + address <= AUD3WAVERAM + 0x3F: return self.channel3.get_wave_pattern(address) return 0xFF def write(self, address, data): address = int(address) - if address==constants.NR10: + if address == NR10: self.channel1.set_sweep(data) - elif address == constants.NR11: + elif address == NR11: self.channel1.set_length(data) - elif address == constants.NR12: + elif address == NR12: self.channel1.set_envelope(data) - elif address == constants.NR13: + elif address == NR13: self.channel1.set_frequency(data) - elif address == constants.NR14: + elif address == NR14: self.channel1.set_playback(data) - elif address == constants.NR21: + elif address == NR21: self.channel2.set_length(data) - elif address == constants.NR22: + elif address == NR22: self.channel2.set_envelope(data) - elif address == constants.NR23: + elif address == NR23: self.channel2.set_frequency(data) - elif address == constants.NR24: + elif address == NR24: self.channel2.set_playback(data) - elif address == constants.NR30: + elif address == NR30: self.channel3.set_enable(data) - elif address == constants.NR31: + elif address == NR31: self.channel3.set_length(data) - elif address == constants.NR32: + elif address == NR32: self.channel3.set_level(data) - elif address == constants.NR33: + elif address == NR33: self.channel3.set_frequency(data) - elif address == constants.NR34: + elif address == NR34: self.channel3.set_playback(data) - elif address == constants.NR41: + elif address == NR41: self.channel4.set_length(data) - elif address == constants.NR42: + elif address == NR42: self.channel4.set_envelope(data) - elif address == constants.NR43: + elif address == NR43: self.channel4.set_polynomial(data) - elif address == constants.NR44: + elif address == NR44: self.channel4.set_playback(data) - elif address == constants.NR50: + elif address == NR50: self.set_output_level(data) - elif address == constants.NR51: + elif address == NR51: self.set_output_terminal(data) - elif address == constants.NR52: + elif address == NR52: self.set_output_enable(data) - elif address >= constants.AUD3WAVERAM and \ - address <= constants.AUD3WAVERAM + 0x3F: + elif address >= AUD3WAVERAM and \ + address <= AUD3WAVERAM + 0x3F: self.channel3.set_wave_pattern(address, data) def update_audio(self): if (self.output_enable & 0x80) == 0: return - if (self.output_enable & 0x01) != 0: - self.channel1.update_audio() - if (self.output_enable & 0x02) != 0: - self.channel2.update_audio() - if (self.output_enable & 0x04) != 0: - self.channel3.update_audio() - if (self.output_enable & 0x08) != 0: - self.channel4.update_audio() + for channel in self.channels + if channel.enabled: + channel.update_audio() def mix_audio(self, buffer, length): if (self.output_enable & 0x80) == 0: return - if (self.output_enable & 0x01) != 0: - self.channel1.mix_audio(buffer, length, self.output_terminal) - if (self.output_enable & 0x02) != 0: - self.channel2.mix_audio(buffer, length, self.output_terminal) - if (self.output_enable & 0x04) != 0: - self.channel3.mix_audio(buffer, length, self.output_terminal) - if (self.output_enable & 0x08) != 0: - self.channel4.mix_audio(buffer, length, self.output_terminal) + for channel in self.channels + if channel.enabled: + channel.mix_audio(buffer, length, self.output_terminal) # Output Control def get_output_level(self): @@ -696,6 +693,7 @@ self.output_terminal = data def set_output_enable(self, data): + # TODO map directly to the channels self.output_enable = (self.output_enable & 0x7F) | (data & 0x80) if (self.output_enable & 0x80) == 0x00: self.output_enable &= 0xF0 From arigo at codespeak.net Thu Mar 5 10:27:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 10:27:22 +0100 (CET) Subject: [pypy-svn] r62565 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090305092722.E3AFA168063@codespeak.net> Author: arigo Date: Thu Mar 5 10:27:21 2009 New Revision: 62565 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Give a consistent name to the codewriter operations and the resoperations for PURE versions of getfield and getarrayitem. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 5 10:27:21 2009 @@ -521,16 +521,16 @@ # check for deepfrozen structures that force constant-folding #pure = self.codewriter.is_green_var(op.result) if op.args[0].concretetype.TO._hints.get('immutable'): - opname = 'getfield_pure' + pure = '_pure' else: - opname = 'getfield' + pure = '' # turn the flow graph 'getfield' operation into our own version [v_inst, c_fieldname] = op.args RESULT = op.result.concretetype if RESULT is lltype.Void: return argname = v_inst.concretetype.TO._gckind - self.emit('%s_%s' % (opname, argname)) + self.emit('getfield_%s%s' % (argname, pure)) self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) @@ -742,7 +742,7 @@ # if oopspec_name == 'list.getitem_foldable': return self.handle_list_getitem(op, arraydescr, args, - 'getarrayitem_foldable_gc') + 'getarrayitem_gc_pure') # if oopspec_name == 'list.setitem': index = self.prepare_list_getset(op, arraydescr, args) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 5 10:27:21 2009 @@ -328,7 +328,7 @@ self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox], tp) @arguments("box", "constbox", "box") - def opimpl_getarrayitem_foldable_gc(self, arraybox, arraydesc, indexbox): + def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): tp = self.metainterp.cpu.typefor(arraydesc.getint()) self.execute(rop.GETARRAYITEM_GC_PURE, [arraybox, arraydesc, indexbox], tp, True) @@ -377,7 +377,7 @@ tp = self.metainterp.cpu.typefor(fielddesc.getint()) self.execute(rop.GETFIELD_GC, [box, fielddesc], tp) @arguments("box", "constbox") - def opimpl_getfield_pure_gc(self, box, fielddesc): + def opimpl_getfield_gc_pure(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc], tp, True) @arguments("box", "constbox", "box") @@ -390,9 +390,9 @@ tp = self.metainterp.cpu.typefor(fielddesc.getint()) self.execute(rop.GETFIELD_RAW, [box, fielddesc], tp) @arguments("box", "constbox") - def opimpl_getfield_pure_raw(self, box, fielddesc): + def opimpl_getfield_raw_pure(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_RAW, [box, fielddesc], tp, True) + self.execute(rop.GETFIELD_RAW_PURE, [box, fielddesc], tp, True) @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, fielddesc, valuebox], From fijal at codespeak.net Thu Mar 5 10:35:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 10:35:23 +0100 (CET) Subject: [pypy-svn] r62567 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090305093523.343AD16851B@codespeak.net> Author: fijal Date: Thu Mar 5 10:35:22 2009 New Revision: 62567 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: An attempt to see failedToImplement Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Thu Mar 5 10:35:22 2009 @@ -42,10 +42,10 @@ pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) descr_impl = getattr(pypy.objspace.descroperation.DescrOperation, 'inplace_' + name2) - self.seepath( - getattr(pypy.interpreter.pyframe.PyFrame, 'INPLACE_'+ opname), - descr_impl, - obj_impl) + op_impl = getattr(pypy.interpreter.pyframe.PyFrame, 'INPLACE_'+ opname) + self.seepath(op_impl, descr_impl, obj_impl) + self.seepath(op_impl, + pypy.objspace.std.multimethod.raiseFailedToImplement) self.seepath(descr_impl, pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) From tverwaes at codespeak.net Thu Mar 5 10:35:32 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 5 Mar 2009 10:35:32 +0100 (CET) Subject: [pypy-svn] r62568 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305093532.CA4D6168520@codespeak.net> Author: tverwaes Date: Thu Mar 5 10:35:32 2009 New Revision: 62568 Modified: pypy/trunk/pypy/lang/gameboy/sound.py Log: fixing syntax Modified: pypy/trunk/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/sound.py (original) +++ pypy/trunk/pypy/lang/gameboy/sound.py Thu Mar 5 10:35:32 2009 @@ -48,7 +48,7 @@ pass def update_frequency_and_playback(): - + pass def get_length(self): return self.length @@ -193,10 +193,10 @@ self.index += self.frequency # if (self.index & (0x1F << 22)) >= wave_pattern: # output_terminal & 0x20 for the second SquareWaveChannel - if (output_terminal & 0x10) != 0: - buffer[index + 0] -= self.volume - if (output_terminal & 0x01) != 0: - buffer[index + 1] -= self.volume + if (output_terminal & 0x10) != 0: + buffer[index + 0] -= self.volume + if (output_terminal & 0x01) != 0: + buffer[index + 1] -= self.volume #else: # if (output_terminal & 0x10) != 0: # buffer[index + 0] += self.volume @@ -283,7 +283,7 @@ def update_audio(self): if (self.playback & 0x40) != 0 and self.length > 0: self.length-=1 - self.enabled = self.length <= 0: + self.enabled = self.length <= 0 #self.output_enable &= ~0x04 def mix_audio(self, buffer, length, output_terminal): @@ -429,7 +429,7 @@ def update_enabled(self): if (self.playback & 0x40) != 0 and self.length > 0: self.length-=1 - self.enabled = self.length <= 0: + self.enabled = self.length <= 0 #self.output_enable &= ~0x08 def update_envelope_and_volume(self): @@ -665,14 +665,14 @@ def update_audio(self): if (self.output_enable & 0x80) == 0: return - for channel in self.channels + for channel in self.channels: if channel.enabled: channel.update_audio() def mix_audio(self, buffer, length): if (self.output_enable & 0x80) == 0: return - for channel in self.channels + for channel in self.channels: if channel.enabled: channel.mix_audio(buffer, length, self.output_terminal) From fijal at codespeak.net Thu Mar 5 10:35:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 10:35:40 +0100 (CET) Subject: [pypy-svn] r62569 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305093540.6DAE1168529@codespeak.net> Author: fijal Date: Thu Mar 5 10:35:40 2009 New Revision: 62569 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: try inplace_add Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Thu Mar 5 10:35:40 2009 @@ -5,7 +5,7 @@ i = 0 while i < 100: # XXX implement inplace_add method for ints - i = i + 3 + i += 3 print i # should print 102 f() From fijal at codespeak.net Thu Mar 5 10:57:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 10:57:40 +0100 (CET) Subject: [pypy-svn] r62570 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090305095740.281B7168529@codespeak.net> Author: fijal Date: Thu Mar 5 10:57:39 2009 New Revision: 62570 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: Look at all builtin shortcuts and FailedToImplement.__init__ Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Thu Mar 5 10:57:39 2009 @@ -1,11 +1,14 @@ import pypy from pypy.jit.metainterp.policy import ManualJitPolicy +from pypy.translator.backendopt.support import find_calls_from class PyPyJitPolicy(ManualJitPolicy): def look_inside_function(self, func): mod = func.__module__ or '?' + if func.__name__.startswith('__mm_'): + return True if mod.startswith('pypy.objspace.'): return False if '_geninterp_' in func.func_globals: # skip all geninterped stuff @@ -28,6 +31,9 @@ return super(PyPyJitPolicy, self).look_inside_function(func) def seebinary(self, opname): + def fc(o): + return [i[1] for i in find_calls_from(self.translator, o)] + name2 = name1 = opname[:3].lower() if name1 in ('and', 'or'): name1 += '_' @@ -44,8 +50,6 @@ 'inplace_' + name2) op_impl = getattr(pypy.interpreter.pyframe.PyFrame, 'INPLACE_'+ opname) self.seepath(op_impl, descr_impl, obj_impl) - self.seepath(op_impl, - pypy.objspace.std.multimethod.raiseFailedToImplement) self.seepath(descr_impl, pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) @@ -97,6 +101,8 @@ self.seepath(pypy.objspace.descroperation.DescrOperation.add, pypy.objspace.std.Space.is_w) self.seegraph(pypy.interpreter.pyframe.PyFrame.execute_frame, False) + self.seegraph(pypy.objspace.std.multimethod.FailedToImplement.__init__, + True) # -------------------- self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, pypy.objspace.std.boolobject.nonzero__Bool) From arigo at codespeak.net Thu Mar 5 11:28:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 11:28:34 +0100 (CET) Subject: [pypy-svn] r62571 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090305102834.CED32168529@codespeak.net> Author: arigo Date: Thu Mar 5 11:28:31 2009 New Revision: 62571 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Rewrite operations CALL_# to CALL and CALL_PURE. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 11:28:31 2009 @@ -98,9 +98,8 @@ 'getarrayitem_gc' : (('ptr', 'int', 'int'), 'intorptr'), 'getarrayitem_gc_pure' : (('ptr', 'int', 'int'), 'intorptr'), 'arraylen_gc' : (('ptr', 'int'), 'int'), - 'call_ptr' : (('ptr', 'varargs'), 'ptr'), - 'call__4' : (('ptr', 'varargs'), 'int'), - 'call_void' : (('ptr', 'varargs'), None), + 'call' : (('ptr', 'int', 'varargs'), 'intorptr'), + 'call_pure' : (('ptr', 'int', 'varargs'), 'intorptr'), 'guard_true' : (('bool',), None), 'guard_false' : (('bool',), None), 'guard_value' : (('int', 'int'), None), @@ -823,7 +822,7 @@ assert self.last_exception_handled self.last_exception = None - def do_call(self, f, *args): + def op_call(self, f, calldescr, *args): ptr = cast_int_to_adr(self.memocast, f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS @@ -843,9 +842,7 @@ self.clear_exception() return x - op_call__4 = do_call - op_call_ptr = do_call - op_call_void = do_call + op_call_pure = op_call def op_listop_return(self, ll_func, *args): return self.do_call(ll_func, *args) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 11:28:31 2009 @@ -274,7 +274,19 @@ return size*2 + bit @staticmethod + def calldescrof(ARGS, RESULT): + if RESULT is lltype.Void: + return -1 + token = history.getkind(RESULT) + if token == 'ptr': + return 1 + else: + return 0 + + @staticmethod def typefor(fielddesc): + if fielddesc == -1: + return 'void' if fielddesc % 2: return 'ptr' return 'int' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 5 11:28:31 2009 @@ -5,7 +5,7 @@ from pypy.rlib import objectmodel from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.jit import _we_are_jitted -from pypy.jit.metainterp.history import Const, getkind, getkind_num +from pypy.jit.metainterp.history import Const, getkind from pypy.jit.metainterp import heaptracker, support, history import py @@ -662,18 +662,23 @@ def handle_residual_call(self, op): self.minimize_variables() - self.emit('residual_call_%s' % getkind_num(self.cpu, - op.result.concretetype)) - self.emit_varargs([x for x in op.args - if x.concretetype is not lltype.Void]) + args = [x for x in op.args[1:] if x.concretetype is not lltype.Void] + argtypes = [v.concretetype for v in args] + resulttype = op.result.concretetype + calldescr = self.cpu.calldescrof(argtypes, resulttype) + self.emit('residual_call') + self.emit(self.var_position(op.args[0])) + self.emit(self.const_position(calldescr)) + self.emit_varargs(args) self.register_var(op.result) def handle_builtin_call(self, op): oopspec_name, args = support.decode_builtin_call(op) - ll_args = [v.concretetype for v in args] + argtypes = [v.concretetype for v in args] + resulttype = op.result.concretetype c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, - oopspec_name, ll_args, - op.result.concretetype) + oopspec_name, argtypes, + resulttype) if self.codewriter.metainterp.options.listops: if self.handle_list_call(op, oopspec_name, args, TP): return @@ -704,11 +709,14 @@ ## self._eventualy_builtin(op.result, False) ## return if oopspec_name.endswith('_foldable'): - opname = 'green_call_%s' + opname = 'residual_call_pure' else: - opname = 'residual_call_%s' - self.emit(opname % getkind_num(self.cpu, op.result.concretetype)) - self.emit_varargs([c_func] + args) + opname = 'residual_call' + calldescr = self.cpu.calldescrof(argtypes, resulttype) + self.emit(opname) + self.emit(self.var_position(c_func)) + self.emit(self.const_position(calldescr)) + self.emit_varargs(args) self.register_var(op.result) def handle_list_call(self, op, oopspec_name, args, TP): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 5 11:28:31 2009 @@ -404,44 +404,17 @@ f.setup_call(varargs) return True - @arguments("varargs") - def opimpl_green_call__1(self, varargs): - return self.execute_with_exc(rop.CALL__1, varargs, 'int', True) - @arguments("varargs") - def opimpl_green_call__2(self, varargs): - return self.execute_with_exc(rop.CALL__2, varargs, 'int', True) - @arguments("varargs") - def opimpl_green_call__4(self, varargs): - return self.execute_with_exc(rop.CALL__4, varargs, 'int', True) - @arguments("varargs") - def opimpl_green_call__8(self, varargs): - return self.execute_with_exc(rop.CALL__8, varargs, 'int', True) - - @arguments("varargs") - def opimpl_green_call_ptr(self, varargs): - return self.execute_with_exc(rop.CALL_PTR, varargs, 'ptr', True) - - @arguments("varargs") - def opimpl_residual_call__1(self, varargs): - return self.execute_with_exc(rop.CALL__1, varargs, 'int') - @arguments("varargs") - def opimpl_residual_call__2(self, varargs): - return self.execute_with_exc(rop.CALL__2, varargs, 'int') - @arguments("varargs") - def opimpl_residual_call__4(self, varargs): - return self.execute_with_exc(rop.CALL__4, varargs, 'int') - @arguments("varargs") - def opimpl_residual_call__8(self, varargs): - return self.execute_with_exc(rop.CALL__8, varargs, 'int') - - @arguments("varargs") - def opimpl_residual_call_ptr(self, varargs): - return self.execute_with_exc(rop.CALL_PTR, varargs, 'ptr') - - @arguments("varargs") - def opimpl_residual_call_void(self, varargs): - return self.execute_with_exc(rop.CALL_VOID, varargs, 'void') - + @arguments("box", "constbox", "varargs") + def opimpl_residual_call(self, funcbox, calldescr, varargs): + tp = self.metainterp.cpu.typefor(calldescr.getint()) + args = [funcbox, calldescr] + varargs + return self.execute_with_exc(rop.CALL, args, tp) + + @arguments("box", "constbox", "varargs") + def opimpl_residual_call_pure(self, funcbox, calldescr, varargs): + tp = self.metainterp.cpu.typefor(calldescr.getint()) + args = [funcbox, calldescr] + varargs + return self.execute_with_exc(rop.CALL_PURE, args, tp, True) ## @arguments("fixedlist", "box", "box") ## def opimpl_list_getitem(self, descr, listbox, indexbox): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 5 11:28:31 2009 @@ -65,17 +65,6 @@ # ____________________________________________________________ -class typ(object): - INT = 0 # a register-sized, non-GC-aware value (int or addr) - PTR = 1 # a pointer to a GC object - VOID = 2 # a void - - INT1 = 3 # when we need more precision about the size of the int, - INT2 = 4 # use these instead of INT - INT4 = 5 # (e.g. for reading or writing fields) - INT8 = 6 - - class rop(object): """The possible names of the ResOperations.""" @@ -94,8 +83,10 @@ GUARD_EXCEPTION = 16 _GUARD_LAST = 19 # ----- end of guard operations ----- - _NOSIDEEFFECT_FIRST = 30 # ----- start of no_side_effect operations ----- - _ALWAYS_PURE_FIRST = 30 # ----- start of always_pure operations ----- + _NOSIDEEFFECT_FIRST = 20 # ----- start of no_side_effect operations ----- + _ALWAYS_PURE_FIRST = 20 # ----- start of always_pure operations ----- + CALL_PURE = 20 + # INT_ADD = 30 INT_SUB = 31 INT_MUL = 32 @@ -158,13 +149,7 @@ STRSETITEM = 97 _CANRAISE_FIRST = 100 # ----- start of can_raise operations ----- - _CALL = 100 - CALL__1 = _CALL + typ.INT1 - CALL__2 = _CALL + typ.INT2 - CALL__4 = _CALL + typ.INT4 - CALL__8 = _CALL + typ.INT8 - CALL_PTR = _CALL + typ.PTR - CALL_VOID = _CALL + typ.VOID + CALL = 100 # _OVF_FIRST = 110 INT_ADD_OVF = 110 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Thu Mar 5 11:28:31 2009 @@ -166,7 +166,7 @@ return externfn(n, n+1) res = self.interp_operations(f, [6], policy=StopAtXPolicy(externfn)) assert res == 42 - self.check_history_(int_add=1, int_mul=0, call__4=1) + self.check_history_(int_add=1, int_mul=0, call=1) def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Thu Mar 5 11:28:31 2009 @@ -44,11 +44,11 @@ res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn)) assert res == 2 if self.type_system == 'ootype': - self.check_loops(call_ptr=1, builtin=1) # 'len' remains + self.check_loops(call=1, builtin=1) # 'len' remains else: # 'len' becomes a getfield('num_items') for now in lltype, # which is itself encoded as a 'getfield_gc' - self.check_loops(call_ptr=1, getfield_gc=1) + self.check_loops(call=1, getfield_gc=1) def test_send_to_single_target_method(self): myjitdriver = JitDriver(greens = [], reds = ['i', 'counter']) @@ -72,7 +72,7 @@ res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn), backendopt=True) assert res == 43 - self.check_loops({'call_ptr': 1, 'guard_no_exception': 1, + self.check_loops({'call': 1, 'guard_no_exception': 1, 'getfield_gc': 1, 'int_add': 1, 'merge_point' : 1, 'jump': 1, 'int_gt' : 1, 'guard_true' : 1, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Thu Mar 5 11:28:31 2009 @@ -49,7 +49,7 @@ assert res == 42 # no more list operations in the loop py.test.skip("not a ModifiedList yet") - self.check_loops(call_void=0, call__4=0) + self.check_loops(call=0) def test_lazy_getitem_2(self): py.test.skip("BUG!") @@ -68,7 +68,7 @@ res = self.meta_interp(f, [50], policy=StopAtXPolicy(g)) assert res == f(50) # the list operations stay in the loop - self.check_loops(call_void=1, call__4=2) + self.check_loops(call=3) def test_lazy_getitem_3(self): py.test.skip("in-progress") @@ -81,7 +81,7 @@ res = self.meta_interp(f, [21]) assert res == 42 # two levels of list operations removed from the loop - self.check_loops(call_void=0, call__4=0) + self.check_loops(call=0) def test_lazy_getitem_4(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'lst']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Thu Mar 5 11:28:31 2009 @@ -125,7 +125,7 @@ assert res == f(10) self.check_loop_count(2) self.check_loops(**{self._new_op: 1}) - self.check_loops(int_mul=0, call__4=1) + self.check_loops(int_mul=0, call=1) def test_two_virtuals(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'prev']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Mar 5 11:28:31 2009 @@ -413,7 +413,7 @@ res = self.meta_interp(f, [53], exceptions=False) assert res == -6 - self.check_loops(getfield_gc=0, setfield_gc=0, call__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0, call=0) def test_single_list_implicit(self): py.test.skip("in-progress") @@ -430,7 +430,7 @@ res = self.meta_interp(f, [53], exceptions=False) assert res == -17 - self.check_loops(getfield_gc=0, setfield_gc=0, call__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0, call=0) ##class TestOOtype(ExplicitVirtualizableTests, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Thu Mar 5 11:28:31 2009 @@ -58,7 +58,7 @@ res = self.meta_interp(f, [10], listops=True) assert res == f(10) # one setitem should be gone by now - self.check_loops(call_ptr=1, setarrayitem_gc=1, getarrayitem_gc=1) + self.check_loops(call=1, setarrayitem_gc=1, getarrayitem_gc=1) def test_ll_fixed_setitem_fast(self): jitdriver = JitDriver(greens = [], reds = ['n', 'l']) @@ -76,7 +76,7 @@ res = self.meta_interp(f, [10], listops=True) assert res == 1 py.test.skip("Constant propagation of length missing") - self.check_loops(setarrayitem_gc=0, call_ptr=0, call__4=0) + self.check_loops(setarrayitem_gc=0, call=0) def test_vlist_with_default_read(self): py.test.skip("for now, more support in codewriter needed") From arigo at codespeak.net Thu Mar 5 11:45:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 11:45:09 +0100 (CET) Subject: [pypy-svn] r62574 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090305104509.8C26E168529@codespeak.net> Author: arigo Date: Thu Mar 5 11:45:08 2009 New Revision: 62574 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Remove the 'pure' argument to execute() and record_and_execute(), now that the 'opnum' is enough to have the information. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 5 11:45:08 2009 @@ -355,10 +355,10 @@ self.cpu = cpu self.operations = [] - def execute_and_record(self, opnum, argboxes, result_type, pure): + def execute_and_record(self, opnum, argboxes, result_type): # collect arguments canfold = False - if pure: + if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: for box in argboxes: if not isinstance(box, Const): break @@ -372,7 +372,6 @@ else: self.record(opnum, argboxes, resbox) return resbox - execute_and_record._annspecialcase_ = 'specialize:arg(4)' def record(self, opnum, argboxes, resbox): op = ResOperation(opnum, argboxes, resbox) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 5 11:45:08 2009 @@ -1024,13 +1024,13 @@ vtablebox = ConstInt(vtable) instbox = history.execute_and_record(rop.NEW_WITH_VTABLE, [sizebox, vtablebox], - 'ptr', False) + 'ptr') allocated_boxes.append(instbox) for ad, lgt in storage.list_allocations: sizebox = ConstInt(lgt) listbox = history.execute_and_record(rop.NEW_ARRAY, [ad, sizebox], - 'ptr', False) + 'ptr') allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: fieldbox = box_from_index(allocated_boxes, allocated_lists, @@ -1040,7 +1040,7 @@ index_in_alloc) history.execute_and_record(rop.SETFIELD_GC, [box, ConstInt(ofs), fieldbox], - 'void', False) + 'void') for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) @@ -1048,7 +1048,7 @@ boxes_from_frame, index_in_alloc) history.execute_and_record(rop.SETARRAYITEM_GC, [box, ad, ConstInt(ofs), itembox], - 'void', False) + 'void') ## if storage.setitems: ## #history.execute_and_record('guard_no_exception', [], 'void', False) ## # XXX this needs to check for exceptions somehow Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 5 11:45:08 2009 @@ -233,7 +233,7 @@ exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, [b1, b2], "int", True) + self.execute(rop.%s, [b1, b2], "int") ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', @@ -241,7 +241,7 @@ exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - return self.execute_with_exc(rop.%s, [b1, b2], "int", True) + return self.execute_with_exc(rop.%s, [b1, b2], "int") ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', @@ -249,7 +249,7 @@ exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(rop.%s, [b], "int", True) + self.execute(rop.%s, [b], "int") ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_neg_ovf', @@ -257,7 +257,7 @@ exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - return self.execute_with_exc(rop.%s, [b], "int", True) + return self.execute_with_exc(rop.%s, [b], "int") ''' % (_opimpl, _opimpl.upper())).compile() @arguments() @@ -331,7 +331,7 @@ def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): tp = self.metainterp.cpu.typefor(arraydesc.getint()) self.execute(rop.GETARRAYITEM_GC_PURE, - [arraybox, arraydesc, indexbox], tp, True) + [arraybox, arraydesc, indexbox], tp) @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): @@ -340,36 +340,36 @@ @arguments("box", "constbox") def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int', True) + self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') @arguments("orgpc", "box", "constbox", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): negbox = self.metainterp.history.execute_and_record( - rop.INT_LT, [indexbox, ConstInt(0)], 'int', True) + rop.INT_LT, [indexbox, ConstInt(0)], 'int') negbox = self.implement_guard_value(pc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.history.execute_and_record( - rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int', True) + rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') indexbox = self.metainterp.history.execute_and_record( - rop.INT_ADD, [indexbox, lenbox], 'int', True) + rop.INT_ADD, [indexbox, lenbox], 'int') self.make_result_box(indexbox) @arguments("box") def opimpl_ptr_nonzero(self, box): - self.execute(rop.OONONNULL, [box], 'int', True) + self.execute(rop.OONONNULL, [box], 'int') @arguments("box") def opimpl_ptr_iszero(self, box): - self.execute(rop.OOISNULL, [box], 'int', True) + self.execute(rop.OOISNULL, [box], 'int') @arguments("box", "box") def opimpl_ptr_eq(self, box1, box2): - self.execute(rop.OOIS, [box1, box2], 'int', True) + self.execute(rop.OOIS, [box1, box2], 'int') @arguments("box", "box") def opimpl_ptr_ne(self, box1, box2): - self.execute(rop.OOISNOT, [box1, box2], 'int', True) + self.execute(rop.OOISNOT, [box1, box2], 'int') @arguments("box", "constbox") @@ -379,7 +379,7 @@ @arguments("box", "constbox") def opimpl_getfield_gc_pure(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc], tp, True) + self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc], tp) @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_GC, [box, fielddesc, valuebox], @@ -392,7 +392,7 @@ @arguments("box", "constbox") def opimpl_getfield_raw_pure(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_RAW_PURE, [box, fielddesc], tp, True) + self.execute(rop.GETFIELD_RAW_PURE, [box, fielddesc], tp) @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, fielddesc, valuebox], @@ -414,7 +414,7 @@ def opimpl_residual_call_pure(self, funcbox, calldescr, varargs): tp = self.metainterp.cpu.typefor(calldescr.getint()) args = [funcbox, calldescr] + varargs - return self.execute_with_exc(rop.CALL_PURE, args, tp, True) + return self.execute_with_exc(rop.CALL_PURE, args, tp) ## @arguments("fixedlist", "box", "box") ## def opimpl_list_getitem(self, descr, listbox, indexbox): @@ -478,11 +478,11 @@ @arguments("box") def opimpl_strlen(self, str): - self.execute(rop.STRLEN, [str], 'int', True) + self.execute(rop.STRLEN, [str], 'int') @arguments("box", "box") def opimpl_strgetitem(self, str, index): - self.execute(rop.STRGETITEM, [str, index], 'int', True) + self.execute(rop.STRGETITEM, [str, index], 'int') @arguments("box", "box", "box") def opimpl_strsetitem(self, str, index, newchar): @@ -653,18 +653,16 @@ cls = llmemory.cast_ptr_to_adr(obj.typeptr) return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) - def execute(self, opnum, argboxes, result_type, pure=False): + def execute(self, opnum, argboxes, result_type): resbox = self.metainterp.history.execute_and_record(opnum, argboxes, - result_type, - pure) + result_type) if resbox is not None: self.make_result_box(resbox) - execute._annspecialcase_ = 'specialize:arg(4)' - def execute_with_exc(self, opnum, argboxes, result_type, pure=False): + def execute_with_exc(self, opnum, argboxes, result_type): old_index = len(self.metainterp.history.operations) try: - self.execute(opnum, argboxes, result_type, pure) + self.execute(opnum, argboxes, result_type) except Exception, e: if not we_are_translated(): if not isinstance(e, LLException): @@ -684,7 +682,7 @@ self.metainterp.history.record(opnum, argboxes, resultbox) else: if not self.metainterp.history.generate_anything_since(old_index): - assert pure + assert rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST return False if not we_are_translated(): self.metainterp._debug_history.append(['call', @@ -695,7 +693,6 @@ llmemory.cast_ptr_to_adr(etype)) value_as_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, evalue) return self.metainterp.handle_exception(type_as_int, value_as_gcref) - execute_with_exc._annspecialcase_ = 'specialize:arg(4)' # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 5 11:45:08 2009 @@ -323,7 +323,7 @@ def __init__(self): self.ops = [] - def execute_and_record(self, opnum, args, res_type, pure): + def execute_and_record(self, opnum, args, res_type): self.ops.append((opnum, args)) if res_type != 'void': return 'allocated' From tverwaes at codespeak.net Thu Mar 5 13:04:50 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 5 Mar 2009 13:04:50 +0100 (CET) Subject: [pypy-svn] r62576 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305120450.5971616853C@codespeak.net> Author: tverwaes Date: Thu Mar 5 13:04:48 2009 New Revision: 62576 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: some refactorings to make sure we can reuse window and background on other surfaces as well. Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Thu Mar 5 13:04:48 2009 @@ -8,8 +8,7 @@ from pypy.lang.gameboy import constants import time -use_rsdl = False -use_tile_screen = True +use_rsdl = True if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper @@ -110,24 +109,14 @@ def __init__(self): VideoDriver.__init__(self) self.create_screen() - #self.create_tile_screen() self.map = [] - #def create_tile_screen(self): - # if use_rsdl and use_tile_screen: - # self.tile_screen = RSDL.SetVideoMode(128, 128, 32, 0) - def create_screen(self): if use_rsdl: self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): if use_rsdl: - # if use_tile_screen: - # RSDL.LockSurface(self.tile_screen) - # self.draw_tile_pixels() - # RSDL.UnlockSurface(self.tile_screen) - # RSDL.Flip(self.tile_screen) RSDL.LockSurface(self.screen) self.draw_pixels() RSDL.UnlockSurface(self.screen) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Thu Mar 5 13:04:48 2009 @@ -390,11 +390,11 @@ """ Specifies the upper/left positions of the Window area. (The window is an alternate background area which can be displayed above of the normal - background. OBJs (sprites) may be still displayed above or behinf the + background. OBJs (sprites) may be still displayed above or behind the window, just as for normal BG.) The window becomes visible (if enabled) when positions are set in range WX=0..166, WY=0..143. A postion of WX=7, WY=0 locates the window at - upper left, it is then completly covering normal background. + upper left, it is then completely covering normal background. """ self.window.y = data @@ -454,12 +454,24 @@ self.driver.update_display() def draw_line(self): + if self.control.background_and_window_lower_tile_data_selected: + tile_index_flip = 0x00 + else: + tile_index_flip = 0x80 + tile_data = self.get_selected_tile_data_space() + if self.background.enabled: - self.background.draw_line(self.line_y) + self.background.draw_line(self.line_y, + tile_data, + tile_index_flip, + self.line) else: - self.background.draw_clean_line(self.line_y) + self.background.draw_clean_line(self.line) if self.window.enabled: - self.window.draw_line(self.line_y) + self.window.draw_line(self.line_y, + tile_data, + tile_index_flip, + self.line) if self.control.sprites_enabled: self.draw_sprites_line() self.draw_pixels_line() Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Thu Mar 5 13:04:48 2009 @@ -241,15 +241,13 @@ def reset(self): raise Exception("Not implemented") - def draw_tiles(self, x_start, tile_group, y, group_index=0): + def draw_tiles(self, x_start, tile_group, y, tile_data, index_flip, line, group_index=0): x = x_start - tile_data = self.video.get_selected_tile_data_space() while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: tile_index = tile_group[group_index % TILE_GROUP_SIZE] - if not self.video.control.background_and_window_lower_tile_data_selected: - tile_index ^= 0x80 + tile_index ^= index_flip tile = tile_data[tile_index] - tile.draw(self.video.line, x, y) + tile.draw(line, x, y) group_index += 1 x += SPRITE_SIZE @@ -266,14 +264,16 @@ if self.line_y == 0 and self.video.line_y > self.y: self.line_y = GAMEBOY_SCREEN_HEIGHT - def draw_line(self, line_y): + def draw_line(self, line_y, tile_data, tile_index_flip, line): if line_y >= self.y and self.x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE-1 and \ self.line_y < GAMEBOY_SCREEN_HEIGHT: tile_map = self.get_tile_map_space() tile_group = tile_map[self.line_y >> 5] - self.draw_tiles(self.x + 1, tile_group, self.line_y) + self.draw_tiles(self.x + 1, tile_group, + self.line_y, tile_data, + tile_index_flip, line) self.line_y += 1 # ----------------------------------------------------------------------------- @@ -288,14 +288,16 @@ self.enabled = True self.upper_tile_map_selected = False - def draw_clean_line(self, line_y): - for x in range(SPRITE_SIZE+GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE): - self.video.line[x] = 0x00 + def draw_clean_line(self, line): + for x in range(len(line)): + line[x] = 0x00 - def draw_line(self, line_y): + def draw_line(self, line_y, tile_data, tile_index_flip, line): y = (self.scroll_y + line_y) & 0xFF x = self.scroll_x tile_map = self.get_tile_map_space() tile_group = tile_map[y >> 3] - self.draw_tiles(8 - (x % 8), tile_group, y, x >> 3) + self.draw_tiles(8 - (x % 8), tile_group, + y, tile_data, + tile_index_flip, line, x >> 3) From arigo at codespeak.net Thu Mar 5 14:04:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 14:04:02 +0100 (CET) Subject: [pypy-svn] r62577 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090305130402.4E780168059@codespeak.net> Author: arigo Date: Thu Mar 5 14:04:00 2009 New Revision: 62577 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Move the actual execution of an operation out of the class History and into the class OOMetaInterp. Note that now execute_and_record() can be specialized according to the operation it runs. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 5 14:04:00 2009 @@ -709,7 +709,7 @@ ## self._eventualy_builtin(op.result, False) ## return if oopspec_name.endswith('_foldable'): - opname = 'residual_call_pure' + opname = 'residual_call_pure' # XXX not for possibly-raising calls else: opname = 'residual_call' calldescr = self.cpu.calldescrof(argtypes, resulttype) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 5 14:04:00 2009 @@ -324,12 +324,12 @@ op = operations[0] assert op.opnum in (rop.MERGE_POINT, rop.CATCH) seen = dict.fromkeys(op.args) - for op in operations[1:]: + for op in operations: for box in op.args: if isinstance(box, Box): assert box in seen elif isinstance(box, Const): - assert op.opnum not in (rop.MERGE_POINT, rop.CATCH), ( + assert op.opnum != rop.MERGE_POINT, ( "no Constant arguments allowed in: %s" % (op,)) box = op.result if box is not None: @@ -348,49 +348,21 @@ class Matcher(object): pass - class RunningMatcher(Matcher): - def __init__(self, cpu): self.cpu = cpu self.operations = [] - def execute_and_record(self, opnum, argboxes, result_type): - # collect arguments - canfold = False - if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: - for box in argboxes: - if not isinstance(box, Const): - break - else: - canfold = True - # really run this operation - resbox = self.cpu.execute_operation(opnum, argboxes, result_type) - # collect the result(s) - if canfold: - resbox = resbox.constbox() - else: - self.record(opnum, argboxes, resbox) - return resbox - +class History(RunningMatcher): def record(self, opnum, argboxes, resbox): op = ResOperation(opnum, argboxes, resbox) self.operations.append(op) return op - def generate_anything_since(self, old_index): - return len(self.operations) > old_index - -class History(RunningMatcher): - pass - class BlackHole(RunningMatcher): - def record(self, step, argboxes, resbox): + def record(self, opnum, argboxes, resbox): return None - def generate_anything_since(self, old_index): - return True - def mp_eq(greenkey1, greenkey2): assert len(greenkey1) == len(greenkey2) for i in range(len(greenkey1)): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 5 14:04:00 2009 @@ -1013,7 +1013,6 @@ allocated_boxes = [] allocated_lists = [] storage = guard_op.storage_info - history = metainterp.history for vtable in storage.allocations: if metainterp.cpu.translate_support_code: @@ -1022,15 +1021,15 @@ else: sizebox = ConstInt(metainterp.class_sizes[vtable]) vtablebox = ConstInt(vtable) - instbox = history.execute_and_record(rop.NEW_WITH_VTABLE, - [sizebox, vtablebox], - 'ptr') + instbox = metainterp.execute_and_record(rop.NEW_WITH_VTABLE, + [sizebox, vtablebox], + 'ptr') allocated_boxes.append(instbox) for ad, lgt in storage.list_allocations: sizebox = ConstInt(lgt) - listbox = history.execute_and_record(rop.NEW_ARRAY, - [ad, sizebox], - 'ptr') + listbox = metainterp.execute_and_record(rop.NEW_ARRAY, + [ad, sizebox], + 'ptr') allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: fieldbox = box_from_index(allocated_boxes, allocated_lists, @@ -1038,17 +1037,17 @@ box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) - history.execute_and_record(rop.SETFIELD_GC, - [box, ConstInt(ofs), fieldbox], - 'void') + metainterp.execute_and_record(rop.SETFIELD_GC, + [box, ConstInt(ofs), fieldbox], + 'void') for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) - history.execute_and_record(rop.SETARRAYITEM_GC, - [box, ad, ConstInt(ofs), itembox], - 'void') + metainterp.execute_and_record(rop.SETARRAYITEM_GC, + [box, ad, ConstInt(ofs), itembox], + 'void') ## if storage.setitems: ## #history.execute_and_record('guard_no_exception', [], 'void', False) ## # XXX this needs to check for exceptions somehow Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 5 14:04:00 2009 @@ -344,14 +344,14 @@ @arguments("orgpc", "box", "constbox", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): - negbox = self.metainterp.history.execute_and_record( + negbox = self.metainterp.execute_and_record( rop.INT_LT, [indexbox, ConstInt(0)], 'int') negbox = self.implement_guard_value(pc, negbox) if negbox.getint(): # the index is < 0; add the array length to it - lenbox = self.metainterp.history.execute_and_record( + lenbox = self.metainterp.execute_and_record( rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') - indexbox = self.metainterp.history.execute_and_record( + indexbox = self.metainterp.execute_and_record( rop.INT_ADD, [indexbox, lenbox], 'int') self.make_result_box(indexbox) @@ -414,7 +414,7 @@ def opimpl_residual_call_pure(self, funcbox, calldescr, varargs): tp = self.metainterp.cpu.typefor(calldescr.getint()) args = [funcbox, calldescr] + varargs - return self.execute_with_exc(rop.CALL_PURE, args, tp) + self.execute(rop.CALL_PURE, args, tp) ## @arguments("fixedlist", "box", "box") ## def opimpl_list_getitem(self, descr, listbox, indexbox): @@ -654,15 +654,17 @@ return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) def execute(self, opnum, argboxes, result_type): - resbox = self.metainterp.history.execute_and_record(opnum, argboxes, - result_type) + resbox = self.metainterp.execute_and_record(opnum, argboxes, + result_type) if resbox is not None: self.make_result_box(resbox) + execute._annspecialcase_ = 'specialize:arg(1)' def execute_with_exc(self, opnum, argboxes, result_type): old_index = len(self.metainterp.history.operations) try: - self.execute(opnum, argboxes, result_type) + resbox = self.metainterp.cpu.execute_operation(opnum, argboxes, + result_type) except Exception, e: if not we_are_translated(): if not isinstance(e, LLException): @@ -672,23 +674,22 @@ evalue = cast_instance_to_base_ptr(e) etype = evalue.typeptr if result_type == 'void': - resultbox = None + resbox = None else: if result_type == 'ptr': - resultbox = BoxPtr() + resbox = BoxPtr() else: - resultbox = BoxInt() - self.make_result_box(resultbox) - self.metainterp.history.record(opnum, argboxes, resultbox) + resbox = BoxInt() else: - if not self.metainterp.history.generate_anything_since(old_index): - assert rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST - return False if not we_are_translated(): self.metainterp._debug_history.append(['call', argboxes[0], argboxes[1:]]) etype = lltype.nullptr(rclass.OBJECT_VTABLE) evalue = lltype.nullptr(rclass.OBJECT) + # record the operation in the history + self.metainterp.history.record(opnum, argboxes, resbox) + if resbox is not None: + self.make_result_box(resbox) type_as_int = self.metainterp.cpu.cast_adr_to_int( llmemory.cast_ptr_to_adr(etype)) value_as_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, evalue) @@ -767,6 +768,30 @@ self.history = None self.framestack = None + def _all_constants(self, boxes): + for box in boxes: + if not isinstance(box, Const): + return False + return True + + def execute_and_record(self, opnum, argboxes, result_type): + # execute the operation first + resbox = self.cpu.execute_operation(opnum, argboxes, result_type) + # check if the operation can be constant-folded away + canfold = False + if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: + # this part disappears if execute() is specialized for an + # opnum that is not within the range + assert resbox is not None + canfold = self._all_constants(argboxes) + if canfold: + resbox = resbox.constbox() + # record the operation if not constant-folded away + if not canfold: + self.history.record(opnum, argboxes, resbox) + return resbox + execute_and_record._annspecialcase_ = 'specialize:arg(1)' + def interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, # a ContinueRunningNormally, or a GenerateMergePoint exception. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 5 14:04:00 2009 @@ -319,8 +319,12 @@ assert guard_op.storage_info.setfields == [(0, E.ofs_value, -2)] def test_E_rebuild_after_failure(): - class FakeHistory(object): + class FakeMetaInterp(object): def __init__(self): + self.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): + E.size_of_node} + self.cpu = cpu + self.cpu.translate_support_code = False self.ops = [] def execute_and_record(self, opnum, args, res_type): @@ -329,14 +333,6 @@ return 'allocated' else: return None - - class FakeMetaInterp(object): - def __init__(self): - self.history = FakeHistory() - self.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): - E.size_of_node} - self.cpu = cpu - self.cpu.translate_support_code = False spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() @@ -353,7 +349,7 @@ (rop.NEW_WITH_VTABLE, [E.sizebox, ConstInt(vt)]), (rop.SETFIELD_GC, ['allocated', ConstInt(E.ofs_value), v_v_b]) ] - assert expected == fake_metainterp.history.ops + assert expected == fake_metainterp.ops assert newboxes == [v_sum_b, 'allocated'] # ____________________________________________________________ From tverwaes at codespeak.net Thu Mar 5 14:35:18 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 5 Mar 2009 14:35:18 +0100 (CET) Subject: [pypy-svn] r62578 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305133518.D9E53169E19@codespeak.net> Author: tverwaes Date: Thu Mar 5 14:35:16 2009 New Revision: 62578 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: whoops, now the window draws correctly :) seems like there is no visual noise left ... but who knows Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Thu Mar 5 14:35:16 2009 @@ -131,13 +131,6 @@ color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] RSDL_helper.set_pixel(self.screen, x, y, color) - def draw_tile_pixels(self): - for y in range(128): - for x in range(128): - #color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] - #RSDL_helper.set_pixel(self.screen, x, y, color) - pass - def draw_ascii_pixels(self): str = [] for y in range(self.height): Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Thu Mar 5 14:35:16 2009 @@ -269,7 +269,7 @@ self.line_y < GAMEBOY_SCREEN_HEIGHT: tile_map = self.get_tile_map_space() - tile_group = tile_map[self.line_y >> 5] + tile_group = tile_map[self.line_y >> 3] self.draw_tiles(self.x + 1, tile_group, self.line_y, tile_data, From fijal at codespeak.net Thu Mar 5 14:48:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 14:48:34 +0100 (CET) Subject: [pypy-svn] r62580 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305134834.2DDE7168561@codespeak.net> Author: fijal Date: Thu Mar 5 14:48:33 2009 New Revision: 62580 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: turn off weakrefs and sre (they expose bugs in ll2ctypes when tried on top of x86 backend) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Mar 5 14:48:33 2009 @@ -16,12 +16,16 @@ config.objspace.nofaking = True config.objspace.allworkingmodules = False config.objspace.usemodules.pypyjit = True +config.objspace.usemodules._weakref = False +config.objspace.usemodules._sre = False +config.translation.rweakref = False # XXX set_pypy_opt_level(config, level='0') config.objspace.std.multimethods = 'mrd' config.objspace.std.builtinshortcut = True multimethod.Installer = multimethod.InstallerVersion2 print config +import sys, pdb space = Space(config) w_dict = space.newdict() @@ -50,9 +54,14 @@ from pypy.rpython.test.test_llinterp import get_interpreter # first annotate, rtype, and backendoptimize PyPy - interp, graph = get_interpreter(entry_point, [], backendopt=True, - config=config, - policy=PyPyAnnotatorPolicy(space)) + try: + interp, graph = get_interpreter(entry_point, [], backendopt=True, + config=config, + policy=PyPyAnnotatorPolicy(space)) + except Exception, e: + print '%s: %s' % (e.__class__, e) + pdb.post_mortem(sys.exc_info()[2]) + # parent process loop: spawn a child, wait for the child to finish, # print a message, and restart From tverwaes at codespeak.net Thu Mar 5 15:24:24 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 5 Mar 2009 15:24:24 +0100 (CET) Subject: [pypy-svn] r62581 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305142424.A0F55169E0C@codespeak.net> Author: tverwaes Date: Thu Mar 5 15:24:23 2009 New Revision: 62581 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: moving responsibility Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Thu Mar 5 15:24:23 2009 @@ -510,10 +510,9 @@ def draw_pixels_line(self): self.update_palette() - pixels = self.driver.get_pixels() - offset = self.line_y * self.driver.get_width() - SPRITE_SIZE - for x in range(SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE): - pixels[offset + x] = self.palette[self.line[x]] + for x in range(0, GAMEBOY_SCREEN_WIDTH): + color = self.palette[self.line[SPRITE_SIZE + x]] + self.driver.draw_pixel(x, self.line_y, color) def update_palette(self): if not self.dirty: return @@ -551,6 +550,9 @@ def clear_pixels(self): self.pixels = [0] * self.width * self.height + + def draw_pixel(self, x, y, color): + self.pixels[y * self.width + x] = color def get_width(self): return self.width From tverwaes at codespeak.net Thu Mar 5 15:30:43 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 5 Mar 2009 15:30:43 +0100 (CET) Subject: [pypy-svn] r62582 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090305143043.59B44169E10@codespeak.net> Author: tverwaes Date: Thu Mar 5 15:30:40 2009 New Revision: 62582 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/video.py Log: removing ugly indexes Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Thu Mar 5 15:30:40 2009 @@ -145,7 +145,7 @@ if string: return ["#", "%", "+", ".", " "][self.get_pixel_color(x, y)] else: - return self.pixels[x+self.width*y] + return self.pixels[y][x] # JOYPAD DRIVER ---------------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Thu Mar 5 15:30:40 2009 @@ -504,7 +504,7 @@ assert video.line == [0] * (8+160+8) video.line = range(8+160+8) - video.background.draw_clean_line(video.line_y) + video.background.draw_clean_line(video.line) assert video.line == [0] * (8+160+8) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Thu Mar 5 15:30:40 2009 @@ -512,7 +512,7 @@ self.update_palette() for x in range(0, GAMEBOY_SCREEN_WIDTH): color = self.palette[self.line[SPRITE_SIZE + x]] - self.driver.draw_pixel(x, self.line_y, color) + self.driver.draw_gb_pixel(x, self.line_y, color) def update_palette(self): if not self.dirty: return @@ -549,20 +549,16 @@ self.clear_pixels() def clear_pixels(self): - self.pixels = [0] * self.width * self.height + self.pixels = [[0] * self.width for i in range(self.height)] + + def draw_gb_pixel(self, x, y, color): + self.pixels[y][x] = color - def draw_pixel(self, x, y, color): - self.pixels[y * self.width + x] = color - def get_width(self): return self.width def get_height(self): return self.height - def get_pixels(self): - return self.pixels - def update_display(self): self.clear_pixels() - From cami at codespeak.net Thu Mar 5 15:31:24 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 5 Mar 2009 15:31:24 +0100 (CET) Subject: [pypy-svn] r62583 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305143124.A05D6169E13@codespeak.net> Author: cami Date: Thu Mar 5 15:31:23 2009 New Revision: 62583 Modified: pypy/trunk/pypy/lang/gameboy/sound.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: compacting draw_pixels_line and conquerred the array bounds ;) Modified: pypy/trunk/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/sound.py (original) +++ pypy/trunk/pypy/lang/gameboy/sound.py Thu Mar 5 15:31:23 2009 @@ -41,13 +41,13 @@ self.update_envelope_and_volume() self.update_frequency_and_playback() - def update_enabled(): + def update_enabled(self): pass - def update_envelope_and_volume(): + def update_envelope_and_volume(self): pass - def update_frequency_and_playback(): + def update_frequency_and_playback(self): pass def get_length(self): @@ -167,11 +167,11 @@ return sweep_steps = (self.sample_sweep & 0x07) if sweep_steps != 0: - self.update_frequency() + self.update_frequency(sweep_steps) self.sample_sweep_length += (SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) - def update_frequency(self): + def update_frequency(self, sweep_steps): frequency = ((self.playback & 0x07) << 8) + self.frequency if (self.sample_sweep & 0x08) != 0: frequency -= frequency >> sweep_steps Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Thu Mar 5 15:31:23 2009 @@ -4,7 +4,20 @@ # ----------------------------------------------------------------------------- class Sprite(object): + """ + 8px + +--------+ + | | Normal Sprite size: 8 x 8px + | upper | 8px + | | + (x,y)------+ + | | Big Sprite size: 8 x 16px + | lower | 8px + | | + +--------+ + 8x + """ def __init__(self, video): self.video = video self.big_size = False @@ -116,18 +129,6 @@ value += int(self.palette_number) << 4 value += self.rest_attributes_and_flags return value - - def hide_check(self): - if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: - self.hidden = True - elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: - self.hidden = True - else: - self.hidden = False - return self.hidden - - def get_tile_number(self): - return self.tile_number def get_width(self): return SPRITE_SIZE @@ -137,41 +138,55 @@ return 2*SPRITE_SIZE else: return SPRITE_SIZE - - def intersects_current_line(self): - y = self.current_line_y() - return y >= 0 and y < self.get_height() - - def is_shown_on_current_line(self): - return not self.hidden and self.intersects_current_line() - - def current_line_y(self): - return (self.video.line_y - self.y) + 2 * SPRITE_SIZE + + def get_tile_number(self): + return self.tile_number def get_tile_address(self): address = self.get_tile_number() if self.big_size: address &= 0xFE return address - + + def get_tile_for_current_line(self): + lower = self.current_line_y() < SPRITE_SIZE + if lower ^ (self.big_size and self.y_flipped): + return self.get_tile() + else: + return self.get_lower_tile() + def get_tile(self): return self.video.get_tile_at(self.get_tile_address()) def get_lower_tile(self): return self.video.get_tile_at(self.get_tile_address() + 1) + + def hide_check(self): + """returns and caches the general visibility of a Sprite. + Updates the hidden property. See also intersects_current_line.""" + if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: + self.hidden = True + elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: + self.hidden = True + else: + self.hidden = False + return self.hidden + + def intersects_current_line(self): + y = self.current_line_y() + return y >= 0 and y < self.get_height() + + def is_shown_on_current_line(self): + return not self.hidden and self.intersects_current_line() + + def current_line_y(self): + return (self.video.line_y - self.y) + 2 * SPRITE_SIZE def get_draw_y(self): y = self.current_line_y() if self.y_flipped: y = self.get_height() - 1 - y - return y - - def get_tile_for_current_line(self): - lower = self.current_line_y() < SPRITE_SIZE - if lower ^ (self.big_size and self.y_flipped): - return self.get_tile() - else: - return self.get_lower_tile() + return y def draw(self, lastx): self.get_tile_for_current_line().draw_for_sprite(self, self.video.line, lastx) From fijal at codespeak.net Thu Mar 5 15:44:45 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 15:44:45 +0100 (CET) Subject: [pypy-svn] r62584 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090305144445.982B016852D@codespeak.net> Author: fijal Date: Thu Mar 5 15:44:45 2009 New Revision: 62584 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: int_mod_ovf and int_mod_ovf_zer Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 15:44:45 2009 @@ -68,6 +68,7 @@ 'int_neg' : (('int',), 'int'), 'int_invert' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), + 'int_mod_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), 'int_neg_ovf' : (('int',), 'int'), @@ -866,7 +867,7 @@ return res for _opname in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', - 'int_neg_ovf', + 'int_neg_ovf', 'int_mod_ovf', ]: exec py.code.Source(''' def op_%s(self, *args): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 5 15:44:45 2009 @@ -162,7 +162,7 @@ class BytecodeMaker(object): - debug = True + debug = False def __init__(self, codewriter, graph, portal): self.codewriter = codewriter @@ -197,6 +197,8 @@ self.bytecode._labelpos = labelpos if self.debug: self.bytecode.dump() + else: + print repr(self.bytecode) def const_position(self, constvalue): """Generate a constant of the given value. @@ -466,6 +468,10 @@ def serialize_op_int_add_nonneg_ovf(self, op): self.default_serialize_op(op, 'int_add_ovf') + def serialize_op_int_mod_ovf_zer(self, op): + # XXX handle ZeroDivisionError + self.default_serialize_op(op, 'int_mod_ovf') + def serialize_op_hint(self, op): hints = op.args[1].value if hints.get('promote') and op.args[0].concretetype is not lltype.Void: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 5 15:44:45 2009 @@ -236,7 +236,7 @@ self.execute(rop.%s, [b1, b2], "int") ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', + for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', 'int_mod_ovf', ]: exec py.code.Source(''' @arguments("box", "box") Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 5 15:44:45 2009 @@ -156,7 +156,8 @@ INT_SUB_OVF = 111 INT_MUL_OVF = 112 INT_NEG_OVF = 113 - _OVF_LAST = 113 + INT_MOD_OVF = 114 + _OVF_LAST = 114 _CANRAISE_LAST = 119 # ----- end of can_raise operations ----- _LAST = 119 # for the backend to add more internal operations Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Thu Mar 5 15:44:45 2009 @@ -309,6 +309,17 @@ res = self.meta_interp(f, [1]) assert res == expected + def test_int_mod_ovf_zer(self): + def f(x, y): + try: + return ovfcheck(x%y) + except ZeroDivisionError: + return 1 + except OverflowError: + return 2 + + res = self.interp_operations(f, [1, 2]) + assert res == 1 class MyError(Exception): def __init__(self, n): From fijal at codespeak.net Thu Mar 5 15:53:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 15:53:17 +0100 (CET) Subject: [pypy-svn] r62585 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090305145317.CFEED16852D@codespeak.net> Author: fijal Date: Thu Mar 5 15:53:17 2009 New Revision: 62585 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: let jit see a tiny bit more of pypy Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Thu Mar 5 15:53:17 2009 @@ -80,7 +80,7 @@ import pypy # -------------------- - for binop in 'ADD SUBTRACT MULTIPLY AND OR XOR'.split(): + for binop in 'MODULO ADD SUBTRACT MULTIPLY AND OR XOR'.split(): self.seebinary(binop) for cmpname in 'lt le eq ne ge gt'.split(): self.seecmp(cmpname) @@ -108,6 +108,10 @@ pypy.objspace.std.boolobject.nonzero__Bool) self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, pypy.objspace.std.boolobject.nonzero__Bool) + self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, + pypy.objspace.std.intobject.nonzero__Int) + self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, + pypy.objspace.std.intobject.nonzero__Int) # #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, From fijal at codespeak.net Thu Mar 5 15:53:45 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 15:53:45 +0100 (CET) Subject: [pypy-svn] r62586 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305145345.290E216855F@codespeak.net> Author: fijal Date: Thu Mar 5 15:53:44 2009 New Revision: 62586 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: example of bridge. working so far Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Thu Mar 5 15:53:44 2009 @@ -5,7 +5,10 @@ i = 0 while i < 100: # XXX implement inplace_add method for ints - i += 3 + if i % 2: + i = i + 3 + else: + i = i + 1 print i # should print 102 f() From arigo at codespeak.net Thu Mar 5 16:07:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 16:07:03 +0100 (CET) Subject: [pypy-svn] r62587 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305150703.40F5A168488@codespeak.net> Author: arigo Date: Thu Mar 5 16:07:01 2009 New Revision: 62587 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: Start to write individual backend-specific operations. Only arraylen_gc for now. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 16:07:01 2009 @@ -883,6 +883,12 @@ # ____________________________________________________________ +def do_arraylen_gc(array): + array = array._obj.container + return array.getlength() + +# ____________________________________________________________ + def setannotation(func, annotation, specialize_as_constant=False): @@ -961,3 +967,5 @@ setannotation(new_memo_cast, s_MemoCast) setannotation(cast_adr_to_int, annmodel.SomeInteger()) setannotation(cast_int_to_adr, annmodel.SomeAddress()) + +setannotation(do_arraylen_gc, annmodel.SomeInteger()) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 16:07:01 2009 @@ -307,6 +307,12 @@ def cast_int_to_adr(self, int): return llimpl.cast_int_to_adr(self.memo_cast, int) + # ---------- the backend-dependent operations ---------- + + def do_arraylen_gc(self, args): + array = args[0].getptr_base() + return history.BoxInt(llimpl.do_arraylen_gc(array)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 16:07:01 2009 @@ -153,3 +153,12 @@ [BoxInt(10), BoxInt(2)], "int", expected_class = BoxInt, expected_value = 8) + + def test_do_operations(self): + cpu = CPU(None) + A = lltype.GcArray(lltype.Signed) + a = lltype.malloc(A, 5) + descrbox = ConstInt(cpu.arraydescrof(A)) + x = cpu.do_arraylen_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox]) + assert x.value == 5 From arigo at codespeak.net Thu Mar 5 16:11:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 16:11:45 +0100 (CET) Subject: [pypy-svn] r62588 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305151145.B510A168486@codespeak.net> Author: arigo Date: Thu Mar 5 16:11:43 2009 New Revision: 62588 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: Two more operations. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 16:11:43 2009 @@ -887,6 +887,14 @@ array = array._obj.container return array.getlength() +def do_strlen(string): + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return len(str.chars) + +def do_strgetitem(string, index): + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + return ord(str.chars[index]) + # ____________________________________________________________ @@ -969,3 +977,5 @@ setannotation(cast_int_to_adr, annmodel.SomeAddress()) setannotation(do_arraylen_gc, annmodel.SomeInteger()) +setannotation(do_strlen, annmodel.SomeInteger()) +setannotation(do_strgetitem, annmodel.SomeInteger()) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 16:11:43 2009 @@ -313,6 +313,15 @@ array = args[0].getptr_base() return history.BoxInt(llimpl.do_arraylen_gc(array)) + def do_strlen(cpu, args): + string = args[0].getptr_base() + return history.BoxInt(llimpl.do_strlen(string)) + + def do_strgetitem(cpu, args): + string = args[0].getptr_base() + index = args[1].getint() + return history.BoxInt(llimpl.do_strgetitem(string, index)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 16:11:43 2009 @@ -1,5 +1,5 @@ import py -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, rstr from pypy.rpython.test.test_llinterp import interpret from pypy.rlib.unroll import unrolling_iterable @@ -156,9 +156,20 @@ def test_do_operations(self): cpu = CPU(None) + # A = lltype.GcArray(lltype.Signed) a = lltype.malloc(A, 5) descrbox = ConstInt(cpu.arraydescrof(A)) x = cpu.do_arraylen_gc( [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox]) assert x.value == 5 + # + s = rstr.mallocstr(6) + x = cpu.do_strlen( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))]) + assert x.value == 6 + # + s.chars[3] = 'X' + x = cpu.do_strgetitem( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)]) + assert x.value == ord('X') From arigo at codespeak.net Thu Mar 5 16:23:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 16:23:32 +0100 (CET) Subject: [pypy-svn] r62589 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305152332.C3F9B168556@codespeak.net> Author: arigo Date: Thu Mar 5 16:23:32 2009 New Revision: 62589 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: getarrayitem. Phew, will take a while. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 16:23:32 2009 @@ -440,19 +440,10 @@ return res def as_int(self, x): - TP = lltype.typeOf(x) - if isinstance(TP, lltype.Ptr): - assert TP.TO._gckind == 'raw' - return cast_adr_to_int(self.memocast, llmemory.cast_ptr_to_adr(x)) - if TP == llmemory.Address: - return cast_adr_to_int(self.memocast, x) - return lltype.cast_primitive(lltype.Signed, x) - + return cast_to_int(x, self.memocast) + def as_ptr(self, x): - if isinstance(lltype.typeOf(x), lltype.Ptr): - return lltype.cast_opaque_ptr(llmemory.GCREF, x) - else: - return x + return cast_to_ptr(x) def log_progress(self): count = sum(_stats.exec_counters.values()) @@ -460,6 +451,22 @@ log.trace('ran %d operations, %d jumps' % (count, count_jumps)) +def cast_to_int(x, memocast): + TP = lltype.typeOf(x) + if isinstance(TP, lltype.Ptr): + assert TP.TO._gckind == 'raw' + return cast_adr_to_int(memocast, llmemory.cast_ptr_to_adr(x)) + if TP == llmemory.Address: + return cast_adr_to_int(memocast, x) + return lltype.cast_primitive(lltype.Signed, x) + +def cast_to_ptr(x): + if isinstance(lltype.typeOf(x), lltype.Ptr): + return lltype.cast_opaque_ptr(llmemory.GCREF, x) + else: + return x + + def new_frame(memocast): frame = Frame(memocast) return _to_opaque(frame) @@ -895,6 +902,14 @@ str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return ord(str.chars[index]) +def do_getarrayitem_gc_int(array, index, memocast): + array = array._obj.container + return cast_to_int(array.getitem(index), memocast) + +def do_getarrayitem_gc_ptr(array, index): + array = array._obj.container + return cast_to_ptr(array.getitem(index)) + # ____________________________________________________________ @@ -979,3 +994,5 @@ setannotation(do_arraylen_gc, annmodel.SomeInteger()) setannotation(do_strlen, annmodel.SomeInteger()) setannotation(do_strgetitem, annmodel.SomeInteger()) +setannotation(do_getarrayitem_gc_int, annmodel.SomeInteger()) +setannotation(do_getarrayitem_gc_ptr, annmodel.SomePtr(llmemory.GCREF)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 16:23:32 2009 @@ -313,15 +313,25 @@ array = args[0].getptr_base() return history.BoxInt(llimpl.do_arraylen_gc(array)) - def do_strlen(cpu, args): + def do_strlen(self, args): string = args[0].getptr_base() return history.BoxInt(llimpl.do_strlen(string)) - def do_strgetitem(cpu, args): + def do_strgetitem(self, args): string = args[0].getptr_base() index = args[1].getint() return history.BoxInt(llimpl.do_strgetitem(string, index)) + def do_getarrayitem_gc(self, args): + array = args[0].getptr_base() + arraydescr = args[1].getint() + index = args[2].getint() + if self.typefor(arraydescr) == 'ptr': + return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) + else: + return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, + self.memo_cast)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 16:23:32 2009 @@ -157,13 +157,28 @@ def test_do_operations(self): cpu = CPU(None) # - A = lltype.GcArray(lltype.Signed) + A = lltype.GcArray(lltype.Char) + descrbox_A = ConstInt(cpu.arraydescrof(A)) a = lltype.malloc(A, 5) - descrbox = ConstInt(cpu.arraydescrof(A)) x = cpu.do_arraylen_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A]) assert x.value == 5 # + a[2] = 'Y' + x = cpu.do_getarrayitem_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A, + BoxInt(2)]) + assert x.value == ord('Y') + # + B = lltype.GcArray(lltype.Ptr(A)) + descrbox_B = ConstInt(cpu.arraydescrof(B)) + b = lltype.malloc(B, 4) + b[3] = a + x = cpu.do_getarrayitem_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, + BoxInt(3)]) + assert x.getptr(lltype.Ptr(A)) == a + # s = rstr.mallocstr(6) x = cpu.do_strlen( [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))]) From arigo at codespeak.net Thu Mar 5 16:39:42 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 16:39:42 +0100 (CET) Subject: [pypy-svn] r62590 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305153942.E1AB9169E0C@codespeak.net> Author: arigo Date: Thu Mar 5 16:39:40 2009 New Revision: 62590 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: getfield_gc. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 16:39:40 2009 @@ -910,6 +910,18 @@ array = array._obj.container return cast_to_ptr(array.getitem(index)) +def do_getfield_gc_int(struct, fielddesc, memocast): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) + x = getattr(ptr, fieldname) + return cast_to_int(x, memocast) + +def do_getfield_gc_ptr(struct, fielddesc): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) + x = getattr(ptr, fieldname) + return cast_to_ptr(x) + # ____________________________________________________________ @@ -996,3 +1008,5 @@ setannotation(do_strgetitem, annmodel.SomeInteger()) setannotation(do_getarrayitem_gc_int, annmodel.SomeInteger()) setannotation(do_getarrayitem_gc_ptr, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_getfield_gc_int, annmodel.SomeInteger()) +setannotation(do_getfield_gc_ptr, annmodel.SomePtr(llmemory.GCREF)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 16:39:40 2009 @@ -332,6 +332,17 @@ return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, self.memo_cast)) + def do_getfield_gc(self, args): + struct = args[0].getptr_base() + fielddescr = args[1].getint() + if self.typefor(fielddescr) == 'ptr': + return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, + fielddescr)) + else: + return history.BoxInt(llimpl.do_getfield_gc_int(struct, + fielddescr, + self.memo_cast)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 16:39:40 2009 @@ -177,6 +177,7 @@ x = cpu.do_getarrayitem_gc( [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, BoxInt(3)]) + assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # s = rstr.mallocstr(6) @@ -188,3 +189,20 @@ x = cpu.do_strgetitem( [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)]) assert x.value == ord('X') + # + S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) + descrfld_x = cpu.fielddescrof(S, 'x') + s = lltype.malloc(S) + s.x = 'Z' + x = cpu.do_getfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_x)]) + assert x.value == ord('Z') + # + descrfld_y = cpu.fielddescrof(S, 'y') + s.y = a + x = cpu.do_getfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_y)]) + assert isinstance(x, BoxPtr) + assert x.getptr(lltype.Ptr(A)) == a From arigo at codespeak.net Thu Mar 5 16:48:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 16:48:35 +0100 (CET) Subject: [pypy-svn] r62591 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305154835.7C73C169E10@codespeak.net> Author: arigo Date: Thu Mar 5 16:48:34 2009 New Revision: 62591 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: continuing... Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 16:48:34 2009 @@ -922,6 +922,18 @@ x = getattr(ptr, fieldname) return cast_to_ptr(x) +def do_getfield_raw_int(struct, fielddesc, memocast): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) + x = getattr(ptr, fieldname) + return cast_to_int(x, memocast) + +def do_getfield_raw_ptr(struct, fielddesc): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) + x = getattr(ptr, fieldname) + return cast_to_ptr(x) + # ____________________________________________________________ @@ -1010,3 +1022,5 @@ setannotation(do_getarrayitem_gc_ptr, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_getfield_gc_int, annmodel.SomeInteger()) setannotation(do_getfield_gc_ptr, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_getfield_raw_int, annmodel.SomeInteger()) +setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 16:48:34 2009 @@ -343,6 +343,17 @@ fielddescr, self.memo_cast)) + def do_getfield_raw(self, args): + struct = self.cast_int_to_adr(args[0].getint()) + fielddescr = args[1].getint() + if self.typefor(fielddescr) == 'ptr': + return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, + fielddescr)) + else: + return history.BoxInt(llimpl.do_getfield_raw_int(struct, + fielddescr, + self.memo_cast)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 16:48:34 2009 @@ -206,3 +206,20 @@ BoxInt(descrfld_y)]) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a + # + RS = lltype.Struct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) + descrfld_rx = cpu.fielddescrof(RS, 'x') + rs = lltype.malloc(RS, immortal=True) + rs.x = '?' + x = cpu.do_getfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_rx)]) + assert x.value == ord('?') + # + descrfld_ry = cpu.fielddescrof(RS, 'y') + rs.y = a + x = cpu.do_getfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_ry)]) + assert isinstance(x, BoxPtr) + assert x.getptr(lltype.Ptr(A)) == a From hpk at codespeak.net Thu Mar 5 16:50:10 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 5 Mar 2009 16:50:10 +0100 (CET) Subject: [pypy-svn] r62592 - pypy/trunk/pypy/doc Message-ID: <20090305155010.2A9E3169E10@codespeak.net> Author: hpk Date: Thu Mar 5 16:50:09 2009 New Revision: 62592 Modified: pypy/trunk/pypy/doc/faq.txt Log: update compatibility target. Modified: pypy/trunk/pypy/doc/faq.txt ============================================================================== --- pypy/trunk/pypy/doc/faq.txt (original) +++ pypy/trunk/pypy/doc/faq.txt Thu Mar 5 16:50:09 2009 @@ -60,10 +60,9 @@ Which Python version (2.x?) does PyPy implement? ------------------------------------------------ -PyPy currently aims to be fully compatible with Python 2.4. That means that -it contains the standard library of Python 2.4 and that it supports 2.4 -features (such as decorators). The 2.5 features (e.g. the ``with`` statement, -the ternary operator) are in progress. +PyPy currently aims to be fully compatible with Python 2.5. That means that +it contains the standard library of Python 2.5 and that it supports 2.5 +features (such as the width statement). .. _threading: From arigo at codespeak.net Thu Mar 5 17:00:16 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:00:16 +0100 (CET) Subject: [pypy-svn] r62593 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305160016.725DF169DFE@codespeak.net> Author: arigo Date: Thu Mar 5 17:00:14 2009 New Revision: 62593 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: do_new. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:00:14 2009 @@ -934,6 +934,11 @@ x = getattr(ptr, fieldname) return cast_to_ptr(x) +def do_new(size): + TYPE = symbolic.Size2Type[size] + x = lltype.malloc(TYPE) + return cast_to_ptr(x) + # ____________________________________________________________ @@ -1024,3 +1029,4 @@ setannotation(do_getfield_gc_ptr, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_getfield_raw_int, annmodel.SomeInteger()) setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_new, annmodel.SomePtr(llmemory.GCREF)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:00:14 2009 @@ -354,6 +354,10 @@ fielddescr, self.memo_cast)) + def do_new(self, args): + size = args[0].getint() + return history.BoxPtr(llimpl.do_new(size)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:00:14 2009 @@ -223,3 +223,9 @@ BoxInt(descrfld_ry)]) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a + # + descrsize = cpu.sizeof(S) + x = cpu.do_new( + [BoxInt(descrsize)]) + assert isinstance(x, BoxPtr) + x.getptr(lltype.Ptr(S)) From arigo at codespeak.net Thu Mar 5 17:14:42 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:14:42 +0100 (CET) Subject: [pypy-svn] r62594 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305161442.7AF3E168510@codespeak.net> Author: arigo Date: Thu Mar 5 17:14:41 2009 New Revision: 62594 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: new_with_vtable. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:14:41 2009 @@ -460,11 +460,21 @@ return cast_adr_to_int(memocast, x) return lltype.cast_primitive(lltype.Signed, x) -def cast_to_ptr(x): - if isinstance(lltype.typeOf(x), lltype.Ptr): - return lltype.cast_opaque_ptr(llmemory.GCREF, x) +def cast_from_int(TYPE, x, memocast): + if isinstance(TYPE, lltype.Ptr): + assert TYPE.TO._gckind == 'raw' + return llmemory.cast_adr_to_ptr(cast_int_to_adr(memocast, x), TYPE) + elif TYPE == llmemory.Address: + return cast_int_to_adr(memocast, x) else: - return x + return lltype.cast_primitive(TYPE, x) + +def cast_to_ptr(x): + assert isinstance(lltype.typeOf(x), lltype.Ptr) + return lltype.cast_opaque_ptr(llmemory.GCREF, x) + +def cast_from_ptr(TYPE, x): + return lltype.cast_opaque_ptr(TYPE, x) def new_frame(memocast): @@ -939,6 +949,13 @@ x = lltype.malloc(TYPE) return cast_to_ptr(x) +def do_setfield_gc_int(struct, fielddesc, newvalue, memocast): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) + FIELDTYPE = getattr(STRUCT, fieldname) + newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + setattr(ptr, fieldname, newvalue) + # ____________________________________________________________ @@ -1030,3 +1047,4 @@ setannotation(do_getfield_raw_int, annmodel.SomeInteger()) setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_new, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_setfield_gc_int, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:14:41 2009 @@ -2,7 +2,7 @@ Minimal-API wrapper around the llinterpreter to run operations. """ -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.jit.metainterp import history from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.backend.llgraph import llimpl, symbolic @@ -29,6 +29,7 @@ llimpl._rtyper = self.rtyper if translate_support_code: self.mixlevelann = annmixlevel + self.fielddescrof_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr') def set_meta_interp(self, metainterp): self.metainterp = metainterp # to handle guard failures @@ -358,6 +359,14 @@ size = args[0].getint() return history.BoxPtr(llimpl.do_new(size)) + def do_new_with_vtable(self, args): + size = args[0].getint() + vtable = args[1].getint() + result = llimpl.do_new(size) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable, vtable, + self.memo_cast) + return history.BoxPtr(result) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:14:41 2009 @@ -1,5 +1,5 @@ import py -from pypy.rpython.lltypesystem import lltype, llmemory, rstr +from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rclass from pypy.rpython.test.test_llinterp import interpret from pypy.rlib.unroll import unrolling_iterable @@ -229,3 +229,11 @@ [BoxInt(descrsize)]) assert isinstance(x, BoxPtr) x.getptr(lltype.Ptr(S)) + # + descrsize2 = cpu.sizeof(rclass.OBJECT) + vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) + x = cpu.do_new_with_vtable( + [BoxInt(descrsize2), + BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))]) + assert isinstance(x, BoxPtr) + assert x.getptr(rclass.OBJECTPTR).typeptr == vtable2 From arigo at codespeak.net Thu Mar 5 17:18:28 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:18:28 +0100 (CET) Subject: [pypy-svn] r62595 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305161828.8F74B16855F@codespeak.net> Author: arigo Date: Thu Mar 5 17:18:27 2009 New Revision: 62595 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: new_array. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:18:27 2009 @@ -949,6 +949,11 @@ x = lltype.malloc(TYPE) return cast_to_ptr(x) +def do_new_array(arraydesc, count): + TYPE = symbolic.Size2Type[arraydesc/2] + x = lltype.malloc(TYPE, count) + return cast_to_ptr(x) + def do_setfield_gc_int(struct, fielddesc, newvalue, memocast): STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) @@ -1047,4 +1052,5 @@ setannotation(do_getfield_raw_int, annmodel.SomeInteger()) setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_new, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_new_array, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_setfield_gc_int, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:18:27 2009 @@ -367,6 +367,11 @@ self.memo_cast) return history.BoxPtr(result) + def do_new_array(self, args): + size = args[0].getint() + count = args[1].getint() + return history.BoxPtr(llimpl.do_new_array(size, count)) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:18:27 2009 @@ -237,3 +237,9 @@ BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))]) assert isinstance(x, BoxPtr) assert x.getptr(rclass.OBJECTPTR).typeptr == vtable2 + # + arraydescr = cpu.arraydescrof(A) + x = cpu.do_new_array( + [BoxInt(arraydescr), BoxInt(7)]) + assert isinstance(x, BoxPtr) + assert len(x.getptr(lltype.Ptr(A))) == 7 From arigo at codespeak.net Thu Mar 5 17:34:01 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:34:01 +0100 (CET) Subject: [pypy-svn] r62596 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305163401.706E916855D@codespeak.net> Author: arigo Date: Thu Mar 5 17:34:00 2009 New Revision: 62596 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: setarrayitem_gc Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:34:00 2009 @@ -954,6 +954,18 @@ x = lltype.malloc(TYPE, count) return cast_to_ptr(x) +def do_setarrayitem_gc_int(array, index, newvalue, memocast): + array = array._obj.container + ITEMTYPE = lltype.typeOf(array).OF + newvalue = cast_from_int(ITEMTYPE, newvalue, memocast) + array.setitem(index, newvalue) + +def do_setarrayitem_gc_ptr(array, index, newvalue): + array = array._obj.container + ITEMTYPE = lltype.typeOf(array).OF + newvalue = cast_from_ptr(ITEMTYPE, newvalue) + array.setitem(index, newvalue) + def do_setfield_gc_int(struct, fielddesc, newvalue, memocast): STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) @@ -1053,4 +1065,6 @@ setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_new, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_new_array, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_setarrayitem_gc_int, annmodel.s_None) +setannotation(do_setarrayitem_gc_ptr, annmodel.s_None) setannotation(do_setfield_gc_int, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:34:00 2009 @@ -372,6 +372,18 @@ count = args[1].getint() return history.BoxPtr(llimpl.do_new_array(size, count)) + def do_setarrayitem_gc(self, args): + array = args[0].getptr_base() + arraydescr = args[1].getint() + index = args[2].getint() + if self.typefor(arraydescr) == 'ptr': + newvalue = args[3].getptr_base() + llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) + else: + newvalue = args[3].getint() + llimpl.do_setarrayitem_gc_int(array, index, newvalue, + self.memo_cast) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:34:00 2009 @@ -243,3 +243,12 @@ [BoxInt(arraydescr), BoxInt(7)]) assert isinstance(x, BoxPtr) assert len(x.getptr(lltype.Ptr(A))) == 7 + # + cpu.do_setarrayitem_gc( + [x, descrbox_A, BoxInt(5), BoxInt(ord('*'))]) + assert x.getptr(lltype.Ptr(A))[5] == '*' + # + cpu.do_setarrayitem_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, + BoxInt(1), x]) + assert b[1] == x.getptr(lltype.Ptr(A)) From cfbolz at codespeak.net Thu Mar 5 17:35:55 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 5 Mar 2009 17:35:55 +0100 (CET) Subject: [pypy-svn] r62597 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305163555.715BF16855D@codespeak.net> Author: cfbolz Date: Thu Mar 5 17:35:54 2009 New Revision: 62597 Modified: pypy/trunk/pypy/lang/gameboy/ram.py Log: more explicit exception Modified: pypy/trunk/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/ram.py (original) +++ pypy/trunk/pypy/lang/gameboy/ram.py Thu Mar 5 17:35:54 2009 @@ -6,6 +6,8 @@ from pypy.lang.gameboy import constants +class InvalidMemoryAccess(Exception): + pass class iMemory(object): def write(self, address, data): @@ -42,4 +44,4 @@ # FF80-FFFE elif address >= 0xFF80 and address <= 0xFFFE: return self.hi_ram[address & 0x7F] - raise Exception("Invalid Memory access, address out of range") \ No newline at end of file + raise InvalidMemoryAccess("Invalid Memory access, address out of range") From arigo at codespeak.net Thu Mar 5 17:38:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:38:37 +0100 (CET) Subject: [pypy-svn] r62598 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305163837.40AB916855D@codespeak.net> Author: arigo Date: Thu Mar 5 17:38:36 2009 New Revision: 62598 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: setfield_gc Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:38:36 2009 @@ -973,6 +973,13 @@ newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) setattr(ptr, fieldname, newvalue) +def do_setfield_gc_ptr(struct, fielddesc, newvalue): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) + FIELDTYPE = getattr(STRUCT, fieldname) + newvalue = cast_from_ptr(FIELDTYPE, newvalue) + setattr(ptr, fieldname, newvalue) + # ____________________________________________________________ @@ -1068,3 +1075,4 @@ setannotation(do_setarrayitem_gc_int, annmodel.s_None) setannotation(do_setarrayitem_gc_ptr, annmodel.s_None) setannotation(do_setfield_gc_int, annmodel.s_None) +setannotation(do_setfield_gc_ptr, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:38:36 2009 @@ -384,6 +384,17 @@ llimpl.do_setarrayitem_gc_int(array, index, newvalue, self.memo_cast) + def do_setfield_gc(self, args): + struct = args[0].getptr_base() + fielddescr = args[1].getint() + if self.typefor(fielddescr) == 'ptr': + newvalue = args[2].getptr_base() + llimpl.do_setfield_gc_ptr(struct, fielddescr, newvalue) + else: + newvalue = args[2].getint() + llimpl.do_setfield_gc_int(struct, fielddescr, newvalue, + self.memo_cast) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:38:36 2009 @@ -199,6 +199,12 @@ BoxInt(descrfld_x)]) assert x.value == ord('Z') # + cpu.do_setfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_x), + BoxInt(ord('4'))]) + assert s.x == '4' + # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a x = cpu.do_getfield_gc( @@ -207,6 +213,13 @@ assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # + s.y = lltype.nullptr(A) + cpu.do_setfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_y), + x]) + assert s.y == a + # RS = lltype.Struct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) descrfld_rx = cpu.fielddescrof(RS, 'x') rs = lltype.malloc(RS, immortal=True) From arigo at codespeak.net Thu Mar 5 17:41:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:41:32 +0100 (CET) Subject: [pypy-svn] r62599 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305164132.4D0DA168500@codespeak.net> Author: arigo Date: Thu Mar 5 17:41:31 2009 New Revision: 62599 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: setfield_raw Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:41:31 2009 @@ -980,6 +980,20 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) +def do_setfield_raw_int(struct, fielddesc, newvalue, memocast): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) + FIELDTYPE = getattr(STRUCT, fieldname) + newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) + setattr(ptr, fieldname, newvalue) + +def do_setfield_raw_ptr(struct, fielddesc, newvalue): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] + ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) + FIELDTYPE = getattr(STRUCT, fieldname) + newvalue = cast_from_ptr(FIELDTYPE, newvalue) + setattr(ptr, fieldname, newvalue) + # ____________________________________________________________ @@ -1076,3 +1090,5 @@ setannotation(do_setarrayitem_gc_ptr, annmodel.s_None) setannotation(do_setfield_gc_int, annmodel.s_None) setannotation(do_setfield_gc_ptr, annmodel.s_None) +setannotation(do_setfield_raw_int, annmodel.s_None) +setannotation(do_setfield_raw_ptr, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:41:31 2009 @@ -395,6 +395,17 @@ llimpl.do_setfield_gc_int(struct, fielddescr, newvalue, self.memo_cast) + def do_setfield_raw(self, args): + struct = self.cast_int_to_adr(args[0].getint()) + fielddescr = args[1].getint() + if self.typefor(fielddescr) == 'ptr': + newvalue = args[2].getptr_base() + llimpl.do_setfield_raw_ptr(struct, fielddescr, newvalue) + else: + newvalue = args[2].getint() + llimpl.do_setfield_raw_int(struct, fielddescr, newvalue, + self.memo_cast) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:41:31 2009 @@ -229,6 +229,12 @@ BoxInt(descrfld_rx)]) assert x.value == ord('?') # + cpu.do_setfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_rx), + BoxInt(ord('!'))]) + assert rs.x == '!' + # descrfld_ry = cpu.fielddescrof(RS, 'y') rs.y = a x = cpu.do_getfield_raw( @@ -237,6 +243,13 @@ assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # + rs.y = lltype.nullptr(A) + cpu.do_setfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_ry), + x]) + assert rs.y == a + # descrsize = cpu.sizeof(S) x = cpu.do_new( [BoxInt(descrsize)]) From arigo at codespeak.net Thu Mar 5 17:50:20 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 5 Mar 2009 17:50:20 +0100 (CET) Subject: [pypy-svn] r62600 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090305165020.80027168500@codespeak.net> Author: arigo Date: Thu Mar 5 17:50:19 2009 New Revision: 62600 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: newstr, strsetitem Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 5 17:50:19 2009 @@ -994,6 +994,14 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) +def do_newstr(length): + x = rstr.mallocstr(length) + return cast_to_ptr(x) + +def do_strsetitem(string, index, newvalue): + str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) + str.chars[index] = chr(newvalue) + # ____________________________________________________________ @@ -1092,3 +1100,5 @@ setannotation(do_setfield_gc_ptr, annmodel.s_None) setannotation(do_setfield_raw_int, annmodel.s_None) setannotation(do_setfield_raw_ptr, annmodel.s_None) +setannotation(do_newstr, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_strsetitem, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 5 17:50:19 2009 @@ -406,6 +406,16 @@ llimpl.do_setfield_raw_int(struct, fielddescr, newvalue, self.memo_cast) + def do_newstr(self, args): + length = args[0].getint() + return history.BoxPtr(llimpl.do_newstr(length)) + + def do_strsetitem(self, args): + string = args[0].getptr_base() + index = args[1].getint() + newvalue = args[2].getint() + llimpl.do_strsetitem(string, index, newvalue) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Thu Mar 5 17:50:19 2009 @@ -278,3 +278,10 @@ [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, BoxInt(1), x]) assert b[1] == x.getptr(lltype.Ptr(A)) + # + x = cpu.do_newstr([BoxInt(5)]) + assert isinstance(x, BoxPtr) + assert len(x.getptr(lltype.Ptr(rstr.STR)).chars) == 5 + # + cpu.do_strsetitem([x, BoxInt(4), BoxInt(ord('/'))]) + assert x.getptr(lltype.Ptr(rstr.STR)).chars[4] == '/' From witulski at codespeak.net Thu Mar 5 17:56:34 2009 From: witulski at codespeak.net (witulski at codespeak.net) Date: Thu, 5 Mar 2009 17:56:34 +0100 (CET) Subject: [pypy-svn] r62601 - pypy/branch/spy-graphic/pypy/lang/smalltalk Message-ID: <20090305165634.7ACAB16855D@codespeak.net> Author: witulski Date: Thu Mar 5 17:56:34 2009 New Revision: 62601 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Log: added SIGNAL_AT_BYTES_LEFT and LOW_SPACE_SEMAPHORE (does nothing) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Thu Mar 5 17:56:34 2009 @@ -479,12 +479,14 @@ KBD_NEXT = 108 KBD_PEEK = 109 + @expose_primitive(BE_CURSOR, unwrap_spec=[object]) def func(interp, w_rcvr): # TODO: Use info from cursor object. interp.space.objtable['w_cursor'] = w_rcvr return w_rcvr + @expose_primitive(BE_DISPLAY, unwrap_spec=[object]) def func(interp, w_rcvr): interp.space.objtable['w_display'] = w_rcvr @@ -498,6 +500,7 @@ point.store_x(640) point.store_y(480) return w_res + # ___________________________________________________________________________ # Control Primitives @@ -574,7 +577,16 @@ pass # XXX raise PrimitiveFailedError + at expose_primitive(LOW_SPACE_SEMAPHORE, unwrap_spec=[object, object]) +def func(interp, w_reciver, i): + # dont know when the space runs out + return w_reciver + + at expose_primitive(SIGNAL_AT_BYTES_LEFT, unwrap_spec=[object, int]) +def func(interp, w_reciver, i): + # dont know when the space runs out + return w_reciver # ___________________________________________________________________________ From cfbolz at codespeak.net Thu Mar 5 18:06:09 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 5 Mar 2009 18:06:09 +0100 (CET) Subject: [pypy-svn] r62602 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090305170609.50B071684AB@codespeak.net> Author: cfbolz Date: Thu Mar 5 18:06:08 2009 New Revision: 62602 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/serial.py pypy/trunk/pypy/lang/gameboy/timer.py Log: get rid of a number of * imports Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Thu Mar 5 18:06:08 2009 @@ -1,7 +1,6 @@ from pypy.lang.gameboy import constants -from pypy.lang.gameboy.ram import * -from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.cpu_register import Register, DoubleRegister, \ FlagRegister, ImmediatePseudoRegister Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Thu Mar 5 18:06:08 2009 @@ -5,16 +5,16 @@ """ from pypy.lang.gameboy import constants -from pypy.lang.gameboy.cpu import * -from pypy.lang.gameboy.cartridge import * -from pypy.lang.gameboy.interrupt import * -from pypy.lang.gameboy.joypad import * -from pypy.lang.gameboy.ram import * -from pypy.lang.gameboy.serial import * -from pypy.lang.gameboy.sound import * -from pypy.lang.gameboy.timer import * -from pypy.lang.gameboy.video import * -from pypy.lang.gameboy.cartridge import * +from pypy.lang.gameboy.cpu import CPU +from pypy.lang.gameboy.interrupt import Interrupt +from pypy.lang.gameboy.cartridge import CartridgeManager +from pypy.lang.gameboy.joypad import Joypad, JoypadDriver +from pypy.lang.gameboy.ram import RAM +from pypy.lang.gameboy.serial import Serial +from pypy.lang.gameboy.sound import Sound, SoundDriver, BogusSound +from pypy.lang.gameboy.timer import Timer, Clock +from pypy.lang.gameboy.video import Video, VideoDriver +from pypy.lang.gameboy.cartridge import CartridgeManager, CartridgeFile class GameBoy(object): Modified: pypy/trunk/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/serial.py (original) +++ pypy/trunk/pypy/lang/gameboy/serial.py Thu Mar 5 18:06:08 2009 @@ -1,6 +1,6 @@ from pypy.lang.gameboy import constants -from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.ram import iMemory class Serial(iMemory): Modified: pypy/trunk/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/timer.py (original) +++ pypy/trunk/pypy/lang/gameboy/timer.py Thu Mar 5 18:06:08 2009 @@ -5,7 +5,7 @@ """ from pypy.lang.gameboy import constants -from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.interrupt import Interrupt from math import ceil from pypy.lang.gameboy.ram import iMemory import time From hpk at codespeak.net Thu Mar 5 18:07:22 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 5 Mar 2009 18:07:22 +0100 (CET) Subject: [pypy-svn] r62603 - pypy/trunk/pypy/doc Message-ID: <20090305170722.7B1541684AB@codespeak.net> Author: hpk Date: Thu Mar 5 18:07:21 2009 New Revision: 62603 Modified: pypy/trunk/pypy/doc/maemo.txt Log: maybe not so soon :( Modified: pypy/trunk/pypy/doc/maemo.txt ============================================================================== --- pypy/trunk/pypy/doc/maemo.txt (original) +++ pypy/trunk/pypy/doc/maemo.txt Thu Mar 5 18:07:21 2009 @@ -138,9 +138,7 @@ svn co https://codespeak.net/svn/pypy/trunk pypy-trunk Several svn revisions since the 60000's are known to work and -the last manually tested one is currently 65011. You may -also look at http://test.pypy.org where integration -of automatic maemo builds and tests should soon appear. +the last manually tested one is currently 65011. Change to the ``pypy-trunk/pypy/translator/goal`` directory and execute:: From fijal at codespeak.net Thu Mar 5 18:18:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 18:18:38 +0100 (CET) Subject: [pypy-svn] r62604 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305171838.2C8F616852B@codespeak.net> Author: fijal Date: Thu Mar 5 18:18:37 2009 New Revision: 62604 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: Ok, let's start to collect functions that were tried at least Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Thu Mar 5 18:18:37 2009 @@ -1,14 +1,27 @@ -def f(): - print 543210 +def f0(): + print "simple loop" + + i = 0 + while i < 100: + i = i + 3 + print i + +def f1(): + print "simple loop with inplace_add" i = 0 while i < 100: + i += 3 + print i + +def f(): + print 543210 + + s = 0 + for i in range(100): # XXX implement inplace_add method for ints - if i % 2: - i = i + 3 - else: - i = i + 1 - print i # should print 102 + s += i + print s # should print 102 f() From fijal at codespeak.net Thu Mar 5 18:19:12 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 18:19:12 +0100 (CET) Subject: [pypy-svn] r62605 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305171912.7EF3A16852B@codespeak.net> Author: fijal Date: Thu Mar 5 18:19:12 2009 New Revision: 62605 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: use CALL_LIKELY_BUILTIN. cheat cheat cheat ;-) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Mar 5 18:19:12 2009 @@ -22,6 +22,7 @@ set_pypy_opt_level(config, level='0') config.objspace.std.multimethods = 'mrd' config.objspace.std.builtinshortcut = True +config.objspace.opcodes.CALL_LIKELY_BUILTIN = True multimethod.Installer = multimethod.InstallerVersion2 print config From fijal at codespeak.net Thu Mar 5 18:55:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 18:55:06 +0100 (CET) Subject: [pypy-svn] r62606 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305175506.2A37A16853C@codespeak.net> Author: fijal Date: Thu Mar 5 18:55:04 2009 New Revision: 62606 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: grr. Ask if actually someone meant C-c Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Mar 5 18:55:04 2009 @@ -46,7 +46,9 @@ def entry_point(): source = readfile('pypyjit_demo.py') ec = space.getexecutioncontext() + print "compiling..." code = ec.compiler.compile(source, '?', 'exec', 0) + print "compiled" code.exec_code(space, w_dict, w_dict) @@ -76,7 +78,13 @@ pass print '-' * 79 print 'Child process finished, press Enter to restart...' - raw_input() + try: + raw_input() + except KeyboardInterrupt: + x = raw_input("are you sure? (y/n)") + if x == 'y': + raise + # otherwise continue from pypy.jit.tl.pypyjit_child import run_child run_child(globals(), locals()) From hpk at codespeak.net Thu Mar 5 19:34:09 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 5 Mar 2009 19:34:09 +0100 (CET) Subject: [pypy-svn] r62607 - pypy/trunk/pypy/doc Message-ID: <20090305183409.A56C716851B@codespeak.net> Author: hpk Date: Thu Mar 5 19:34:07 2009 New Revision: 62607 Modified: pypy/trunk/pypy/doc/faq.txt Log: fix typo, admittedly i am not using the with statement often, not at all, to be precise. Modified: pypy/trunk/pypy/doc/faq.txt ============================================================================== --- pypy/trunk/pypy/doc/faq.txt (original) +++ pypy/trunk/pypy/doc/faq.txt Thu Mar 5 19:34:07 2009 @@ -62,7 +62,7 @@ PyPy currently aims to be fully compatible with Python 2.5. That means that it contains the standard library of Python 2.5 and that it supports 2.5 -features (such as the width statement). +features (such as the with statement). .. _threading: From fijal at codespeak.net Thu Mar 5 20:14:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 20:14:19 +0100 (CET) Subject: [pypy-svn] r62608 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305191419.4479C16851A@codespeak.net> Author: fijal Date: Thu Mar 5 20:14:16 2009 New Revision: 62608 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: use plain addition here Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Thu Mar 5 20:14:16 2009 @@ -21,7 +21,7 @@ s = 0 for i in range(100): # XXX implement inplace_add method for ints - s += i + s = s + i print s # should print 102 f() From fijal at codespeak.net Thu Mar 5 20:14:44 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 5 Mar 2009 20:14:44 +0100 (CET) Subject: [pypy-svn] r62609 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305191444.D285F16851B@codespeak.net> Author: fijal Date: Thu Mar 5 20:14:44 2009 New Revision: 62609 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: enable range lists Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Mar 5 20:14:44 2009 @@ -23,6 +23,7 @@ config.objspace.std.multimethods = 'mrd' config.objspace.std.builtinshortcut = True config.objspace.opcodes.CALL_LIKELY_BUILTIN = True +config.objspace.std.withrangelist = True multimethod.Installer = multimethod.InstallerVersion2 print config From hpk at codespeak.net Fri Mar 6 00:24:09 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 6 Mar 2009 00:24:09 +0100 (CET) Subject: [pypy-svn] r62618 - pypy/build/doc Message-ID: <20090305232409.18B061684B6@codespeak.net> Author: hpk Date: Fri Mar 6 00:24:08 2009 New Revision: 62618 Modified: pypy/build/doc/ssh_config Log: adding the now reachable maemo device, thanks cfbolz Modified: pypy/build/doc/ssh_config ============================================================================== --- pypy/build/doc/ssh_config (original) +++ pypy/build/doc/ssh_config Fri Mar 6 00:24:08 2009 @@ -26,3 +26,7 @@ Host t20 Hostname t20.pypy.org + +Host Maemo + Hostname codespeak.net + Port 2222 From hpk at codespeak.net Fri Mar 6 00:28:34 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 6 Mar 2009 00:28:34 +0100 (CET) Subject: [pypy-svn] r62619 - pypy/trunk/pypy/translator/js/test Message-ID: <20090305232834.1B4AE1684B6@codespeak.net> Author: hpk Date: Fri Mar 6 00:28:32 2009 New Revision: 62619 Modified: pypy/trunk/pypy/translator/js/test/runtest.py Log: fix access to options Modified: pypy/trunk/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/trunk/pypy/translator/js/test/runtest.py (original) +++ pypy/trunk/pypy/translator/js/test/runtest.py Fri Mar 6 00:28:32 2009 @@ -4,9 +4,7 @@ from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.js.js import JS from pypy.translator.js.test.browsertest import jstest -from pypy.translator.js import conftest from pypy.translator.js.log import log -from pypy.conftest import option from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin from pypy.rlib.nonconst import NonConstant from pypy.rpython.ootypesystem import ootype @@ -14,8 +12,9 @@ from pypy.rpython.llinterp import LLException log = log.runtest -use_browsertest = conftest.option.browser -use_tg = conftest.option.tg +use_browsertest = py.test.config.option.browser +use_tg = py.test.config.option.tg +use_view = py.test.config.option.view port = 8080 @@ -43,11 +42,11 @@ ann = t.buildannotator(policy=policy) ann.build_types(function, annotations) - if view or option.view: + if view or use_view: t.view() t.buildrtyper(type_system="ootype").specialize() - if view or option.view: + if view or use_view: t.view() #self.js = JS(t, [function, callback_function], stackless) self.js = JS(t, function, stackless) From fijal at codespeak.net Fri Mar 6 00:41:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 00:41:39 +0100 (CET) Subject: [pypy-svn] r62620 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090305234139.ACFFE1684A7@codespeak.net> Author: fijal Date: Fri Mar 6 00:41:39 2009 New Revision: 62620 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: look a bit at RangeIter, not yet enough Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Fri Mar 6 00:41:39 2009 @@ -31,9 +31,6 @@ return super(PyPyJitPolicy, self).look_inside_function(func) def seebinary(self, opname): - def fc(o): - return [i[1] for i in find_calls_from(self.translator, o)] - name2 = name1 = opname[:3].lower() if name1 in ('and', 'or'): name1 += '_' @@ -78,6 +75,9 @@ def fill_seen_graphs(self): import pypy + def fc(o): + return [i[1] for i in find_calls_from(self.translator, o)] + # -------------------- for binop in 'MODULO ADD SUBTRACT MULTIPLY AND OR XOR'.split(): @@ -112,7 +112,10 @@ pypy.objspace.std.intobject.nonzero__Int) self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, pypy.objspace.std.intobject.nonzero__Int) - + self.seepath(pypy.interpreter.pyframe.PyFrame.FOR_ITER, + pypy.objspace.descroperation.DescrOperation.next, + pypy.objspace.std.rangeobject.next__RangeIter) +# pypy.objspace.std.rangeobject.) # #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, # pypy.interpreter.function.Function.funccall_valuestack) From fijal at codespeak.net Fri Mar 6 00:43:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 00:43:17 +0100 (CET) Subject: [pypy-svn] r62621 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090305234317.BCA741684B6@codespeak.net> Author: fijal Date: Fri Mar 6 00:43:17 2009 New Revision: 62621 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: cheat cheat cheat. Move some of the logic to pure python. This speeds up loading and running python code. A LOT Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Fri Mar 6 00:43:17 2009 @@ -8,6 +8,10 @@ from pypy.config.translationoption import set_opt_level from pypy.config.pypyoption import get_pypy_config, set_pypy_opt_level from pypy.objspace.std import multimethod +from pypy.rpython.annlowlevel import llhelper, llstr, hlstr +from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.lltypesystem import lltype +from pypy.interpreter.pycode import PyCode config = get_pypy_config(translating=True) config.translation.backendopt.inline_threshold = 0 @@ -44,14 +48,22 @@ os.close(fd) return ''.join(blocks) -def entry_point(): +def read_code(): + from pypy.module.marshal.interp_marshal import dumps + source = readfile('pypyjit_demo.py') ec = space.getexecutioncontext() - print "compiling..." code = ec.compiler.compile(source, '?', 'exec', 0) - print "compiled" - code.exec_code(space, w_dict, w_dict) + return llstr(space.str_w(dumps(space, code, space.wrap(2)))) + +FPTR = lltype.Ptr(lltype.FuncType([], lltype.Ptr(STR))) +read_code_ptr = llhelper(FPTR, read_code) +def entry_point(): + from pypy.module.marshal.interp_marshal import loads + code = loads(space, space.wrap(hlstr(read_code_ptr()))) + assert isinstance(code, PyCode) + code.exec_code(space, w_dict, w_dict) def test_run_translation(): from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy @@ -65,7 +77,7 @@ except Exception, e: print '%s: %s' % (e.__class__, e) pdb.post_mortem(sys.exc_info()[2]) - + raise # parent process loop: spawn a child, wait for the child to finish, # print a message, and restart From fijal at codespeak.net Fri Mar 6 01:30:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 01:30:14 +0100 (CET) Subject: [pypy-svn] r62622 - in pypy/branch/pyjitpl5/pypy: jit/metainterp translator/backendopt Message-ID: <20090306003014.CE62F1684C0@codespeak.net> Author: fijal Date: Fri Mar 6 01:30:13 2009 New Revision: 62622 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py Log: add an optional memo to find_calls_from, combined with previous checkin lets me run a pypy jit in just below one minute, progress :-) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Fri Mar 6 01:30:13 2009 @@ -59,6 +59,7 @@ self.translator = translator self.bookkeeper = translator.annotator.bookkeeper self.enabled_graphs = {} + self.memo = {} self.fill_seen_graphs() def look_inside_graph(self, graph): @@ -80,7 +81,7 @@ for tofunc in tofuncs: targetgraphs[self._graph(tofunc)] = True graphs = graphs_on_the_path_to(self.translator, self._graph(fromfunc), - targetgraphs) + targetgraphs, self.memo) for graph in graphs: if graph not in self.enabled_graphs: self.enabled_graphs[graph] = True @@ -99,7 +100,7 @@ else: print '--', graph -def enumerate_reachable_graphs(translator, startgraph): +def enumerate_reachable_graphs(translator, startgraph, memo=None): from pypy.translator.backendopt.support import find_calls_from pending = [(startgraph, None)] yield pending[0] @@ -110,7 +111,7 @@ nextseen = {} for node in pending: head, tail = node - for block, callee in find_calls_from(translator, head): + for block, callee in find_calls_from(translator, head, memo): if callee not in seen: newnode = callee, node yield newnode @@ -120,11 +121,11 @@ seen.update(nextseen) yield None -def graphs_on_the_path_to(translator, startgraph, targetgraphs): +def graphs_on_the_path_to(translator, startgraph, targetgraphs, memo=None): targetgraphs = targetgraphs.copy() result = {} found = {} - for node in enumerate_reachable_graphs(translator, startgraph): + for node in enumerate_reachable_graphs(translator, startgraph, memo): if node is None: # hack: a separator meaning "length increases now" for graph in found: del targetgraphs[graph] Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py Fri Mar 6 01:30:13 2009 @@ -107,7 +107,14 @@ afterblock.operations[pos:pos] = generate_keepalive(keep_alive_vars) return splitlink -def find_calls_from(translator, graph): +def find_calls_from(translator, graph, memo=None): + if memo and graph in memo: + return memo[graph] + res = [i for i in _find_calls_from(translator, graph)] + memo[graph] = res + return res + +def _find_calls_from(translator, graph): for block in graph.iterblocks(): for op in block.operations: if op.opname == "direct_call": From tverwaes at codespeak.net Fri Mar 6 02:25:22 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 02:25:22 +0100 (CET) Subject: [pypy-svn] r62623 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306012522.8D7E3168485@codespeak.net> Author: tverwaes Date: Fri Mar 6 02:25:18 2009 New Revision: 62623 Added: pypy/trunk/pypy/lang/gameboy/video_meta.py Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: small refactorings + adding possibility of visualizing meta-data at runtime. This will for now show what's in tile_data_0,1 and the 40 sprites. Sprites will have while block in between when small sprites are selected. Otherwise big sprites are joined together Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Fri Mar 6 02:25:18 2009 @@ -11,6 +11,7 @@ GAMEBOY_SCREEN_HEIGHT = 144 SPRITE_SIZE = 8 +MAX_SPRITES = 40 #___________________________________________________________________________ # CATRIGE TYPES Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Fri Mar 6 02:25:18 2009 @@ -21,14 +21,14 @@ def __init__(self): self.create_drivers() - self.create_gamboy_elements() + self.create_gameboy_elements() def create_drivers(self): self.joypad_driver = JoypadDriver() self.video_driver = VideoDriver() self.sound_driver = SoundDriver() - def create_gamboy_elements(self): + def create_gameboy_elements(self): self.clock = Clock() self.ram = RAM() self.cartridge_manager = CartridgeManager(self.clock) Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Mar 6 02:25:18 2009 @@ -5,10 +5,12 @@ from pypy.lang.gameboy.video import VideoDriver from pypy.lang.gameboy.sound import SoundDriver from pypy.lang.gameboy.timer import Clock +from pypy.lang.gameboy.video_meta import TileDataWindow, SpriteWindow from pypy.lang.gameboy import constants import time use_rsdl = True +show_metadata = False # Extends the window with windows visualizing meta-data if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper @@ -24,6 +26,7 @@ GameBoy.__init__(self) self.is_running = False self.penalty = 0.0 + self.sync_time = time.time() if use_rsdl: self.init_sdl() @@ -34,7 +37,7 @@ def create_drivers(self): self.clock = Clock() self.joypad_driver = JoypadDriverImplementation() - self.video_driver = VideoDriverImplementation() + self.video_driver = VideoDriverImplementation(self) self.sound_driver = SoundDriverImplementation() def mainLoop(self): @@ -51,16 +54,14 @@ return 0 def emulate_cycle(self): - # self.joypad_driver.button_up(True) X = 1<<6 # About 1<<6 to make sure we have a clean distrubution of about # 1<<6 frames per second - start_time = time.time() self.handle_events() # Come back to this cycle every 1/X seconds self.emulate(constants.GAMEBOY_CLOCK / X) # if use_rsdl: # RSDL.Delay(100) - spent = time.time() - start_time + spent = time.time() - self.sync_time left = (1.0/X) + self.penalty - spent if left > 0: time.sleep(left) @@ -68,6 +69,7 @@ else: self.penalty = left # print "WARNING: Going too slow: ", spent, " ", left + self.sync_time = time.time() def handle_execution_error(self, error): @@ -106,30 +108,48 @@ COLOR_MAP = [0xFFFFFF, 0xCCCCCC, 0x666666, 0x000000] - def __init__(self): + def __init__(self, gameboy): VideoDriver.__init__(self) + + self.create_pixels() + if show_metadata: + self.create_meta_windows(gameboy) self.create_screen() - self.map = [] def create_screen(self): if use_rsdl: self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) - + + def create_meta_windows(self, gameboy): + self.meta_windows = [TileDataWindow(gameboy), + SpriteWindow(gameboy)] + + for window in self.meta_windows: + window.set_origin(self.width, 0) + self.height = max(self.height, window.height) + self.width += window.width + def update_display(self): if use_rsdl: RSDL.LockSurface(self.screen) + if show_metadata: + for meta_window in self.meta_windows: + meta_window.draw() self.draw_pixels() RSDL.UnlockSurface(self.screen) RSDL.Flip(self.screen) else: - print '\x1b[H\x1b[2J' + print '\x1b[H\x1b[2J' # Clear screen self.draw_ascii_pixels() - + + def draw_pixel(self, x, y, color): + color = VideoDriverImplementation.COLOR_MAP[color] + RSDL_helper.set_pixel(self.screen, x, y, color) + def draw_pixels(self): - for y in range(self.height): - for x in range(self.width): - color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] - RSDL_helper.set_pixel(self.screen, x, y, color) + for y in range(constants.GAMEBOY_SCREEN_HEIGHT): + for x in range(constants.GAMEBOY_SCREEN_WIDTH): + self.draw_pixel(x, y, self.pixels[y][x]) def draw_ascii_pixels(self): str = [] @@ -137,17 +157,9 @@ str.append("\n") for x in range(self.width): if y%2 == 0 or True: - str.append(self.get_pixel_color(x, y, string=True)) + str.append(["#", "%", "+", "."][self.pixels[y][x]]) print "".join(str) - @specialize.arg(3) - def get_pixel_color(self, x, y, string=False): - if string: - return ["#", "%", "+", ".", " "][self.get_pixel_color(x, y)] - else: - return self.pixels[y][x] - - # JOYPAD DRIVER ---------------------------------------------------------------- class JoypadDriverImplementation(JoypadDriver): Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Mar 6 02:25:18 2009 @@ -93,13 +93,13 @@ # ----------------------------------------------------------------------- def create_sprites(self): - self.sprites = [None] * 40 - for i in range(40): + self.sprites = [None] * MAX_SPRITES + for i in range(MAX_SPRITES): self.sprites[i] = Sprite(self) def update_all_sprites(self): # TODO: TEST! - for i in range(40): + for i in range(MAX_SPRITES): address = i * 4 self.sprites[i].set_data(self.oam[address + 0], self.oam[address + 1], @@ -112,12 +112,15 @@ def update_sprite_size(self): for sprite in self.sprites: sprite.big_size = self.control.big_sprites - + + def get_sprite_at(self, sprite_index): + return self.sprites[sprite_index] + def get_sprite(self, address): address -= OAM_ADDR # address divided by 4 gives the correct sprite, each sprite has 4 # bytes of attributes - return self.sprites[ int(math.floor(address / 4)) ] + return self.get_sprite_at(address / 4) # ----------------------------------------------------------------------- @@ -447,11 +450,11 @@ # graphics handling -------------------------------------------------------- def draw_frame(self): - self.driver.update_display() + self.driver.update_gb_display() def clear_frame(self): - self.driver.clear_pixels() - self.driver.update_display() + self.driver.clear_gb_pixels() + self.driver.update_gb_display() def draw_line(self): if self.control.background_and_window_lower_tile_data_selected: @@ -482,14 +485,14 @@ lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): sprite = self.shown_sprites[index] - sprite.draw(lastx) + sprite.draw(self.line, self.line_y, lastx) lastx = sprite.x def scan_sprites(self): # search active shown_sprites count = 0 for sprite in self.sprites: - if sprite.is_shown_on_current_line(): + if sprite.is_shown_on_line(self.line_y): self.shown_sprites[count] = sprite count += 1 if count >= SPRITES_PER_LINE: @@ -544,21 +547,20 @@ class VideoDriver(object): def __init__(self): - self.width = int(GAMEBOY_SCREEN_WIDTH) - self.height = int(GAMEBOY_SCREEN_HEIGHT) - self.clear_pixels() - - def clear_pixels(self): - self.pixels = [[0] * self.width for i in range(self.height)] + self.width = GAMEBOY_SCREEN_WIDTH + self.height = GAMEBOY_SCREEN_HEIGHT + + def clear_gb_pixels(self): + for y in range(GAMEBOY_SCREEN_HEIGHT): + for x in range(GAMEBOY_SCREEN_WIDTH): + self.draw_gb_pixel(x, y, 0) def draw_gb_pixel(self, x, y, color): self.pixels[y][x] = color - def get_width(self): - return self.width - - def get_height(self): - return self.height - - def update_display(self): - self.clear_pixels() + def update_gb_display(self): + self.update_display() + + def create_pixels(self): + self.pixels = [[0] * self.width + for i in range(self.height)] Added: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 02:25:18 2009 @@ -0,0 +1,80 @@ +from pypy.lang.gameboy.constants import SPRITE_SIZE, MAX_SPRITES + +# Metadata visualizing windows. + +class VideoMetaWindow(object): + def __init__(self, gameboy, x, y): + self.width = x + self.height = y + self.screen = [[0] * x for i in range(y)] + self.gameboy = gameboy + self.x = 0 + self.y = 0 + + def get_screen(self): + return self.screen + + def set_origin(self, x, y): + self.x = x + self.y = y + + def draw(self): + self.update_screen() + self.draw_on_driver() + + def update_screen(self): + raise Exception("Not implemented") + + def draw_on_driver(self): + for y in range(self.height): + line = self.screen[y] + for x in range(self.width): + self.gameboy.video_driver.draw_pixel(x + self.x, + y + self.y, + self.gameboy.video.palette[self.screen[y][x]]) + + def clear_screen(self): + for line in self.screen: + for x in range(len(line)): + line[x] = 0 + +class TileDataWindow(VideoMetaWindow): + def __init__(self, gameboy): + self.tiles_x = 24 + self.tiles_y = 16 + VideoMetaWindow.__init__(self, gameboy, + self.tiles_x * SPRITE_SIZE, + self.tiles_y * SPRITE_SIZE) + + def update_screen(self): + for y_id in range(self.tiles_y): + for x_id in range(self.tiles_x): + tile = self.gameboy.video.get_tile_at(x_id * self.tiles_y + y_id) + for y_offset in range(SPRITE_SIZE): + line = self.screen[y_offset + y_id * SPRITE_SIZE] + tile.draw(line, x_id * SPRITE_SIZE, y_offset) + +class SpriteWindow(VideoMetaWindow): + def __init__(self, gameboy): + self.sprites_y = 8 + self.sprites_x = MAX_SPRITES / self.sprites_y + VideoMetaWindow.__init__(self, gameboy, + self.sprites_x * SPRITE_SIZE, + self.sprites_y * SPRITE_SIZE * 2) # Double sprites + + def update_screen(self): + self.clear_screen() + for y_id in range(self.sprites_y): + for x_id in range(self.sprites_x): + sprite = self.gameboy.video.get_sprite_at(y_id * self.sprites_x + x_id) + for y_offset in range(SPRITE_SIZE * (1 + sprite.big_size)): + line = self.screen[y_offset + y_id * SPRITE_SIZE * 2] + tile = sprite.get_tile_for_relative_line(y_offset) + if sprite.y_flipped: + y_offset = SPRITE_SIZE - 1 - y_offset + tile.draw(line, x_id * SPRITE_SIZE, y_offset) + + for x in range(SPRITE_SIZE): + x += x_id * SPRITE_SIZE + line[x] = line[x] << 1 # Colors of sprites are in + # another range of the palette. Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Mar 6 02:25:18 2009 @@ -130,8 +130,9 @@ value += self.rest_attributes_and_flags return value - def get_width(self): - return SPRITE_SIZE + # Unused. + #def get_width(self): + # return SPRITE_SIZE def get_height(self): if self.big_size: @@ -148,9 +149,11 @@ address &= 0xFE return address - def get_tile_for_current_line(self): - lower = self.current_line_y() < SPRITE_SIZE - if lower ^ (self.big_size and self.y_flipped): + def get_tile_for_current_line(self, y): + return self.get_tile_for_relative_line(self.current_line_y(y)) + + def get_tile_for_relative_line(self, y): + if (y < SPRITE_SIZE) ^ (self.big_size and self.y_flipped): return self.get_tile() else: return self.get_lower_tile() @@ -172,24 +175,26 @@ self.hidden = False return self.hidden - def intersects_current_line(self): - y = self.current_line_y() + def intersects_current_line(self, line_y): + y = self.current_line_y(line_y) return y >= 0 and y < self.get_height() - def is_shown_on_current_line(self): - return not self.hidden and self.intersects_current_line() + def is_shown_on_line(self, line_y): + return not self.hidden and self.intersects_current_line(line_y) - def current_line_y(self): - return (self.video.line_y - self.y) + 2 * SPRITE_SIZE + def current_line_y(self, y): + return (y - self.y) + 2 * SPRITE_SIZE - def get_draw_y(self): - y = self.current_line_y() + def get_draw_y(self, line_y): + y = self.current_line_y(line_y) if self.y_flipped: y = self.get_height() - 1 - y return y - def draw(self, lastx): - self.get_tile_for_current_line().draw_for_sprite(self, self.video.line, lastx) + def draw(self, line, line_y, lastx): + tile = self.get_tile_for_current_line(line_y) + draw_y = self.get_draw_y(line_y) + tile.draw_for_sprite(self, line, draw_y, lastx) # ----------------------------------------------------------------------------- @@ -201,8 +206,8 @@ def draw(self, line, x, y): pattern = self.get_pattern_at(y << 1) for i in range(SPRITE_SIZE): - value = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 - line[x + i] = value + color = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 + line[x + i] = color def set_tile_data(self, data): self.data = data @@ -220,13 +225,13 @@ return self.get_data_at(address) +\ (self.get_data_at(address + 1) << 8) - def draw_for_sprite(self, sprite, line, lastx): + def draw_for_sprite(self, sprite, line, y, lastx): if sprite.x_flipped: convert, offset = 1, 0 # 0-7 else: convert, offset = -1, SPRITE_SIZE # 7-0 - y = sprite.get_draw_y() << 1 + y = y << 1 # 2 bytes per line pattern = self.get_pattern_at(y) << 1 mask = (sprite.palette_number << 2) +\ (sprite.object_behind_background << 3) From fijal at codespeak.net Fri Mar 6 02:45:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 02:45:40 +0100 (CET) Subject: [pypy-svn] r62624 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090306014540.DE7671684A6@codespeak.net> Author: fijal Date: Fri Mar 6 02:45:39 2009 New Revision: 62624 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: a test and a strange fix, that is a bit unrelated to test :( Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 02:45:39 2009 @@ -69,7 +69,7 @@ ad = ConstInt(ld.arraydescr) if instnode.cursize == -1: # fish fish fish - instnode.cursize= cpu.execute_operation(rop.ARRAYLEN_GC, + instnode.cursize = cpu.execute_operation(rop.ARRAYLEN_GC, [instnode.source, ad], 'int').getint() self.list_allocations.append((ad, instnode.cursize)) @@ -158,7 +158,7 @@ ofs in self.vdesc.virtuals): node.add_to_dependency_graph(other.origfields[ofs], dep_graph) - def intersect(self, other): + def intersect(self, other, nodes): if not other.cls: return NotSpecNode() if self.cls: @@ -175,21 +175,23 @@ return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: + fields = [] if self is other: - d = other.curfields.copy() - d.update(self.origfields) + d = self.origfields.copy() + d.update(other.curfields) else: d = other.curfields lst = d.keys() sort_integers(lst) for ofs in lst: node = d[ofs] - if ofs in self.origfields: - specnode = self.origfields[ofs].intersect(node) - else: - self.origfields[ofs] = InstanceNode(node.source.clonebox()) - specnode = NotSpecNode() + if ofs not in self.origfields: + box = node.source.clonebox() + self.origfields[ofs] = InstanceNode(box, escaped=False) + self.origfields[ofs].cls = node.cls + nodes[box] = self.origfields[ofs] + specnode = self.origfields[ofs].intersect(node, nodes) fields.append((ofs, specnode)) if isinstance(known_class, FixedList): return VirtualFixedListSpecNode(known_class, fields, @@ -215,10 +217,10 @@ for ofs in offsets: if ofs in self.origfields and ofs in other.curfields: node = other.curfields[ofs] - specnode = self.origfields[ofs].intersect(node) + specnode = self.origfields[ofs].intersect(node, nodes) elif ofs in self.origfields: node = self.origfields[ofs] - specnode = node.intersect(node) + specnode = node.intersect(node, nodes) else: # ofs in other.curfields node = other.curfields[ofs] @@ -585,7 +587,7 @@ for i in range(len(mp.args)): enternode = self.nodes[mp.args[i]] leavenode = self.getnode(jump.args[i]) - specnodes.append(enternode.intersect(leavenode)) + specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes def expanded_version_of(self, boxlist, oplist): @@ -724,6 +726,9 @@ # self.ready_results[arg] = None elif opnum == rop.JUMP: args = self.expanded_version_of(op.args, newoperations) + for arg in args: + if arg in self.nodes: + assert not self.nodes[arg].virtual self.cleanup_field_caches(newoperations) op = ResOperation(rop.JUMP, args, None) newoperations.append(op) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Fri Mar 6 02:45:39 2009 @@ -218,6 +218,31 @@ res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == 3 + def test_virtual_on_virtual(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'parent']) + + class Node(object): + def __init__(self, f): + self.f = f + + class SubNode(object): + def __init__(self, f): + self.f = f + + def f(n): + node = Node(SubNode(3)) + while n > 0: + myjitdriver.can_enter_jit(n=n, parent=node) + myjitdriver.jit_merge_point(n=n, parent=node) + node = Node(SubNode(n + 1)) + if n == -3: + return 8 + n -= 1 + return node.f.f + + res = self.meta_interp(f, [10]) + assert res == 2 + ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) From fijal at codespeak.net Fri Mar 6 02:50:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 02:50:01 +0100 (CET) Subject: [pypy-svn] r62625 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090306015001.5762F1684AB@codespeak.net> Author: fijal Date: Fri Mar 6 02:50:00 2009 New Revision: 62625 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: Add asserts Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Fri Mar 6 02:50:00 2009 @@ -6,6 +6,7 @@ while i < 100: i = i + 3 print i + assert i == 102 def f1(): print "simple loop with inplace_add" @@ -14,14 +15,16 @@ while i < 100: i += 3 print i + assert i == 102 def f(): - print 543210 + print "range object, but outside the loop" s = 0 for i in range(100): # XXX implement inplace_add method for ints s = s + i - print s # should print 102 + print s + assert s == 4950 f() From fijal at codespeak.net Fri Mar 6 02:50:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 02:50:38 +0100 (CET) Subject: [pypy-svn] r62626 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090306015038.2222316803B@codespeak.net> Author: fijal Date: Fri Mar 6 02:50:37 2009 New Revision: 62626 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Log: pom pom pom. see range object (at least some of that). this makes for i in range(xxx) quite efficient Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Fri Mar 6 02:50:37 2009 @@ -114,8 +114,8 @@ pypy.objspace.std.intobject.nonzero__Int) self.seepath(pypy.interpreter.pyframe.PyFrame.FOR_ITER, pypy.objspace.descroperation.DescrOperation.next, - pypy.objspace.std.rangeobject.next__RangeIter) -# pypy.objspace.std.rangeobject.) + pypy.objspace.std.rangeobject.next__RangeIter, + pypy.objspace.std.rangeobject.W_RangeListObject.getitem) # #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, # pypy.interpreter.function.Function.funccall_valuestack) From tverwaes at codespeak.net Fri Mar 6 03:32:07 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 03:32:07 +0100 (CET) Subject: [pypy-svn] r62627 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306023207.378D2168488@codespeak.net> Author: tverwaes Date: Fri Mar 6 03:32:05 2009 New Revision: 62627 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_meta.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: adding viz for foreground and background. still a bug in the foreground though... Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Mar 6 03:32:05 2009 @@ -5,12 +5,13 @@ from pypy.lang.gameboy.video import VideoDriver from pypy.lang.gameboy.sound import SoundDriver from pypy.lang.gameboy.timer import Clock -from pypy.lang.gameboy.video_meta import TileDataWindow, SpriteWindow +from pypy.lang.gameboy.video_meta import TileDataWindow, SpriteWindow,\ + WindowPreview, BackgroundPreview from pypy.lang.gameboy import constants import time use_rsdl = True -show_metadata = False # Extends the window with windows visualizing meta-data +show_metadata = True # Extends the window with windows visualizing meta-data if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper @@ -122,7 +123,9 @@ def create_meta_windows(self, gameboy): self.meta_windows = [TileDataWindow(gameboy), - SpriteWindow(gameboy)] + SpriteWindow(gameboy), + WindowPreview(gameboy), + BackgroundPreview(gameboy)] for window in self.meta_windows: window.set_origin(self.width, 0) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Mar 6 03:32:05 2009 @@ -456,31 +456,28 @@ self.driver.clear_gb_pixels() self.driver.update_gb_display() - def draw_line(self): + def tile_index_flip(self): if self.control.background_and_window_lower_tile_data_selected: - tile_index_flip = 0x00 + return 0x00 else: - tile_index_flip = 0x80 - tile_data = self.get_selected_tile_data_space() + return 0x80 - if self.background.enabled: - self.background.draw_line(self.line_y, - tile_data, - tile_index_flip, - self.line) + def draw_window(self, window, line_y, line): + if window.enabled: + tile_data = self.get_selected_tile_data_space() + tile_index_flip = self.tile_index_flip() + window.draw_line(line_y, tile_data, tile_index_flip, line) else: - self.background.draw_clean_line(self.line) - if self.window.enabled: - self.window.draw_line(self.line_y, - tile_data, - tile_index_flip, - self.line) - if self.control.sprites_enabled: - self.draw_sprites_line() - self.draw_pixels_line() + window.draw_clean_line(self.line) + def draw_line(self): + self.draw_window(self.background, self.line_y, self.line) + self.draw_window(self.window, self.line_y, self.line) + self.draw_sprites_line() + self.send_pixels_line_to_driver() def draw_sprites_line(self): + if not self.control.sprites_enabled: return count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): @@ -511,7 +508,7 @@ self.shown_sprites[index], self.shown_sprites[highest] = \ self.shown_sprites[highest], self.shown_sprites[index] - def draw_pixels_line(self): + def send_pixels_line_to_driver(self): self.update_palette() for x in range(0, GAMEBOY_SCREEN_WIDTH): color = self.palette[self.line[SPRITE_SIZE + x]] Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 03:32:05 2009 @@ -1,4 +1,6 @@ -from pypy.lang.gameboy.constants import SPRITE_SIZE, MAX_SPRITES +from pypy.lang.gameboy.constants import SPRITE_SIZE, MAX_SPRITES,\ + GAMEBOY_SCREEN_HEIGHT,\ + GAMEBOY_SCREEN_WIDTH # Metadata visualizing windows. @@ -54,6 +56,28 @@ line = self.screen[y_offset + y_id * SPRITE_SIZE] tile.draw(line, x_id * SPRITE_SIZE, y_offset) +class PreviewWindow(VideoMetaWindow): + def __init__(self, gameboy): + VideoMetaWindow.__init__(self, gameboy, + SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE, + SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE) + + def get_window(self): + raise Exception("Not Implemented") + + def update_screen(self): + for y in range(self.height): + line = self.screen[y] + self.gameboy.video.draw_window(self.get_window(), y, line) + +class WindowPreview(PreviewWindow): + def get_window(self): + return self.gameboy.video.window + +class BackgroundPreview(PreviewWindow): + def get_window(self): + return self.gameboy.video.background + class SpriteWindow(VideoMetaWindow): def __init__(self, gameboy): self.sprites_y = 8 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Mar 6 03:32:05 2009 @@ -271,6 +271,12 @@ group_index += 1 x += SPRITE_SIZE + def draw_line(self, line_y, tile_data, tile_index_flip, line): + raise Exception("Not implemented") + + def draw_clean_line(self, line): + raise Exception("Not implemented") + class Window(Drawable): def reset(self): @@ -283,6 +289,9 @@ def switch_on(self): if self.line_y == 0 and self.video.line_y > self.y: self.line_y = GAMEBOY_SCREEN_HEIGHT + + def draw_clean_line(self, line): + pass def draw_line(self, line_y, tile_data, tile_index_flip, line): if line_y >= self.y and self.x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE-1 and \ From tverwaes at codespeak.net Fri Mar 6 03:55:13 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 03:55:13 +0100 (CET) Subject: [pypy-svn] r62628 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306025513.CE4E016850C@codespeak.net> Author: tverwaes Date: Fri Mar 6 03:55:13 2009 New Revision: 62628 Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py Log: redundant pixels Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 03:55:13 2009 @@ -60,7 +60,7 @@ def __init__(self, gameboy): VideoMetaWindow.__init__(self, gameboy, SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE, - SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE) + GAMEBOY_SCREEN_HEIGHT) def get_window(self): raise Exception("Not Implemented") @@ -72,6 +72,7 @@ class WindowPreview(PreviewWindow): def get_window(self): + # XXX Broken for now return self.gameboy.video.window class BackgroundPreview(PreviewWindow): From fijal at codespeak.net Fri Mar 6 09:36:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 09:36:34 +0100 (CET) Subject: [pypy-svn] r62629 - pypy/branch/pyjitpl5/pypy/translator/backendopt Message-ID: <20090306083634.A56C51684B1@codespeak.net> Author: fijal Date: Fri Mar 6 09:36:30 2009 New Revision: 62629 Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py Log: oops Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/backendopt/support.py Fri Mar 6 09:36:30 2009 @@ -111,7 +111,8 @@ if memo and graph in memo: return memo[graph] res = [i for i in _find_calls_from(translator, graph)] - memo[graph] = res + if memo is not None: + memo[graph] = res return res def _find_calls_from(translator, graph): From hpk at codespeak.net Fri Mar 6 11:25:35 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 6 Mar 2009 11:25:35 +0100 (CET) Subject: [pypy-svn] r62631 - pypy/dist/pypy/doc Message-ID: <20090306102535.7BE9816850C@codespeak.net> Author: hpk Date: Fri Mar 6 11:25:32 2009 New Revision: 62631 Modified: pypy/dist/pypy/doc/coding-guide.txt pypy/dist/pypy/doc/confrest.py pypy/dist/pypy/doc/getting-started.txt pypy/dist/pypy/doc/interpreter.txt pypy/dist/pypy/doc/maemo.txt pypy/dist/pypy/doc/rffi.txt pypy/dist/pypy/doc/svn-help.txt pypy/dist/pypy/doc/theory.txt Log: fixing links to go to dist, not trunk Modified: pypy/dist/pypy/doc/coding-guide.txt ============================================================================== --- pypy/dist/pypy/doc/coding-guide.txt (original) +++ pypy/dist/pypy/doc/coding-guide.txt Fri Mar 6 11:25:32 2009 @@ -173,7 +173,7 @@ enables the code generator to emit efficient machine level replacements for pure integer objects, for instance. -.. _`pyopcode.py`: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/pyopcode.py +.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py Restricted Python ================= @@ -861,11 +861,11 @@ allows checkin/checkout in native line-ending format. - branching (aka "svn copy") of source code should usually - happen at ``svn/pypy/trunk`` level in order to have a full + happen at ``svn/pypy/dist`` level in order to have a full self-contained pypy checkout for each branch. For branching a ``try1`` branch you would for example do:: - svn cp http://codespeak.net/svn/pypy/trunk \ + svn cp http://codespeak.net/svn/pypy/dist \ http://codespeak.net/svn/pypy/branch/try1 This allows to checkout the ``try1`` branch and receive a Modified: pypy/dist/pypy/doc/confrest.py ============================================================================== --- pypy/dist/pypy/doc/confrest.py (original) +++ pypy/dist/pypy/doc/confrest.py Fri Mar 6 11:25:32 2009 @@ -20,7 +20,7 @@ html.a("documentation", href=self.get_doclink("index.html"), class_="menu"), " ", - html.a("svn", href="https://codespeak.net/viewvc/pypy/trunk/", + html.a("svn", href="https://codespeak.net/viewvc/pypy/dist/", class_="menu"), " ", html.a("issues", Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri Mar 6 11:25:32 2009 @@ -43,7 +43,7 @@ some `help on installing subversion`_ for PyPy. Then you can issue on the command line (DOS box or terminal):: - svn co http://codespeak.net/svn/pypy/trunk pypy-dist + svn co http://codespeak.net/svn/pypy/dist pypy-dist This will create a directory named ``pypy-dist``, and will get you the PyPy source in ``pypy-dist/pypy`` and documentation files in @@ -868,15 +868,15 @@ .. _`Dot Graphviz`: http://www.graphviz.org/ .. _Pygame: http://www.pygame.org/ -.. _pyopcode.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/pyopcode.py -.. _eval.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/eval.py -.. _pyframe.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/pyframe.py -.. _function.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/function.py -.. _argument.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/argument.py -.. _baseobjspace.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/baseobjspace.py -.. _module.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/module.py -.. _mixedmodule.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/mixedmodule.py -.. _typedef.py: http://codespeak.net/svn/pypy/trunk/pypy/interpreter/typedef.py +.. _pyopcode.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py +.. _eval.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/eval.py +.. _pyframe.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyframe.py +.. _function.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/function.py +.. _argument.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/argument.py +.. _baseobjspace.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/baseobjspace.py +.. _module.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/module.py +.. _mixedmodule.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/mixedmodule.py +.. _typedef.py: http://codespeak.net/svn/pypy/dist/pypy/interpreter/typedef.py .. _Standard object space: objspace.html#the-standard-object-space .. _objspace.py: ../../pypy/objspace/std/objspace.py .. _thunk: ../../pypy/objspace/thunk.py Modified: pypy/dist/pypy/doc/interpreter.txt ============================================================================== --- pypy/dist/pypy/doc/interpreter.txt (original) +++ pypy/dist/pypy/doc/interpreter.txt Fri Mar 6 11:25:32 2009 @@ -269,7 +269,7 @@ example and the higher level `chapter on Modules in the coding guide`_. -.. _`__builtin__ module`: http://codespeak.net/svn/pypy/trunk/pypy/module/ +.. _`__builtin__ module`: http://codespeak.net/svn/pypy/dist/pypy/module/ .. _`chapter on Modules in the coding guide`: coding-guide.html#modules .. _`Gateway classes`: Modified: pypy/dist/pypy/doc/maemo.txt ============================================================================== --- pypy/dist/pypy/doc/maemo.txt (original) +++ pypy/dist/pypy/doc/maemo.txt Fri Mar 6 11:25:32 2009 @@ -135,7 +135,7 @@ Now, on the host system, perform a subversion checkout of PyPy:: - svn co https://codespeak.net/svn/pypy/trunk pypy-trunk + svn co https://codespeak.net/svn/pypy/dist pypy-trunk Several svn revisions since the 60000's are known to work and the last manually tested one is currently 65011. Modified: pypy/dist/pypy/doc/rffi.txt ============================================================================== --- pypy/dist/pypy/doc/rffi.txt (original) +++ pypy/dist/pypy/doc/rffi.txt Fri Mar 6 11:25:32 2009 @@ -42,7 +42,7 @@ See cbuild_ for more info on ExternalCompilationInfo. -.. _cbuild: http://codespeak.net/svn/pypy/trunk/pypy/translator/tool/cbuild.py +.. _cbuild: http://codespeak.net/svn/pypy/dist/pypy/translator/tool/cbuild.py Types @@ -55,7 +55,7 @@ flavor='raw'. There are several helpers like string -> char* converter, refer to the source for details. -.. _rffi: http://codespeak.net/svn/pypy/trunk/pypy/rpython/lltypesystem/rffi.py +.. _rffi: http://codespeak.net/svn/pypy/dist/pypy/rpython/lltypesystem/rffi.py Registering function as external --------------------------------- @@ -67,7 +67,7 @@ functions, passing llimpl as an argument and eventually llfakeimpl as a fake low-level implementation for tests performed by an llinterp. -.. _`extfunc.py`: http://codespeak.net/svn/pypy/trunk/pypy/rpython/extfunc.py +.. _`extfunc.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/extfunc.py OO backends Modified: pypy/dist/pypy/doc/svn-help.txt ============================================================================== --- pypy/dist/pypy/doc/svn-help.txt (original) +++ pypy/dist/pypy/doc/svn-help.txt Fri Mar 6 11:25:32 2009 @@ -40,7 +40,7 @@ deb http://fs.cs.fhm.edu/mirror/backports.org/debian stable subversion -Note that you can always go look at the files online_ with your browser, located at: http://codespeak.net/svn/pypy/trunk +Note that you can always go look at the files online_ with your browser, located at: http://codespeak.net/svn/pypy/dist But, you'll want to check out your own local copies to work on. Check out and Check in @@ -48,7 +48,7 @@ In order to get the sourcecode and docs downloaded onto your drive, open a shell or commandline and type:: - $ svn co http://codespeak.net/svn/pypy/trunk + $ svn co http://codespeak.net/svn/pypy/dist If you are behind a dump proxy this may or may not work; see below. @@ -149,5 +149,5 @@ .. _Win: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4B6140F9-2D36-4977-8FA1-6F8A0F5DCA8F .. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1 .. _backports: http://www.backports.org -.. _online: http://codespeak.net/svn/pypy/trunk/ +.. _online: http://codespeak.net/svn/pypy/dist/ .. _coding-guide: coding-guide.html Modified: pypy/dist/pypy/doc/theory.txt ============================================================================== --- pypy/dist/pypy/doc/theory.txt (original) +++ pypy/dist/pypy/doc/theory.txt Fri Mar 6 11:25:32 2009 @@ -81,7 +81,7 @@ one`_ written in RPython_ for the purposes of the StdObjSpace_, and a `short two-arguments-dispatching one`_ used internally by the annotator_. -.. _`quite general one`: http://codespeak.net/svn/pypy/trunk/pypy/objspace/std/multimethod.py +.. _`quite general one`: http://codespeak.net/svn/pypy/dist/pypy/objspace/std/multimethod.py .. _StdObjSpace: objspace.html#the-standard-object-space -.. _`short two-arguments-dispatching one`: http://codespeak.net/svn/pypy/trunk/pypy/annotation/pairtype.py +.. _`short two-arguments-dispatching one`: http://codespeak.net/svn/pypy/dist/pypy/annotation/pairtype.py .. _annotator: translation.html#annotator From arigo at codespeak.net Fri Mar 6 13:10:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 13:10:44 +0100 (CET) Subject: [pypy-svn] r62634 - in pypy/branch/pyjitpl5/pypy/jit/backend/llgraph: . test Message-ID: <20090306121044.9444A168489@codespeak.net> Author: arigo Date: Fri Mar 6 13:10:42 2009 New Revision: 62634 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: Code for do_call. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Mar 6 13:10:42 2009 @@ -1002,6 +1002,52 @@ str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) str.chars[index] = chr(newvalue) +# ---------- call ---------- + +_call_args = [] + +def do_call_pushint(x): + _call_args.append(('int', x)) + +def do_call_pushptr(x): + _call_args.append(('ptr', x)) + +def _do_call_common(f, memocast): + ptr = cast_int_to_adr(memocast, f).ptr + FUNC = lltype.typeOf(ptr).TO + ARGS = FUNC.ARGS + args = [] + nextitem = iter(_call_args).next + for i in range(len(ARGS)): + if ARGS[i] is lltype.Void: + x = None + else: + typ, x = nextitem() + if typ == 'ptr': + x = cast_from_ptr(ARGS[i], x) + else: + x = cast_from_int(ARGS[i], x, memocast) + args.append(x) + del _call_args[:] + assert len(ARGS) == len(args) + if hasattr(ptr._obj, 'graph'): + llinterp = _llinterp # it's a global set here by CPU.__init__() + result = llinterp.eval_graph(ptr._obj.graph, args) + else: + result = ptr._obj._callable(*args) + return result + +def do_call_void(f, memocast): + _do_call_common(f, memocast) + +def do_call_int(f, memocast): + x = _do_call_common(f, memocast) + return cast_to_int(x, memocast) + +def do_call_ptr(f, memocast): + x = _do_call_common(f, memocast) + return cast_to_ptr(x) + # ____________________________________________________________ @@ -1102,3 +1148,8 @@ setannotation(do_setfield_raw_ptr, annmodel.s_None) setannotation(do_newstr, annmodel.SomePtr(llmemory.GCREF)) setannotation(do_strsetitem, annmodel.s_None) +setannotation(do_call_pushint, annmodel.s_None) +setannotation(do_call_pushptr, annmodel.s_None) +setannotation(do_call_int, annmodel.SomeInteger()) +setannotation(do_call_ptr, annmodel.SomePtr(llmemory.GCREF)) +setannotation(do_call_void, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Fri Mar 6 13:10:42 2009 @@ -3,6 +3,7 @@ """ from pypy.rpython.lltypesystem import lltype, llmemory, rclass +from pypy.rpython.llinterp import LLInterpreter from pypy.jit.metainterp import history from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.backend.llgraph import llimpl, symbolic @@ -27,6 +28,7 @@ self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats llimpl._rtyper = self.rtyper + llimpl._llinterp = LLInterpreter(self.rtyper) if translate_support_code: self.mixlevelann = annmixlevel self.fielddescrof_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr') @@ -416,6 +418,23 @@ newvalue = args[2].getint() llimpl.do_strsetitem(string, index, newvalue) + def do_call(self, args): + func = args[0].getint() + calldescr = args[1].getint() + for arg in args[2:]: + if (isinstance(arg, history.BoxPtr) or + isinstance(arg, history.ConstPtr)): + llimpl.do_call_pushptr(arg.getptr_base()) + else: + llimpl.do_call_pushint(arg.getint()) + restype = self.typefor(calldescr) + if restype == 'ptr': + return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast)) + elif restype == 'int': + return history.BoxInt(llimpl.do_call_int(func, self.memo_cast)) + else: # restype == 'void' + llimpl.do_call_void(func, self.memo_cast) + class GuardFailed(object): returns = False Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Mar 6 13:10:42 2009 @@ -285,3 +285,18 @@ # cpu.do_strsetitem([x, BoxInt(4), BoxInt(ord('/'))]) assert x.getptr(lltype.Ptr(rstr.STR)).chars[4] == '/' + + def test_do_call(self): + from pypy.rpython.annlowlevel import llhelper + cpu = CPU(None) + # + def func(c): + return chr(ord(c) + 1) + FPTR = lltype.Ptr(lltype.FuncType([lltype.Char], lltype.Char)) + func_ptr = llhelper(FPTR, func) + calldescr = cpu.calldescrof([lltype.Char], lltype.Char) + x = cpu.do_call( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(func_ptr))), + ConstInt(calldescr), + BoxInt(ord('A'))]) + assert x.value == ord('B') From arigo at codespeak.net Fri Mar 6 13:33:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 13:33:35 +0100 (CET) Subject: [pypy-svn] r62638 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/llgraph/test metainterp Message-ID: <20090306123335.23D56168496@codespeak.net> Author: arigo Date: Fri Mar 6 13:33:34 2009 New Revision: 62638 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Add metainterp/executor.py, which collects all operations for a given backend's CPU class. Add a test for the llgraph backend. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Fri Mar 6 13:33:34 2009 @@ -451,3 +451,8 @@ llimpl.frame_clear(self.frame, merge_point._compiled, merge_point._opindex) self.merge_point = merge_point + +# ____________________________________________________________ + +import pypy.jit.metainterp.executor +pypy.jit.metainterp.executor.make_execute_list(CPU) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Mar 6 13:33:34 2009 @@ -5,6 +5,7 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, Const, ConstInt from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.metainterp.executor import get_execute_function from pypy.jit.backend.llgraph.runner import CPU, GuardFailed @@ -300,3 +301,11 @@ ConstInt(calldescr), BoxInt(ord('A'))]) assert x.value == ord('B') + + def test_executor(self): + cpu = CPU(None) + fn = get_execute_function(cpu, rop.INT_ADD) + assert fn(cpu, [BoxInt(100), ConstInt(42)]).value == 142 + fn = get_execute_function(cpu, rop.NEWSTR) + s = fn(cpu, [BoxInt(8)]) + assert len(s.getptr(lltype.Ptr(rstr.STR)).chars) == 8 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Fri Mar 6 13:33:34 2009 @@ -0,0 +1,173 @@ +"""This implements pyjitpl's execution of operations. +""" + +import py +from pypy.rlib.rarithmetic import ovfcheck, r_uint +from pypy.jit.metainterp.history import BoxInt, ConstInt, BoxPtr +from pypy.jit.metainterp.resoperation import rop + + +# Operations in the _ALWAYS_PURE part of the table of resoperation.py +# must return a ConstInt or ConstPtr. Other operations must return +# a BoxInt or BoxPtr or None. + +# ____________________________________________________________ + +def do_int_add(cpu, args): + return ConstInt(args[0].getint() + args[1].getint()) + +def do_int_sub(cpu, args): + return ConstInt(args[0].getint() - args[1].getint()) + +def do_int_mul(cpu, args): + return ConstInt(args[0].getint() * args[1].getint()) + +def do_int_floordiv(cpu, args): + return ConstInt(args[0].getint() // args[1].getint()) + +def do_int_mod(cpu, args): + return ConstInt(args[0].getint() % args[1].getint()) + +def do_int_and(cpu, args): + return ConstInt(args[0].getint() & args[1].getint()) + +def do_int_or(cpu, args): + return ConstInt(args[0].getint() | args[1].getint()) + +def do_int_xor(cpu, args): + return ConstInt(args[0].getint() ^ args[1].getint()) + +def do_int_rshift(cpu, args): + return ConstInt(args[0].getint() >> args[1].getint()) + +def do_int_lshift(cpu, args): + return ConstInt(args[0].getint() << args[1].getint()) + +do_uint_add = do_int_add +do_uint_sub = do_int_sub +do_uint_mul = do_int_mul + +# ---------- + +def do_int_lt(cpu, args): + return ConstInt(args[0].getint() < args[1].getint()) + +def do_int_le(cpu, args): + return ConstInt(args[0].getint() <= args[1].getint()) + +def do_int_eq(cpu, args): + return ConstInt(args[0].getint() == args[1].getint()) + +def do_int_ne(cpu, args): + return ConstInt(args[0].getint() != args[1].getint()) + +def do_int_gt(cpu, args): + return ConstInt(args[0].getint() > args[1].getint()) + +def do_int_ge(cpu, args): + return ConstInt(args[0].getint() >= args[1].getint()) + +def do_uint_lt(cpu, args): + return ConstInt(r_uint(args[0].getint()) < r_uint(args[1].getint())) + +def do_uint_le(cpu, args): + return ConstInt(r_uint(args[0].getint()) <= r_uint(args[1].getint())) + +do_uint_eq = do_int_eq +do_uint_ne = do_int_ne + +def do_uint_gt(cpu, args): + return ConstInt(r_uint(args[0].getint()) > r_uint(args[1].getint())) + +def do_uint_ge(cpu, args): + return ConstInt(r_uint(args[0].getint()) >= r_uint(args[1].getint())) + +# ---------- + +def do_int_is_true(cpu, args): + return ConstInt(bool(args[0].getint())) + +def do_int_neg(cpu, args): + return ConstInt(-args[0].getint()) + +def do_int_invert(cpu, args): + return ConstInt(~args[0].getint()) + +def do_bool_not(cpu, args): + return ConstInt(not args[0].getint()) + +def do_oononnull(cpu, args): + return ConstInt(bool(args[0].getptr_base())) + +def do_ooisnull(cpu, args): + return ConstInt(not args[0].getptr_base()) + +def do_oois(cpu, args): + return ConstInt(args[0].getptr_base() == args[1].getptr_base()) + +def do_ooisnot(cpu, args): + return ConstInt(args[0].getptr_base() != args[1].getptr_base()) + +# ---------- +# the following operations just delegate to the cpu: + +# do_arraylen_gc +# do_strlen +# do_strgetitem +# do_getarrayitem_gc +# do_getfield_gc +# do_getfield_raw +# do_new +# do_new_with_vtable +# do_new_array +# do_setarrayitem_gc +# do_setfield_gc +# do_setfield_raw +# do_newstr +# do_strsetitem +# do_call + +# ---------- + +def do_int_add_ovf(cpu, args): + return BoxInt(ovfcheck(args[0].getint() + args[1].getint())) + +def do_int_sub_ovf(cpu, args): + return BoxInt(ovfcheck(args[0].getint() - args[1].getint())) + +def do_int_mul_ovf(cpu, args): + return BoxInt(ovfcheck(args[0].getint() * args[1].getint())) + +def do_int_neg_ovf(cpu, args): + return BoxInt(ovfcheck(-args[0].getint())) + +def do_int_mod_ovf(cpu, args): + return BoxInt(ovfcheck(args[0].getint() % args[1].getint())) + +# ____________________________________________________________ + + +def make_execute_list(cpuclass): + execute = [None] * (rop._LAST+1) + for key, value in rop.__dict__.items(): + if not key.startswith('_'): + if (rop._SPECIAL_FIRST <= value <= rop._SPECIAL_LAST or + rop._GUARD_FIRST <= value <= rop._GUARD_LAST): + continue + if execute[value] is not None: + raise Exception("duplicate entry for op number %d" % value) + if key.endswith('_PURE'): + key = key[:-5] + name = 'do_' + key.lower() + try: + execute[value] = getattr(cpuclass, name) + except AttributeError: + execute[value] = globals()[name] + cpuclass._execute_list = execute + +def get_execute_function(cpu, opnum): + # workaround for an annotation limitation: putting this code in + # a specialize:memo function makes sure the following line is + # constant-folded away. Only works if opnum is a constant, of course. + return cpu._execute_list[opnum] +get_execute_function._annspecialcase_ = 'specialize:memo' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Fri Mar 6 13:33:34 2009 @@ -68,10 +68,12 @@ class rop(object): """The possible names of the ResOperations.""" + _SPECIAL_FIRST = 1 MERGE_POINT = 1 CATCH = 2 JUMP = 3 RETURN = 4 + _SPECIAL_LAST = 9 _GUARD_FIRST = 10 # ----- start of guard operations ----- GUARD_TRUE = 10 From arigo at codespeak.net Fri Mar 6 13:52:43 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 13:52:43 +0100 (CET) Subject: [pypy-svn] r62639 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090306125243.56B9116849A@codespeak.net> Author: arigo Date: Fri Mar 6 13:52:42 2009 New Revision: 62639 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Use the new executor module (only from one place so far, more to follow). Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Fri Mar 6 13:52:42 2009 @@ -67,6 +67,9 @@ def constbox(self): raise NotImplementedError + def nonconstbox(self): + raise NotImplementedError + def getaddr(self, cpu): raise NotImplementedError @@ -128,6 +131,8 @@ def clonebox(self): return BoxInt(self.value) + nonconstbox = clonebox + def getint(self): return self.value @@ -162,6 +167,8 @@ def clonebox(self): return BoxInt(self.cpu.cast_adr_to_int(self.value)) + nonconstbox = clonebox + def getint(self): return self.cpu.cast_adr_to_int(self.value) @@ -187,6 +194,8 @@ def clonebox(self): return BoxPtr(self.value) + nonconstbox = clonebox + def getptr_base(self): return self.value @@ -219,6 +228,9 @@ def equals(self, other): return self is other + def nonconstbox(self): + return self + def __repr__(self): result = str(self) if self._extended_display: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 13:52:42 2009 @@ -15,6 +15,7 @@ from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) from pypy.jit.metainterp import codewriter, optimize +from pypy.jit.metainterp.executor import get_execute_function from pypy.rlib.rarithmetic import intmask # ____________________________________________________________ @@ -776,16 +777,20 @@ def execute_and_record(self, opnum, argboxes, result_type): # execute the operation first - resbox = self.cpu.execute_operation(opnum, argboxes, result_type) + func = get_execute_function(self.cpu, opnum) + resbox = func(self.cpu, argboxes) # check if the operation can be constant-folded away canfold = False if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: # this part disappears if execute() is specialized for an # opnum that is not within the range - assert resbox is not None canfold = self._all_constants(argboxes) if canfold: - resbox = resbox.constbox() + resbox = resbox.constbox() # ensure it is a Const + else: + resbox = resbox.nonconstbox() # ensure it is a Box + else: + assert resbox is None or isinstance(resbox, Box) # record the operation if not constant-folded away if not canfold: self.history.record(opnum, argboxes, resbox) From arigo at codespeak.net Fri Mar 6 14:08:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 14:08:45 +0100 (CET) Subject: [pypy-svn] r62640 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090306130845.0B4CF1684AA@codespeak.net> Author: arigo Date: Fri Mar 6 14:08:44 2009 New Revision: 62640 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Use the executor module more. Kill the 3rd argument to execute() and execute_and_record(), i.e. the result type. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Mar 6 14:08:44 2009 @@ -672,7 +672,7 @@ argtypes = [v.concretetype for v in args] resulttype = op.result.concretetype calldescr = self.cpu.calldescrof(argtypes, resulttype) - self.emit('residual_call') + self.emit('residual_call_%s' % getkind(resulttype)) self.emit(self.var_position(op.args[0])) self.emit(self.const_position(calldescr)) self.emit_varargs(args) @@ -717,7 +717,7 @@ if oopspec_name.endswith('_foldable'): opname = 'residual_call_pure' # XXX not for possibly-raising calls else: - opname = 'residual_call' + opname = 'residual_call_%s' % getkind(resulttype) calldescr = self.cpu.calldescrof(argtypes, resulttype) self.emit(opname) self.emit(self.var_position(c_func)) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 14:08:44 2009 @@ -1027,14 +1027,12 @@ sizebox = ConstInt(metainterp.class_sizes[vtable]) vtablebox = ConstInt(vtable) instbox = metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - [sizebox, vtablebox], - 'ptr') + [sizebox, vtablebox]) allocated_boxes.append(instbox) for ad, lgt in storage.list_allocations: sizebox = ConstInt(lgt) listbox = metainterp.execute_and_record(rop.NEW_ARRAY, - [ad, sizebox], - 'ptr') + [ad, sizebox]) allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: fieldbox = box_from_index(allocated_boxes, allocated_lists, @@ -1043,16 +1041,14 @@ boxes_from_frame, index_in_alloc) metainterp.execute_and_record(rop.SETFIELD_GC, - [box, ConstInt(ofs), fieldbox], - 'void') + [box, ConstInt(ofs), fieldbox]) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) metainterp.execute_and_record(rop.SETARRAYITEM_GC, - [box, ad, ConstInt(ofs), itembox], - 'void') + [box, ad, ConstInt(ofs), itembox]) ## if storage.setitems: ## #history.execute_and_record('guard_no_exception', [], 'void', False) ## # XXX this needs to check for exceptions somehow Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 14:08:44 2009 @@ -3,7 +3,7 @@ from pypy.rpython.llinterp import LLException from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib.objectmodel import we_are_translated, r_dict +from pypy.rlib.objectmodel import we_are_translated, r_dict, instantiate from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.debug import debug_print @@ -234,7 +234,7 @@ exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - self.execute(rop.%s, [b1, b2], "int") + self.execute(rop.%s, [b1, b2]) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', 'int_mod_ovf', @@ -242,7 +242,7 @@ exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - return self.execute_with_exc(rop.%s, [b1, b2], "int") + return self.execute_with_exc(rop.%s, [b1, b2], returnsBoxInt) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', @@ -250,7 +250,7 @@ exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - self.execute(rop.%s, [b], "int") + self.execute(rop.%s, [b]) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_neg_ovf', @@ -258,7 +258,7 @@ exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - return self.execute_with_exc(rop.%s, [b], "int") + return self.execute_with_exc(rop.%s, [b], returnsBoxInt) ''' % (_opimpl, _opimpl.upper())).compile() @arguments() @@ -313,91 +313,83 @@ @arguments("constbox") def opimpl_new(self, sizebox): - self.execute(rop.NEW, [sizebox], 'ptr') + self.execute(rop.NEW, [sizebox]) @arguments("constbox", "constbox") def opimpl_new_with_vtable(self, sizebox, vtablebox): - self.execute(rop.NEW_WITH_VTABLE, [sizebox, vtablebox], 'ptr') + self.execute(rop.NEW_WITH_VTABLE, [sizebox, vtablebox]) @arguments("constbox", "box") def opimpl_new_array(self, itemsizebox, countbox): - self.execute(rop.NEW_ARRAY, [itemsizebox, countbox], 'ptr') + self.execute(rop.NEW_ARRAY, [itemsizebox, countbox]) @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): - tp = self.metainterp.cpu.typefor(arraydesc.getint()) - self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox], tp) + self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox]) @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): - tp = self.metainterp.cpu.typefor(arraydesc.getint()) self.execute(rop.GETARRAYITEM_GC_PURE, - [arraybox, arraydesc, indexbox], tp) + [arraybox, arraydesc, indexbox]) @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): self.execute(rop.SETARRAYITEM_GC, [arraybox, arraydesc, - indexbox, itembox], 'void') + indexbox, itembox]) @arguments("box", "constbox") def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') + self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc]) @arguments("orgpc", "box", "constbox", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): negbox = self.metainterp.execute_and_record( - rop.INT_LT, [indexbox, ConstInt(0)], 'int') + rop.INT_LT, [indexbox, ConstInt(0)]) negbox = self.implement_guard_value(pc, negbox) if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int') + rop.ARRAYLEN_GC, [arraybox, arraydesc]) indexbox = self.metainterp.execute_and_record( - rop.INT_ADD, [indexbox, lenbox], 'int') + rop.INT_ADD, [indexbox, lenbox]) self.make_result_box(indexbox) @arguments("box") def opimpl_ptr_nonzero(self, box): - self.execute(rop.OONONNULL, [box], 'int') + self.execute(rop.OONONNULL, [box]) @arguments("box") def opimpl_ptr_iszero(self, box): - self.execute(rop.OOISNULL, [box], 'int') + self.execute(rop.OOISNULL, [box]) @arguments("box", "box") def opimpl_ptr_eq(self, box1, box2): - self.execute(rop.OOIS, [box1, box2], 'int') + self.execute(rop.OOIS, [box1, box2]) @arguments("box", "box") def opimpl_ptr_ne(self, box1, box2): - self.execute(rop.OOISNOT, [box1, box2], 'int') + self.execute(rop.OOISNOT, [box1, box2]) @arguments("box", "constbox") def opimpl_getfield_gc(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_GC, [box, fielddesc], tp) + self.execute(rop.GETFIELD_GC, [box, fielddesc]) @arguments("box", "constbox") def opimpl_getfield_gc_pure(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc], tp) + self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc]) @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute(rop.SETFIELD_GC, [box, fielddesc, valuebox], - 'void') + self.execute(rop.SETFIELD_GC, [box, fielddesc, valuebox]) @arguments("box", "constbox") def opimpl_getfield_raw(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_RAW, [box, fielddesc], tp) + self.execute(rop.GETFIELD_RAW, [box, fielddesc]) @arguments("box", "constbox") def opimpl_getfield_raw_pure(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc.getint()) - self.execute(rop.GETFIELD_RAW_PURE, [box, fielddesc], tp) + self.execute(rop.GETFIELD_RAW_PURE, [box, fielddesc]) @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute(rop.SETFIELD_RAW, [box, fielddesc, valuebox], - 'void') + self.execute(rop.SETFIELD_RAW, [box, fielddesc, valuebox]) @arguments("bytecode", "varargs") def opimpl_call(self, callee, varargs): @@ -406,16 +398,24 @@ return True @arguments("box", "constbox", "varargs") - def opimpl_residual_call(self, funcbox, calldescr, varargs): - tp = self.metainterp.cpu.typefor(calldescr.getint()) + def opimpl_residual_call_int(self, funcbox, calldescr, varargs): args = [funcbox, calldescr] + varargs - return self.execute_with_exc(rop.CALL, args, tp) + return self.execute_with_exc(rop.CALL, args, returnsBoxInt) + + @arguments("box", "constbox", "varargs") + def opimpl_residual_call_ptr(self, funcbox, calldescr, varargs): + args = [funcbox, calldescr] + varargs + return self.execute_with_exc(rop.CALL, args, returnsBoxPtr) + + @arguments("box", "constbox", "varargs") + def opimpl_residual_call_void(self, funcbox, calldescr, varargs): + args = [funcbox, calldescr] + varargs + return self.execute_with_exc(rop.CALL, args, returnsNone) @arguments("box", "constbox", "varargs") def opimpl_residual_call_pure(self, funcbox, calldescr, varargs): - tp = self.metainterp.cpu.typefor(calldescr.getint()) args = [funcbox, calldescr] + varargs - self.execute(rop.CALL_PURE, args, tp) + self.execute(rop.CALL_PURE, args) ## @arguments("fixedlist", "box", "box") ## def opimpl_list_getitem(self, descr, listbox, indexbox): @@ -479,19 +479,19 @@ @arguments("box") def opimpl_strlen(self, str): - self.execute(rop.STRLEN, [str], 'int') + self.execute(rop.STRLEN, [str]) @arguments("box", "box") def opimpl_strgetitem(self, str, index): - self.execute(rop.STRGETITEM, [str, index], 'int') + self.execute(rop.STRGETITEM, [str, index]) @arguments("box", "box", "box") def opimpl_strsetitem(self, str, index, newchar): - self.execute(rop.STRSETITEM, [str, index, newchar], 'void') + self.execute(rop.STRSETITEM, [str, index, newchar]) @arguments("box") def opimpl_newstr(self, length): - self.execute(rop.NEWSTR, [length], 'ptr') + self.execute(rop.NEWSTR, [length]) @arguments("orgpc", "box", returns="box") def opimpl_guard_value(self, pc, box): @@ -654,18 +654,16 @@ cls = llmemory.cast_ptr_to_adr(obj.typeptr) return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) - def execute(self, opnum, argboxes, result_type): - resbox = self.metainterp.execute_and_record(opnum, argboxes, - result_type) + def execute(self, opnum, argboxes): + resbox = self.metainterp.execute_and_record(opnum, argboxes) if resbox is not None: self.make_result_box(resbox) execute._annspecialcase_ = 'specialize:arg(1)' - def execute_with_exc(self, opnum, argboxes, result_type): - old_index = len(self.metainterp.history.operations) + def execute_with_exc(self, opnum, argboxes, makeresbox): + func = get_execute_function(self.metainterp.cpu, opnum) try: - resbox = self.metainterp.cpu.execute_operation(opnum, argboxes, - result_type) + resbox = func(self.metainterp.cpu, argboxes) except Exception, e: if not we_are_translated(): if not isinstance(e, LLException): @@ -674,13 +672,7 @@ else: evalue = cast_instance_to_base_ptr(e) etype = evalue.typeptr - if result_type == 'void': - resbox = None - else: - if result_type == 'ptr': - resbox = BoxPtr() - else: - resbox = BoxInt() + resbox = makeresbox() else: if not we_are_translated(): self.metainterp._debug_history.append(['call', @@ -775,7 +767,7 @@ return False return True - def execute_and_record(self, opnum, argboxes, result_type): + def execute_and_record(self, opnum, argboxes): # execute the operation first func = get_execute_function(self.cpu, opnum) resbox = func(self.cpu, argboxes) @@ -1029,3 +1021,8 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args + + +def returnsBoxInt(): return BoxInt() +def returnsBoxPtr(): return BoxPtr() +def returnsNone(): return None Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Mar 6 14:08:44 2009 @@ -327,12 +327,9 @@ self.cpu.translate_support_code = False self.ops = [] - def execute_and_record(self, opnum, args, res_type): + def execute_and_record(self, opnum, args): self.ops.append((opnum, args)) - if res_type != 'void': - return 'allocated' - else: - return None + return 'stuff' spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() @@ -347,10 +344,10 @@ [v_sum_b, v_v_b]) expected = [ (rop.NEW_WITH_VTABLE, [E.sizebox, ConstInt(vt)]), - (rop.SETFIELD_GC, ['allocated', ConstInt(E.ofs_value), v_v_b]) + (rop.SETFIELD_GC, ['stuff', ConstInt(E.ofs_value), v_v_b]) ] assert expected == fake_metainterp.ops - assert newboxes == [v_sum_b, 'allocated'] + assert newboxes == [v_sum_b, 'stuff'] # ____________________________________________________________ From arigo at codespeak.net Fri Mar 6 14:25:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 14:25:17 +0100 (CET) Subject: [pypy-svn] r62641 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090306132517.C629F1684D3@codespeak.net> Author: arigo Date: Fri Mar 6 14:25:13 2009 New Revision: 62641 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Log: Remove all remaining calls to cpu.execute_operation(). Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Fri Mar 6 14:25:13 2009 @@ -171,3 +171,8 @@ # constant-folded away. Only works if opnum is a constant, of course. return cpu._execute_list[opnum] get_execute_function._annspecialcase_ = 'specialize:memo' + +def execute(cpu, opnum, argboxes): + func = get_execute_function(cpu, opnum) + return func(cpu, argboxes) +execute._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 14:25:13 2009 @@ -14,6 +14,7 @@ VirtualFixedListSpecNode, #VirtualListSpecNode, ) +from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated #from pypy.jit.metainterp.codewriter import ListDescr @@ -69,9 +70,9 @@ ad = ConstInt(ld.arraydescr) if instnode.cursize == -1: # fish fish fish - instnode.cursize = cpu.execute_operation(rop.ARRAYLEN_GC, - [instnode.source, ad], - 'int').getint() + instnode.cursize = executor.execute(cpu, rop.ARRAYLEN_GC, + [instnode.source, ad] + ).getint() self.list_allocations.append((ad, instnode.cursize)) res = (alloc_offset + 1) << 16 else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 14:25:13 2009 @@ -14,8 +14,7 @@ from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) -from pypy.jit.metainterp import codewriter, optimize -from pypy.jit.metainterp.executor import get_execute_function +from pypy.jit.metainterp import codewriter, optimize, executor from pypy.rlib.rarithmetic import intmask # ____________________________________________________________ @@ -661,9 +660,8 @@ execute._annspecialcase_ = 'specialize:arg(1)' def execute_with_exc(self, opnum, argboxes, makeresbox): - func = get_execute_function(self.metainterp.cpu, opnum) try: - resbox = func(self.metainterp.cpu, argboxes) + resbox = executor.execute(self.metainterp.cpu, opnum, argboxes) except Exception, e: if not we_are_translated(): if not isinstance(e, LLException): @@ -769,8 +767,7 @@ def execute_and_record(self, opnum, argboxes): # execute the operation first - func = get_execute_function(self.cpu, opnum) - resbox = func(self.cpu, argboxes) + resbox = executor.execute(self.cpu, opnum, argboxes) # check if the operation can be constant-folded away canfold = False if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Fri Mar 6 14:25:13 2009 @@ -1,5 +1,6 @@ from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt +from pypy.jit.metainterp import executor class SpecNode(object): @@ -125,11 +126,8 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: - cls = self.known_class.getint() - tp = cpu.typefor(ofs) - fieldbox = cpu.execute_operation(rop.GETFIELD_GC, - [valuebox, ConstInt(ofs)], - tp) + fieldbox = executor.execute(cpu, rop.GETFIELD_GC, + [valuebox, ConstInt(ofs)]) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): @@ -203,9 +201,8 @@ arraydescr = cls.arraydescr ad = ConstInt(arraydescr) for ofs, subspecnode in self.fields: - fieldbox = cpu.execute_operation(rop.GETARRAYITEM_GC, - [valuebox, ad, ConstInt(ofs)], - cpu.typefor(arraydescr)) + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ad, ConstInt(ofs)]) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualizableSpecNode(VirtualizedSpecNode): @@ -252,7 +249,6 @@ cls = self.known_class assert isinstance(cls, FixedList) ad = ConstInt(cls.arraydescr) - fieldbox = cpu.execute_operation(rop.GETARRAYITEM_GC, - [valuebox, ad, ConstInt(ofs)], - cpu.typefor(cls.arraydescr)) + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ad, ConstInt(ofs)]) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) From afa at codespeak.net Fri Mar 6 14:27:16 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Mar 2009 14:27:16 +0100 (CET) Subject: [pypy-svn] r62642 - pypy/trunk/pypy/rpython/module Message-ID: <20090306132716.F35531684E2@codespeak.net> Author: afa Date: Fri Mar 6 14:27:16 2009 New Revision: 62642 Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py Log: Fix the fake implementation of os.stat, so that test_rmmap passes when run with cpython2.4. Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Fri Mar 6 14:27:16 2009 @@ -249,6 +249,8 @@ val = getattr(st, fieldname) if isinstance(TYPE, lltype.Number): rffi.setintfield(ll_tup, 'item%d' % i, int(val)) + elif TYPE is lltype.Float: + setattr(ll_tup, 'item%d' % i, float(val)) else: setattr(ll_tup, 'item%d' % i, val) return ll_tup From arigo at codespeak.net Fri Mar 6 14:35:16 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 14:35:16 +0100 (CET) Subject: [pypy-svn] r62643 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/llgraph/test metainterp Message-ID: <20090306133516.D938C168471@codespeak.net> Author: arigo Date: Fri Mar 6 14:35:15 2009 New Revision: 62643 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Kill execute_operation() in the llgraph backend. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Fri Mar 6 14:35:15 2009 @@ -102,14 +102,13 @@ llimpl.compile_from_guard(c, from_guard._compiled, from_guard._opindex) - def execute_operations_in_new_frame(self, name, merge_point, valueboxes, - result_type=None): + def execute_operations_in_new_frame(self, name, operations, valueboxes): """Perform a 'call' to the given merge point, i.e. create a new CPU frame and use it to execute the operations that follow the merge point. """ - assert result_type is None or isinstance(result_type, str) frame = llimpl.new_frame(self.memo_cast) + merge_point = operations[0] llimpl.frame_clear(frame, merge_point._compiled, merge_point._opindex) for box in valueboxes: if isinstance(box, history.BoxInt): @@ -124,73 +123,6 @@ raise Exception("bad box in valueboxes: %r" % (box,)) return self.loop(frame) - def execute_operation(self, opnum, valueboxes, result_type): - """Execute a single operation, returning the result. - Mostly a hack: falls back to interpreting a complete bridge - containing the operation. - """ - #if opname[0] == '#': - # return None - c = self.get_compiled_single_op(opnum, valueboxes, result_type) - frame = llimpl.new_frame(self.memo_cast) - llimpl.frame_clear(frame, c, 0) - for box in valueboxes: - if box.type == 'int': - llimpl.frame_add_int(frame, box.getint()) - elif box.type == 'ptr': - llimpl.frame_add_ptr(frame, box.getptr_base()) - else: - raise Exception("bad box in valueboxes: %r" % (box,)) - res = llimpl.frame_execute(frame) - assert res == -1 - if result_type == 'int': - return history.BoxInt(llimpl.frame_int_getresult(frame)) - elif result_type == 'ptr': - return history.BoxPtr(llimpl.frame_ptr_getresult(frame)) - else: - return None - - def get_compiled_single_op(self, opnum, valueboxes, result_type): - assert isinstance(opnum, int) - keylist = self.compiled_single_ops.setdefault((opnum, result_type), - []) - types = [valuebox.type for valuebox in valueboxes] - for key, impl in keylist: - if len(key) == len(types): - for i in range(len(key)): - if key[i] is not types[i]: - break - else: - return impl - valueboxes = [] - for type in types: - if type == 'int': - valueboxes.append(history.BoxInt()) - elif type == 'ptr': - valueboxes.append(history.BoxPtr()) - else: - raise AssertionError('valuebox type=%s' % (type,)) - if result_type == 'void': - resbox = None - elif result_type == 'int': - resbox = history.BoxInt() - elif result_type == 'ptr': - resbox = history.BoxPtr() - else: - raise AssertionError(result_type) - resboxes = [] - if resbox is not None: - resboxes.append(resbox) - operations = [ - ResOperation(rop.MERGE_POINT, valueboxes, None), - ResOperation(opnum, valueboxes, resbox), - ResOperation(rop.RETURN, resboxes, None), - ] - self.compile_operations(operations) - impl = operations[0]._compiled - keylist.append((types, impl)) - return impl - def loop(self, frame): """Execute a loop. When the loop fails, ask the metainterp for more. """ Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Mar 6 14:35:15 2009 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, Const, ConstInt from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.executor import get_execute_function +from pypy.jit.metainterp.executor import execute from pypy.jit.backend.llgraph.runner import CPU, GuardFailed @@ -44,30 +44,6 @@ assert getattr(res, key) == value interpret(main, []) - def test_simple(self): - cpu = CPU(None) - box = cpu.execute_operation(rop.INT_SUB, [BoxInt(10), BoxInt(2)], - "int") - assert isinstance(box, BoxInt) - assert box.value == 8 - - def test_execute_operation(self): - cpu = CPU(None) - node = lltype.malloc(NODE) - node_value = cpu.fielddescrof(NODE, 'value') - nodeadr = lltype.cast_opaque_ptr(llmemory.GCREF, node) - box = cpu.execute_operation(rop.SETFIELD_GC, [BoxPtr(nodeadr), - ConstInt(node_value), - BoxInt(3)], - 'void') - assert box is None - assert node.value == 3 - - box = cpu.execute_operation(rop.GETFIELD_GC, [BoxPtr(nodeadr), - ConstInt(node_value)], - 'int') - assert box.value == 3 - def test_execute_operations_in_env(self): cpu = CPU(None) cpu.set_meta_interp(FakeMetaInterp(cpu)) @@ -85,10 +61,9 @@ ResOperation(rop.JUMP, [z, t], None), ] operations[-2].liveboxes = [t, z] - startmp = operations[0] - operations[-1].jump_target = startmp + operations[-1].jump_target = operations[0] cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', startmp, + res = cpu.execute_operations_in_new_frame('foo', operations, [BoxInt(0), BoxInt(10)]) assert res.value == 42 gf = cpu.metainterp.gf @@ -129,9 +104,8 @@ ResOperation(opnum, args, []), ResOperation(rop.VOID_RETURN, [], []), ] - startmp = operations[0] cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', startmp, args) + res = cpu.execute_operations_in_new_frame('foo', operations, args) assert res.value == 42 def test_cast_adr_to_int_and_back(self): @@ -304,8 +278,7 @@ def test_executor(self): cpu = CPU(None) - fn = get_execute_function(cpu, rop.INT_ADD) - assert fn(cpu, [BoxInt(100), ConstInt(42)]).value == 142 - fn = get_execute_function(cpu, rop.NEWSTR) - s = fn(cpu, [BoxInt(8)]) + x = execute(cpu, rop.INT_ADD, [BoxInt(100), ConstInt(42)]) + assert x.value == 142 + s = execute(cpu, rop.NEWSTR, [BoxInt(8)]) assert len(s.getptr(lltype.Ptr(rstr.STR)).chars) == 8 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Fri Mar 6 14:35:15 2009 @@ -72,7 +72,6 @@ MERGE_POINT = 1 CATCH = 2 JUMP = 3 - RETURN = 4 _SPECIAL_LAST = 9 _GUARD_FIRST = 10 # ----- start of guard operations ----- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Fri Mar 6 14:35:15 2009 @@ -485,10 +485,9 @@ loop, boxes = warmrunnerdesc.metainterp.compile_and_run(*args) if loop: cpu = warmrunnerdesc.metainterp.cpu - mp = loop.operations[0] + operations = loop.operations box = cpu.execute_operations_in_new_frame('run_this_loop', - mp, boxes, - "int") + operations, boxes) raise warmrunnerdesc.DoneWithThisFrame(box) def must_compile_from_failure(self, guard_failure): From afa at codespeak.net Fri Mar 6 14:42:12 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Mar 2009 14:42:12 +0100 (CET) Subject: [pypy-svn] r62644 - pypy/trunk/pypy/module/_locale/test Message-ID: <20090306134212.18CBE168471@codespeak.net> Author: afa Date: Fri Mar 6 14:42:11 2009 New Revision: 62644 Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py Log: Probably fix the _locale test failure. (my machine does not have the pl_PL locale, will watch the buildbot) Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Fri Mar 6 14:42:11 2009 @@ -9,7 +9,7 @@ if sys.platform != 'win32': cls.w_language_en = cls.space.wrap("en_US") cls.w_language_utf8 = cls.space.wrap("en_US.UTF-8") - cls.w_language_pl = cls.space.wrap("pl_PL") + cls.w_language_pl = cls.space.wrap("pl_PL.UTF-8") else: cls.w_language_en = cls.space.wrap("English_US") cls.w_language_utf8 = cls.space.wrap("English_US.65001") From tverwaes at codespeak.net Fri Mar 6 15:15:21 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 15:15:21 +0100 (CET) Subject: [pypy-svn] r62645 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090306141521.BF3691684E2@codespeak.net> Author: tverwaes Date: Fri Mar 6 15:15:18 2009 New Revision: 62645 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_meta.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixing tests Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Mar 6 15:15:18 2009 @@ -112,7 +112,6 @@ def __init__(self, gameboy): VideoDriver.__init__(self) - self.create_pixels() if show_metadata: self.create_meta_windows(gameboy) self.create_screen() Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py Fri Mar 6 15:15:18 2009 @@ -136,12 +136,12 @@ def line_intersection_test(sprite): sprite.video.line_y = 0 - assert not sprite.intersects_current_line() + assert not sprite.intersects_current_line(sprite.video.line_y) for i in range(sprite.get_height()): sprite.video.line_y = i+1 - assert sprite.intersects_current_line(), i + assert sprite.intersects_current_line(sprite.video.line_y), i sprite.video.line_y = sprite.get_height()+1 - assert not sprite.intersects_current_line() + assert not sprite.intersects_current_line(sprite.video.line_y) # test sprite in video --------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Mar 6 15:15:18 2009 @@ -546,6 +546,7 @@ def __init__(self): self.width = GAMEBOY_SCREEN_WIDTH self.height = GAMEBOY_SCREEN_HEIGHT + self.create_pixels() def clear_gb_pixels(self): for y in range(GAMEBOY_SCREEN_HEIGHT): @@ -558,6 +559,10 @@ def update_gb_display(self): self.update_display() + def update_display(self): + # Overwrite this method to actually put the pixels on a screen. + pass + def create_pixels(self): self.pixels = [[0] * self.width for i in range(self.height)] Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 15:15:18 2009 @@ -70,6 +70,23 @@ line = self.screen[y] self.gameboy.video.draw_window(self.get_window(), y, line) +class MapViewer(VideoMetaWindow): + def __init__(self, gameboy): + self.map_x = 32 + self.map_y = 32 + VideoMetaWindow.__init__(self, gameboy, + SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE, + GAMEBOY_SCREEN_HEIGHT) + + def get_window(self): + raise Exception("Not Implemented") + + def update_screen(self): + for y in range(self.height): + line = self.screen[y] + self.gameboy.video.draw_window(self.get_window(), y, line) + + class WindowPreview(PreviewWindow): def get_window(self): # XXX Broken for now Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Mar 6 15:15:18 2009 @@ -130,9 +130,9 @@ value += self.rest_attributes_and_flags return value - # Unused. - #def get_width(self): - # return SPRITE_SIZE + # For testing purposes only + def get_width(self): + return SPRITE_SIZE def get_height(self): if self.big_size: From tverwaes at codespeak.net Fri Mar 6 16:21:11 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 16:21:11 +0100 (CET) Subject: [pypy-svn] r62646 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306152111.2E47B168467@codespeak.net> Author: tverwaes Date: Fri Mar 6 16:21:09 2009 New Revision: 62646 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video_meta.py Log: adding map support. Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Fri Mar 6 16:21:09 2009 @@ -134,7 +134,7 @@ TILE_MAP_ADDR = 0x9800 TILE_MAP_SIZE = 32 # 32 Groups -TILE_GROUP_SIZE = 32 # of 32 addresses +TILE_GROUP_SIZE = 32 # of 32 tile-pointers VRAM_MAP_A = 0x1800 # 1KB BG Tile Map 0 (9000..9BFF) VRAM_MAP_B = 0x1C00 # 1KB BG Tile Map 1 (9C00..9FFF) Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Mar 6 16:21:09 2009 @@ -6,7 +6,8 @@ from pypy.lang.gameboy.sound import SoundDriver from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy.video_meta import TileDataWindow, SpriteWindow,\ - WindowPreview, BackgroundPreview + WindowPreview, BackgroundPreview,\ + MapAViewer, MapBViewer from pypy.lang.gameboy import constants import time @@ -124,7 +125,9 @@ self.meta_windows = [TileDataWindow(gameboy), SpriteWindow(gameboy), WindowPreview(gameboy), - BackgroundPreview(gameboy)] + BackgroundPreview(gameboy), + MapAViewer(gameboy), + MapBViewer(gameboy)] for window in self.meta_windows: window.set_origin(self.width, 0) Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 16:21:09 2009 @@ -75,17 +75,34 @@ self.map_x = 32 self.map_y = 32 VideoMetaWindow.__init__(self, gameboy, - SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE, - GAMEBOY_SCREEN_HEIGHT) + SPRITE_SIZE * self.map_x, + SPRITE_SIZE * self.map_y) - def get_window(self): - raise Exception("Not Implemented") + def get_map(self): + raise Exception("Subclass responsibility") + + def get_tile_data(self): + return self.gameboy.video.get_selected_tile_data_space() def update_screen(self): + map = self.get_map() + tile_data = self.get_tile_data() for y in range(self.height): line = self.screen[y] - self.gameboy.video.draw_window(self.get_window(), y, line) - + group = map[y >> 3] + for x in range(self.map_x): + tile_idx = group[x] + tile_idx ^= self.gameboy.video.tile_index_flip() + tile = tile_data[tile_idx] + tile.draw(line, x * SPRITE_SIZE, y) + +class MapAViewer(MapViewer): + def get_map(self): + return self.gameboy.video.tile_map_0 + +class MapBViewer(MapViewer): + def get_map(self): + return self.gameboy.video.tile_map_1 class WindowPreview(PreviewWindow): def get_window(self): From fijal at codespeak.net Fri Mar 6 16:27:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 16:27:06 +0100 (CET) Subject: [pypy-svn] r62647 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090306152706.7D89E168476@codespeak.net> Author: fijal Date: Fri Mar 6 16:27:03 2009 New Revision: 62647 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: a test that I have lying around in my WC for quite a while, will be needed at some point Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Mar 6 16:27:03 2009 @@ -128,3 +128,26 @@ assert res.value == 42 assert meta_interp.recordedvalues == [0, 1, 3, 2, 0] +def test_bool_optimizations(): + py.test.skip("Not yet") + meta_interp = FakeMetaInterp() + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.set_meta_interp(meta_interp) + arg0 = BoxInt(3) + arg1 = BoxInt(4) + res = BoxInt(0) + ops = [ + ResOperation(rop.MERGE_POINT, [arg0, arg1], None), + ResOperation(rop.INT_GT, [arg0, arg1], res), + ResOperation(rop.GUARD_TRUE, [res], None), + # we should never get here + ] + ops[2].liveboxes = [res] + + cpu.compile_operations(ops) + res = cpu.execute_operations_in_new_frame('foo', ops[0], + [arg0, arg1], 'int') + + assert len(cpu.assembler._regalloc.computed_ops) == 2 + assert meta_interp.gf + # er, what to check here, assembler??? From fijal at codespeak.net Fri Mar 6 16:28:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 16:28:06 +0100 (CET) Subject: [pypy-svn] r62648 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306152806.2923116846D@codespeak.net> Author: fijal Date: Fri Mar 6 16:28:05 2009 New Revision: 62648 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: IN-PROGRESS. Refactor x86 backend to adapt to new interface. Add xxx in places that should never be called Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 6 16:28:05 2009 @@ -499,47 +499,19 @@ self.mc2.JMP(eax) return recovery_code_addr - def _new_gen_call(): - def gen_call(self, op, arglocs, resloc): - extra_on_stack = 0 - for i in range(len(op.args) - 1, 0, -1): + def genop_call(self, op, arglocs, resloc): + extra_on_stack = 0 + for i in range(len(op.args) - 1, 0, -1): + # op.args[1] is a calldesc + if i != 1: v = op.args[i] - loc = arglocs[i] + loc = arglocs[len(arglocs) - 1 - extra_on_stack] if not isinstance(loc, MODRM): self.mc.PUSH(loc) else: # we need to add a bit, ble self.mc.PUSH(stack_pos(loc.position + extra_on_stack)) extra_on_stack += 1 - if isinstance(op.args[0], Const): - x = rel32(self.cpu.get_box_value_as_int(op.args[0])) - else: - # XXX add extra_on_stack? - x = arglocs[0] - self.mc.CALL(x) - self.mc.ADD(esp, imm(WORD * extra_on_stack)) - return gen_call - - genop_call__4 = _new_gen_call() - gen_call = _new_gen_call() - genop_call_ptr = gen_call - xxx_genop_getitem = _new_gen_call() - xxx_genop_len = _new_gen_call() - xxx_genop_pop = _new_gen_call() - xxx_genop_newlist = _new_gen_call() - xxx_genop_listnonzero = _new_gen_call() - - def genop_call_void(self, op, arglocs): - extra_on_stack = 0 - for i in range(len(op.args) - 1, 0, -1): - v = op.args[i] - loc = arglocs[i] - if not isinstance(loc, MODRM): - self.mc.PUSH(loc) - else: - # we need to add a bit, ble - self.mc.PUSH(stack_pos(loc.position + extra_on_stack)) - extra_on_stack += 1 if isinstance(op.args[0], Const): x = rel32(self.cpu.get_box_value_as_int(op.args[0])) else: @@ -548,18 +520,14 @@ self.mc.CALL(x) self.mc.ADD(esp, imm(WORD * extra_on_stack)) - xxx_genop_append = genop_call_void - xxx_genop_setitem = genop_call_void - xxx_genop_insert = genop_call_void - - def genop_call__1(self, op, arglocs, resloc): - self.gen_call(op, arglocs, resloc) - self.mc.MOVZX(eax, al) - - def genop_call__2(self, op, arglocs, resloc): - # XXX test it test it test it - self.gen_call(op, arglocs, resloc) - self.mc.MOVZX(eax, eax) + #def genop_call__1(self, op, arglocs, resloc): + # self.gen_call(op, arglocs, resloc) + # self.mc.MOVZX(eax, al) + + #def genop_call__2(self, op, arglocs, resloc): + # # XXX test it test it test it + # self.gen_call(op, arglocs, resloc) + # self.mc.MOVZX(eax, eax) genop_discard_list = [None] * rop._LAST genop_list = [None] * rop._LAST @@ -579,8 +547,6 @@ else: genop_list[num] = value -genop_discard_list[rop.CALL_VOID] = Assembler386.genop_call_void - def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): if isinstance(reg_or_imm1, IMM32): if isinstance(reg_or_imm2, IMM32): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 16:28:05 2009 @@ -718,14 +718,11 @@ self.free_regs = REGS[:] return ops + [PerformDiscard(op, arglocs)] - def consider_call_ptr(self, op, ignored): - return self._call(op, [self.loc(arg) for arg in op.args]) + def consider_call(self, op, ignored): + args = [op.args[0]] + op.args[2:] + return self._call(op, [self.loc(arg) for arg in args]) - consider_call_void = consider_call_ptr - consider_call__1 = consider_call_ptr - consider_call__2 = consider_call_ptr - consider_call__4 = consider_call_ptr - consider_call__8 = consider_call_ptr + consider_call_pure = consider_call def consider_new(self, op, ignored): return self._call(op, [self.loc(arg) for arg in op.args]) @@ -764,15 +761,6 @@ [eax, imm(ofs + ofs_length), imm(WORD), loc])]) return res - - def _unpack_arraydescr(self, arraydescr): - if arraydescr < 0: - arraydescr = ~arraydescr - assert arraydescr - size_of_field = arraydescr >> 16 - ofs = arraydescr & 0xffff - return size_of_field, ofs - def consider_new_array(self, op, ignored): size_of_field, basesize = self._unpack_arraydescr(op.args[0].getint()) return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[1], @@ -785,12 +773,14 @@ assert reg return [Perform(op, [argloc], reg)] + def _unpack_arraydescr(self, arraydescr): + from pypy.jit.backend.x86.runner import CPU386 + return CPU386.unpack_arraydescr(arraydescr) + def _unpack_fielddescr(self, fielddescr): - if fielddescr < 0: - fielddescr = ~fielddescr - ofs_loc = imm(fielddescr & 0xffff) - size_loc = imm(fielddescr >> 16) - return ofs_loc, size_loc + from pypy.jit.backend.x86.runner import CPU386 + ofs, size, _ = CPU386.unpack_fielddescr(arraydescr) + return imm(ofs), imm(size) def consider_setfield_gc(self, op, ignored): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 16:28:05 2009 @@ -1,7 +1,7 @@ import sys import ctypes import py -from pypy.rpython.lltypesystem import lltype, llmemory, ll2ctypes, rffi +from pypy.rpython.lltypesystem import lltype, llmemory, ll2ctypes, rffi, rstr from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize @@ -11,10 +11,13 @@ from pypy.jit.metainterp import history from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) -from pypy.jit.backend.x86.assembler import Assembler386 +from pypy.jit.backend.x86.assembler import Assembler386, WORD from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.x86.executor import execute +from pypy.jit.backend.x86.support import gc_malloc_fnaddr + +GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) class CPU386(object): debug = True @@ -139,6 +142,7 @@ return self.cast_int_to_gcref(self.assembler._exception_data[1]) def execute_operation(self, opnum, valueboxes, result_type): + xxx if execute[opnum] is not None: return execute[opnum](valueboxes) @@ -171,6 +175,7 @@ def get_compiled_single_operation(self, opnum, result_type, key, valueboxes): + xxx real_key = '%d,%s' % (opnum, result_type) + ','.join(key) try: return self._compiled_ops[real_key] @@ -355,16 +360,161 @@ def sizeof(self, S): return symbolic.get_size(S) - numof = sizeof - addresssuffix = str(symbolic.get_size(llmemory.Address)) +# numof = sizeof +# addresssuffix = str(symbolic.get_size(llmemory.Address)) - def itemoffsetof(self, A): - basesize, itemsize, ofs_length = symbolic.get_array_token(A) - return basesize +# def itemoffsetof(self, A): +# basesize, itemsize, ofs_length = symbolic.get_array_token(A) +# return basesize + +# def arraylengthoffset(self, A): +# basesize, itemsize, ofs_length = symbolic.get_array_token(A) +# return ofs_length + + # ------------------- backend-specific ops ------------------------ + + def do_arraylen_gc(self, args): + gcref = args[0].getptr(llmemory.GCREF) + return BoxInt(rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[0]) + + def do_getarrayitem_gc(self, args): + arraydescr = args[1].getint() + field = args[2].getint() + gcref = args[0].getptr(llmemory.GCREF) + if arraydescr < 0: + ptr = True + else: + ptr = False + shift, ofs = self.unpack_arraydescr(arraydescr) + size = 1 << shift + if size == 1: + return BoxInt(ord(rffi.cast(rffi.CArrayPtr(lltype.Char), gcref) + [ofs + field])) + elif size == WORD: + val = (rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) + [ofs/WORD + field]) + if not ptr: + return BoxInt(val) + else: + return BoxPtr(self.cast_int_to_gcref(val)) + else: + raise NotImplementedError("size = %d" % size) - def arraylengthoffset(self, A): - basesize, itemsize, ofs_length = symbolic.get_array_token(A) - return ofs_length + def do_setarrayitem_gc(self, args): + arraydescr = args[1].getint() + field = args[2].getint() + gcref = args[0].getptr(llmemory.GCREF) + if arraydescr < 0: + ptr = True + else: + ptr = False + shift, ofs = self.unpack_arraydescr(arraydescr) + size = 1 << shift + if size == 1: + v = args[3].getint() + rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[ofs + field] = chr(v) + elif size == WORD: + a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) + if not ptr: + a[ofs/WORD + field] = args[3].getint() + else: + p = args[3].getptr(llmemory.GCREF) + a[ofs/WORD + field] = self.cast_gcref_to_int(p) + else: + raise NotImplementedError("size = %d" % size) + + def do_strlen(self, args): + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + gcref = args[0].getptr(llmemory.GCREF) + v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] + return BoxInt(v) + + def do_strgetitem(self, args): + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + gcref = args[0].getptr(llmemory.GCREF) + i = args[1].getint() + v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] + return BoxInt(ord(v)) + + @specialize.argtype(1) + def _base_do_getfield(self, gcref, fielddescr): + ofs, size, ptr = self.unpack_fielddescr(fielddescr) + if size == 1: + v = ord(rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[ofs]) + elif size == 2: + v = rffi.cast(rffi.CArrayPtr(rffi.USHORT), gcref)[ofs/2] + elif size == WORD: + v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs/WORD] + if ptr: + return BoxPtr(self.cast_int_to_gcref(v)) + else: + raise NotImplementedError("size = %d" % size) + return BoxInt(v) + + def do_getfield_gc(self, args): + fielddescr = args[1].getint() + gcref = args[0].getptr(llmemory.GCREF) + return self._base_do_getfield(gcref, fielddescr) + + def do_getfield_raw(self, args): + fielddescr = args[1].getint() + return self._base_do_getfield(args[0].getint(), fielddescr) + + @specialize.argtype(2) + def _base_do_setfield(self, fielddescr, gcref, vbox): + ofs, size, ptr = self.unpack_fielddescr(fielddescr) + if size == 1: + v = vbox.getint() + rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[ofs] = chr(v) + elif size == 2: + v = vbox.getint() + rffi.cast(rffi.CArrayPtr(rffi.USHORT), gcref)[ofs/2] = v + elif size == WORD: + a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) + if ptr: + ptr = vbox.getptr(llmemory.GCREF) + a[ofs/WORD] = self.cast_gcref_to_int(ptr) + else: + a[ofs/WORD] = vbox.getint() + else: + raise NotImplementedError("size = %d" % size) + + def do_setfield_gc(self, args): + fielddescr = args[1].getint() + gcref = args[0].getptr(llmemory.GCREF) + self._base_do_setfield(fielddescr, gcref, args[2]) + + def do_setfield_raw(self, args): + fielddescr = args[1].getint() + self._base_do_setfield(fielddescr, args[0].getint(), args[2]) + + def do_new(self, args): + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(args[0].getint()) + return BoxPtr(self.cast_int_to_gcref(res)) + + def do_new_with_vtable(self, args): + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(args[0].getint()) + rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[1].getint() + return BoxPtr(self.cast_int_to_gcref(res)) + + def do_new_array(self, args): + size_of_field, ofs = self.unpack_arraydescr(args[0].getint()) + num_elem = args[1].getint() + size = ofs + (1 << size_of_field) * num_elem + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) + rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = num_elem + return BoxPtr(self.cast_int_to_gcref(res)) + + def do_newstr(self, args): + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + assert itemsize == 1 + num_elem = args[0].getint() + size = basesize + num_elem + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) + rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem + return BoxPtr(self.cast_int_to_gcref(res)) + + # ------------------- helpers and descriptions -------------------- @staticmethod def cast_adr_to_int(x): @@ -391,6 +541,20 @@ return res @staticmethod + def unpack_arraydescr(arraydescr): + # XXX move it to some saner place, regalloc is using it + if arraydescr < 0: + arraydescr = ~arraydescr + assert arraydescr + size_of_field = arraydescr >> 16 + ofs = arraydescr & 0xffff + return size_of_field, ofs + + @staticmethod + def calldescrof(argtypes, resulttype): + return 3 + + @staticmethod def fielddescrof(S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname) val = (size << 16) + ofs @@ -400,6 +564,16 @@ return val @staticmethod + def unpack_fielddescr(fielddescr): + ptr = False + if fielddescr < 0: + fielddescr = ~fielddescr + ptr = True + ofs = fielddescr & 0xffff + size = fielddescr >> 16 + return ofs, size, ptr + + @staticmethod def typefor(fielddesc): if fielddesc < 0: return "ptr" Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Fri Mar 6 16:28:05 2009 @@ -10,9 +10,6 @@ GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) -def gc_malloc(size): - return llop.call_boehm_gc_alloc(llmemory.Address, size) - def gc_malloc_fnaddr(): """Returns the address of the Boehm 'malloc' function.""" if we_are_translated(): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 16:28:05 2009 @@ -1,5 +1,5 @@ import py -from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rstr, rclass from pypy.jit.metainterp.history import ResOperation from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, Box) @@ -370,3 +370,138 @@ res = self.execute_operation(rop.UINT_GT, [arg0, arg1], 'int') assert res.value == 1 + + def test_do_operations(self): + cpu = self.cpu + # + A = lltype.GcArray(lltype.Char) + descrbox_A = ConstInt(cpu.arraydescrof(A)) + a = lltype.malloc(A, 5) + x = cpu.do_arraylen_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A]) + assert x.value == 5 + # + a[2] = 'Y' + x = cpu.do_getarrayitem_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A, + BoxInt(2)]) + assert x.value == ord('Y') + # + B = lltype.GcArray(lltype.Ptr(A)) + descrbox_B = ConstInt(cpu.arraydescrof(B)) + b = lltype.malloc(B, 4) + b[3] = a + x = cpu.do_getarrayitem_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, + BoxInt(3)]) + assert isinstance(x, BoxPtr) + assert x.getptr(lltype.Ptr(A)) == a + # + s = rstr.mallocstr(6) + x = cpu.do_strlen( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))]) + assert x.value == 6 + # + s.chars[3] = 'X' + x = cpu.do_strgetitem( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), BoxInt(3)]) + assert x.value == ord('X') + # + S = lltype.GcStruct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) + descrfld_x = cpu.fielddescrof(S, 'x') + s = lltype.malloc(S) + s.x = 'Z' + x = cpu.do_getfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_x)]) + assert x.value == ord('Z') + # + cpu.do_setfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_x), + BoxInt(ord('4'))]) + assert s.x == '4' + # + descrfld_y = cpu.fielddescrof(S, 'y') + s.y = a + x = cpu.do_getfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_y)]) + assert isinstance(x, BoxPtr) + assert x.getptr(lltype.Ptr(A)) == a + # + s.y = lltype.nullptr(A) + cpu.do_setfield_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), + BoxInt(descrfld_y), + x]) + assert s.y == a + # + RS = lltype.Struct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) + descrfld_rx = cpu.fielddescrof(RS, 'x') + rs = lltype.malloc(RS, immortal=True) + rs.x = '?' + x = cpu.do_getfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_rx)]) + assert x.value == ord('?') + # + cpu.do_setfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_rx), + BoxInt(ord('!'))]) + assert rs.x == '!' + # + descrfld_ry = cpu.fielddescrof(RS, 'y') + rs.y = a + x = cpu.do_getfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_ry)]) + assert isinstance(x, BoxPtr) + assert x.getptr(lltype.Ptr(A)) == a + # + rs.y = lltype.nullptr(A) + cpu.do_setfield_raw( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), + BoxInt(descrfld_ry), + x]) + assert rs.y == a + # + descrsize = cpu.sizeof(S) + x = cpu.do_new( + [BoxInt(descrsize)]) + assert isinstance(x, BoxPtr) + x.getptr(lltype.Ptr(S)) + # + descrsize2 = cpu.sizeof(rclass.OBJECT) + vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) + x = cpu.do_new_with_vtable( + [BoxInt(descrsize2), + BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))]) + assert isinstance(x, BoxPtr) + # well.... + assert (rffi.cast(rffi.CArrayPtr(lltype.Signed), + x.getptr(llmemory.GCREF))[0]) + #assert x.getptr(rclass.OBJECTPTR).typeptr == vtable2 + # + arraydescr = cpu.arraydescrof(A) + x = cpu.do_new_array( + [BoxInt(arraydescr), BoxInt(7)]) + assert isinstance(x, BoxPtr) + assert len(x.getptr(lltype.Ptr(A))) == 7 + # + cpu.do_setarrayitem_gc( + [x, descrbox_A, BoxInt(5), BoxInt(ord('*'))]) + assert x.getptr(lltype.Ptr(A))[5] == '*' + # + cpu.do_setarrayitem_gc( + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, + BoxInt(1), x]) + assert b[1] == x.getptr(lltype.Ptr(A)) + # + x = cpu.do_newstr([BoxInt(5)]) + assert isinstance(x, BoxPtr) + assert len(x.getptr(lltype.Ptr(rstr.STR)).chars) == 5 + # + cpu.do_strsetitem([x, BoxInt(4), BoxInt(ord('/'))]) + assert x.getptr(lltype.Ptr(rstr.STR)).chars[4] == '/' From arigo at codespeak.net Fri Mar 6 16:34:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 16:34:44 +0100 (CET) Subject: [pypy-svn] r62649 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp Message-ID: <20090306153444.D9A14168476@codespeak.net> Author: arigo Date: Fri Mar 6 16:34:44 2009 New Revision: 62649 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Finish the refactoring of the llgraph backend. Now the do_call() operation also reports exceptions via cpu.get_exception() instead of just raising it. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Mar 6 16:34:44 2009 @@ -12,10 +12,10 @@ from pypy.rpython.lltypesystem import lloperation from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport -from pypy.rpython.llinterp import LLInterpreter, LLFrame, LLException +from pypy.rpython.llinterp import LLException from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.jit.metainterp import heaptracker, resoperation +from pypy.jit.metainterp import heaptracker, resoperation, executor from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llgraph import symbolic @@ -125,7 +125,6 @@ # ____________________________________________________________ - class LoopOrBridge(object): def __init__(self): self.operations = [] @@ -327,14 +326,9 @@ # ------------------------------ class Frame(object): + OPHANDLERS = [None] * (rop._LAST+1) def __init__(self, memocast): - llinterp = LLInterpreter(_rtyper) # '_rtyper' set by CPU - llinterp.traceback_frames = [] - self.llframe = ExtendedLLFrame(None, None, llinterp) - self.llframe.memocast = memocast - self.llframe.last_exception = None - self.llframe.last_exception_handled = True self.verbose = False self.memocast = memocast @@ -355,6 +349,9 @@ """Execute all operations in a loop, possibly following to other loops as well. """ + global _last_exception, _last_exception_handled + _last_exception = None + _last_exception_handled = True verbose = True while True: self.opindex += 1 @@ -369,9 +366,8 @@ args) _stats.exec_jumps += 1 continue - opname = resoperation.opname[op.opnum].lower() try: - result = self.execute_operation(opname, args, verbose) + result = self.execute_operation(op.opnum, args, verbose) #verbose = self.verbose assert (result is None) == (op.result is None) if op.result is not None: @@ -385,7 +381,7 @@ % (RESTYPE,)) self.env[op.result] = x except GuardFailed: - assert self.llframe.last_exception_handled + assert _last_exception_handled if hasattr(op, 'jump_target'): # the guard already failed once, go to the # already-generated code @@ -409,21 +405,21 @@ self.failed_guard_op = op return op.failnum - def execute_operation(self, opname, values, verbose): + def execute_operation(self, opnum, values, verbose): """Execute a single operation. """ - ophandler = self.llframe.getoperationhandler(opname) - assert not getattr(ophandler, 'specialform', False) - if getattr(ophandler, 'need_result_type', False): - assert result_type is not None - values = list(values) - values.insert(0, result_type) + ophandler = self.OPHANDLERS[opnum] + if ophandler is None: + self._define_impl(opnum) + ophandler = self.OPHANDLERS[opnum] + assert ophandler is not None, "missing impl for op %d" % opnum + opname = resoperation.opname[opnum].lower() exec_counters = _stats.exec_counters exec_counters[opname] = exec_counters.get(opname, 0) + 1 for i in range(len(values)): if isinstance(values[i], ComputedIntSymbolic): values[i] = values[i].compute_fn() - res = ophandler(*values) + res = ophandler(self, *values) if verbose: argtypes, restype = TYPES[opname] if res is None: @@ -450,6 +446,189 @@ count_jumps = _stats.exec_jumps log.trace('ran %d operations, %d jumps' % (count, count_jumps)) + # ---------- + + def _define_impl(self, opnum): + opname = resoperation.opname[opnum] + try: + op = getattr(Frame, 'op_' + opname.lower()) # op_guard_true etc. + except AttributeError: + name = 'do_' + opname.lower() + try: + impl = globals()[name] # do_arraylen_gc etc. + def op(self, *args): + return impl(*args) + # + except KeyError: + from pypy.jit.backend.llgraph import llimpl + impl = getattr(executor, name) # do_int_add etc. + def _op_default_implementation(self, *args): + # for all operations implemented in execute.py + boxedargs = [] + for x in args: + if type(x) is int: + boxedargs.append(BoxInt(x)) + else: + boxedargs.append(BoxPtr(x)) + # xxx this passes the 'llimpl' module as the CPU argument + resbox = impl(llimpl, boxedargs) + return resbox.value + op = _op_default_implementation + # + Frame.OPHANDLERS[opnum] = op + + def op_guard_true(self, value): + if not value: + raise GuardFailed + + def op_guard_false(self, value): + if value: + raise GuardFailed + + op_guard_nonzero = op_guard_true + op_guard_iszero = op_guard_false + + def op_guard_nonnull(self, ptr): + if lltype.typeOf(ptr) != llmemory.GCREF: + ptr = cast_int_to_adr(self.memocast, ptr) + if not ptr: + raise GuardFailed + + def op_guard_isnull(self, ptr): + if lltype.typeOf(ptr) != llmemory.GCREF: + ptr = cast_int_to_adr(self.memocast, ptr) + if ptr: + raise GuardFailed + + def op_guard_lt(self, value1, value2): + if value1 >= value2: + raise GuardFailed + + def op_guard_le(self, value1, value2): + if value1 > value2: + raise GuardFailed + + def op_guard_eq(self, value1, value2): + if value1 != value2: + raise GuardFailed + + def op_guard_ne(self, value1, value2): + if value1 == value2: + raise GuardFailed + + def op_guard_gt(self, value1, value2): + if value1 <= value2: + raise GuardFailed + + def op_guard_ge(self, value1, value2): + if value1 < value2: + raise GuardFailed + + op_guard_is = op_guard_eq + op_guard_isnot = op_guard_ne + + def op_guard_class(self, value, expected_class): + value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) + expected_class = llmemory.cast_adr_to_ptr( + cast_int_to_adr(self.memocast, expected_class), + rclass.CLASSTYPE) + if value.typeptr != expected_class: + raise GuardFailed + + def op_guard_value(self, value, expected_value): + if value != expected_value: + raise GuardFailed + + def op_guard_nonvirtualized(self, value, expected_class, + for_accessing_field): + self.op_guard_class(value, expected_class) + if heaptracker.cast_vable(value).vable_rti: + raise GuardFailed # some other code is already in control + + def op_guard_no_exception(self): + global _last_exception_handled + _last_exception_handled = True + if _last_exception: + raise GuardFailed + + def op_guard_exception(self, expected_exception): + global _last_exception_handled + _last_exception_handled = True + expected_exception = llmemory.cast_adr_to_ptr( + cast_int_to_adr(self.memocast, expected_exception), + rclass.CLASSTYPE) + assert expected_exception + if _last_exception: + got = _last_exception.args[0] + if not rclass.ll_issubclass(got, expected_exception): + raise GuardFailed + return _last_exception.args[1] + else: + raise GuardFailed + + # ---------- + # delegating to the builtins do_xxx() (done automatically for simple cases) + + def op_getarrayitem_gc(self, array, arraydescr, index): + if arraydescr & 1: + return do_getarrayitem_gc_ptr(array, index) + else: + return do_getarrayitem_gc_int(array, index, self.memocast) + + def op_getfield_gc(self, struct, fielddescr): + if fielddescr & 1: + return do_getfield_gc_ptr(struct, fielddescr) + else: + return do_getfield_gc_int(struct, fielddescr, self.memocast) + + def op_getfield_raw(self, struct, fielddescr): + if fielddescr & 1: + return do_getfield_raw_ptr(struct, fielddescr) + else: + return do_getfield_raw_int(struct, fielddescr, self.memocast) + + def op_new_with_vtable(self, size, vtable): + result = do_new(size) + value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) + value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) + return result + + def op_setarrayitem_gc(self, array, arraydescr, index, newvalue): + if arraydescr & 1: + do_setarrayitem_gc_ptr(array, index, newvalue) + else: + do_setarrayitem_gc_int(array, index, newvalue, self.memocast) + + def op_setfield_gc(self, struct, fielddescr, newvalue): + if fielddescr & 1: + do_setfield_gc_ptr(struct, fielddescr, newvalue) + else: + do_setfield_gc_int(struct, fielddescr, newvalue, self.memocast) + + def op_setfield_raw(self, struct, fielddescr, newvalue): + if fielddescr & 1: + do_setfield_raw_ptr(struct, fielddescr, newvalue) + else: + do_setfield_raw_int(struct, fielddescr, newvalue, self.memocast) + + def op_call(self, func, calldescr, *args): + global _last_exception, _last_exception_handled + _call_args[:] = args + try: + res = _do_call_common(func, self.memocast) + _last_exception = None + return res + except LLException, e: + _last_exception = e + _last_exception_handled = False + if calldescr == -1: + return None + elif calldescr & 1: + return lltype.nullptr(llmemory.GCREF) + else: + return 0 + +# ____________________________________________________________ def cast_to_int(x, memocast): TP = lltype.typeOf(x) @@ -511,11 +690,6 @@ if frame.verbose: log.trace('Leaving CPU frame -> #%d' % (result,)) frame.log_progress() - except ExecutionReturned, e: - frame.returned_value = e.args[0] - return -1 - except ExecutionRaised, e: - raise e.args[0] except Exception, e: log.ERROR('%s in CPU frame: %s' % (e.__class__.__name__, e)) import sys, pdb; pdb.post_mortem(sys.exc_info()[2]) @@ -546,23 +720,33 @@ frame = _from_opaque(frame) return frame.returned_value -def frame_exception(frame): - frame = _from_opaque(frame) - assert frame.llframe.last_exception_handled - last_exception = frame.llframe.last_exception - if last_exception: - return llmemory.cast_ptr_to_adr(last_exception.args[0]) +def get_exception(): + global _last_exception, _last_exception_handled + _last_exception_handled = True + if _last_exception: + return llmemory.cast_ptr_to_adr(_last_exception.args[0]) else: return llmemory.NULL -def frame_exc_value(frame): - frame = _from_opaque(frame) - last_exception = frame.llframe.last_exception - if last_exception: - return lltype.cast_opaque_ptr(llmemory.GCREF, last_exception.args[1]) +def get_exc_value(): + global _last_exception, _last_exception_handled + _last_exception_handled = True + if _last_exception: + return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1]) else: return lltype.nullptr(llmemory.GCREF.TO) +def set_overflow_error(): + global _last_exception, _last_exception_handled + llframe = _llinterp.frame_class(None, None, _llinterp) + try: + llframe.make_llexception(OverflowError()) + except LLException, e: + _last_exception = e + _last_exception_handled = False + else: + assert 0, "should have raised" + class MemoCast(object): def __init__(self): self.addresses = [llmemory.NULL] @@ -592,315 +776,10 @@ class GuardFailed(Exception): pass -class ExecutionReturned(Exception): - pass - -class ExecutionRaised(Exception): - pass - -class ExtendedLLFrame(LLFrame): - - def newsubframe(self, graph, args): - # the default implementation would also create an ExtendedLLFrame, - # but we don't want this to occur in our case - return LLFrame(graph, args, self.llinterpreter) - - # ---------- signed/unsigned support ---------- - - # for these operations, we expect to be called with regular ints - # and to return regular ints - for _opname in ['uint_add', 'uint_sub', 'uint_mul', - 'uint_lt', 'uint_le', 'uint_eq', - 'uint_ne', 'uint_gt', 'uint_ge', - ]: - exec py.code.Source(""" - def op_%s(self, x, y): - x = r_uint(x) - y = r_uint(y) - ophandler = lloperation.LL_OPERATIONS[%r].fold - z = ophandler(x, y) - return intmask(z) - """ % (_opname, _opname)).compile() - - # ---------------------------------------- - - def op_return(self, value=None): - if self.last_exception is None: - raise ExecutionReturned(value) - else: - raise ExecutionRaised(self.last_exception) - - def op_guard_pause(self): - raise GuardFailed - - def op_guard_builtin(self, b): - pass - - def op_guard_true(self, value): - if not value: - raise GuardFailed - - def op_guard_false(self, value): - if value: - raise GuardFailed - - op_guard_nonzero = op_guard_true - op_guard_iszero = op_guard_false - - def op_guard_nonnull(self, ptr): - if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = cast_int_to_adr(self.memocast, ptr) - if not ptr: - raise GuardFailed - - def op_guard_isnull(self, ptr): - if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = cast_int_to_adr(self.memocast, ptr) - if ptr: - raise GuardFailed - - def op_guard_lt(self, value1, value2): - if value1 >= value2: - raise GuardFailed - - def op_guard_le(self, value1, value2): - if value1 > value2: - raise GuardFailed - - def op_guard_eq(self, value1, value2): - if value1 != value2: - raise GuardFailed - - def op_guard_ne(self, value1, value2): - if value1 == value2: - raise GuardFailed - - def op_guard_gt(self, value1, value2): - if value1 <= value2: - raise GuardFailed - - def op_guard_ge(self, value1, value2): - if value1 < value2: - raise GuardFailed - - op_guard_is = op_guard_eq - op_guard_isnot = op_guard_ne - - def op_guard_class(self, value, expected_class): - value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) - expected_class = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, expected_class), - rclass.CLASSTYPE) - if value.typeptr != expected_class: - raise GuardFailed - - def op_guard_value(self, value, expected_value): - if value != expected_value: - raise GuardFailed - - def op_guard_nonvirtualized(self, value, expected_class, - for_accessing_field): - self.op_guard_class(value, expected_class) - if heaptracker.cast_vable(value).vable_rti: - raise GuardFailed # some other code is already in control - - def op_guard_no_exception(self): - if self.last_exception: - self.last_exception_handled = True - raise GuardFailed - - def op_guard_exception(self, expected_exception): - expected_exception = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, expected_exception), - rclass.CLASSTYPE) - assert expected_exception - if self.last_exception: - got = self.last_exception.args[0] - self.last_exception_handled = True - if not rclass.ll_issubclass(got, expected_exception): - raise GuardFailed - return self.last_exception.args[1] - else: - raise GuardFailed - - def op_new(self, typesize): - TYPE = symbolic.Size2Type[typesize] - return lltype.malloc(TYPE) - - def op_new_with_vtable(self, typesize, vtable): - TYPE = symbolic.Size2Type[typesize] - ptr = lltype.malloc(TYPE) - ptr = lltype.cast_opaque_ptr(llmemory.GCREF, ptr) - self.op_setfield_gc(ptr, 2, vtable) - return ptr - - def op_new_array(self, arraydesc, count): - TYPE = symbolic.Size2Type[arraydesc/2] - return lltype.malloc(TYPE, count) - - def op_getfield_gc(self, ptr, fielddesc): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] - ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) - return getattr(ptr, fieldname) - - op_getfield_gc_pure = op_getfield_gc - - def op_getfield_raw(self, intval, fielddesc): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] - ptr = llmemory.cast_adr_to_ptr(cast_int_to_adr(self.memocast, intval), - lltype.Ptr(STRUCT)) - return getattr(ptr, fieldname) - - op_getfield_raw_pure = op_getfield_raw - - def _cast_newvalue(self, desc, TYPE, newvalue): - if desc % 2: - newvalue = lltype.cast_opaque_ptr(TYPE, newvalue) - else: - if isinstance(TYPE, lltype.Ptr): - assert TYPE.TO._gckind == 'raw' - newvalue = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, newvalue), - TYPE) - elif TYPE == llmemory.Address: - newvalue = cast_int_to_adr(self.memocast, newvalue) - return newvalue - - def op_setfield_gc(self, ptr, fielddesc, newvalue): - offset = fielddesc/2 - STRUCT, fieldname = symbolic.TokenToField[offset] - if lltype.typeOf(ptr) == llmemory.GCREF: - ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) - FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = self._cast_newvalue(fielddesc, FIELDTYPE, newvalue) - setattr(ptr, fieldname, newvalue) - - def op_setfield_raw(self, intval, fielddesc, newvalue): - ptr = llmemory.cast_adr_to_ptr(cast_int_to_adr(self.memocast, intval), - lltype.Ptr(STRUCT)) - self.op_setfield_gc(ptr, fielddesc, newvalue) - - def op_getarrayitem_gc(self, array, arraydesc, index): - array = array._obj.container - return array.getitem(index) - - op_getarrayitem_gc_pure = op_getarrayitem_gc - - def op_arraylen_gc(self, array, arraydesc): - array = array._obj.container - return array.getlength() - - def op_setarrayitem_gc(self, array, arraydesc, index, newvalue): - ITEMTYPE = symbolic.Size2Type[arraydesc/2].OF - array = array._obj.container - newvalue = self._cast_newvalue(arraydesc, ITEMTYPE, newvalue) - array.setitem(index, newvalue) - - def op_ooisnull(self, ptr): - if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = cast_int_to_adr(self.memocast, ptr) - return not ptr - - def op_oononnull(self, ptr): - if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = cast_int_to_adr(self.memocast, ptr) - return bool(ptr) - - def op_oois(self, ptr1, ptr2): - return ptr1 == ptr2 - - def op_ooisnot(self, ptr1, ptr2): - return ptr1 != ptr2 - - def op_bool_not(self, b): - assert isinstance(b, int) - return not b - - def op_strlen(self, str): - str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str) - return len(str.chars) - - def op_strgetitem(self, str, index): - str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str) - return ord(str.chars[index]) - - def op_strsetitem(self, str, index, newchar): - str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str) - str.chars[index] = chr(newchar) - - def op_newstr(self, length): - return rstr.mallocstr(length) - - def catch_exception(self, e): - assert self.last_exception_handled - self.last_exception = e - self.last_exception_handled = False - - def clear_exception(self): - assert self.last_exception_handled - self.last_exception = None - - def op_call(self, f, calldescr, *args): - ptr = cast_int_to_adr(self.memocast, f).ptr - FUNC = lltype.typeOf(ptr).TO - ARGS = FUNC.ARGS - args = list(args) - for i in range(len(ARGS)): - if ARGS[i] is lltype.Void: - args.insert(i, lltype.Void) - assert len(ARGS) == len(args) - fixedargs = [heaptracker.fixupobj(TYPE, x) - for TYPE, x in zip(ARGS, args)] - try: - x = self.perform_call(ptr, ARGS, fixedargs) - except LLException, e: - self.catch_exception(e) - x = FUNC.RESULT._defl() - else: - self.clear_exception() - return x - - op_call_pure = op_call - - def op_listop_return(self, ll_func, *args): - return self.do_call(ll_func, *args) - - def op_listop(self, ll_func, *args): - self.do_call(ll_func, *args) - - op_getitem = op_listop_return - op_setitem = op_listop - op_append = op_listop - op_insert = op_listop - op_pop = op_listop_return - op_len = op_listop_return - op_listnonzero = op_listop_return - - def op_newlist(self, ll_newlist, lgt, default_val=None): - if default_val is not None: - res = self.do_call(ll_newlist, lgt, default_val) - else: - res = self.do_call(ll_newlist, lgt) - return res - - for _opname in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', - 'int_neg_ovf', 'int_mod_ovf', - ]: - exec py.code.Source(''' - def op_%s(self, *args): - try: - z = LLFrame.op_%s(self, *args) - except LLException, e: - self.catch_exception(e) - z = 0 - else: - self.clear_exception() - return z - ''' % (_opname, _opname)).compile() - # ____________________________________________________________ -def do_arraylen_gc(array): + +def do_arraylen_gc(array, ignored): array = array._obj.container return array.getlength() @@ -1007,10 +886,10 @@ _call_args = [] def do_call_pushint(x): - _call_args.append(('int', x)) + _call_args.append(x) def do_call_pushptr(x): - _call_args.append(('ptr', x)) + _call_args.append(x) def _do_call_common(f, memocast): ptr = cast_int_to_adr(memocast, f).ptr @@ -1018,15 +897,15 @@ ARGS = FUNC.ARGS args = [] nextitem = iter(_call_args).next - for i in range(len(ARGS)): - if ARGS[i] is lltype.Void: + for TYPE in ARGS: + if TYPE is lltype.Void: x = None else: - typ, x = nextitem() - if typ == 'ptr': - x = cast_from_ptr(ARGS[i], x) + x = nextitem() + if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': + x = cast_from_ptr(TYPE, x) else: - x = cast_from_int(ARGS[i], x, memocast) + x = cast_from_int(TYPE, x, memocast) args.append(x) del _call_args[:] assert len(ARGS) == len(args) @@ -1122,8 +1001,10 @@ setannotation(frame_ptr_setvalue, annmodel.s_None) setannotation(frame_int_getresult, annmodel.SomeInteger()) setannotation(frame_ptr_getresult, annmodel.SomePtr(llmemory.GCREF)) -setannotation(frame_exception, annmodel.SomeAddress()) -setannotation(frame_exc_value, annmodel.SomePtr(llmemory.GCREF)) + +setannotation(get_exception, annmodel.SomeAddress()) +setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) +setannotation(set_overflow_error, annmodel.s_None) setannotation(new_memo_cast, s_MemoCast) setannotation(cast_adr_to_int, annmodel.SomeInteger()) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Fri Mar 6 16:34:44 2009 @@ -171,11 +171,14 @@ else: raise AssertionError('setvalue: valuebox = %s' % (valuebox,)) - def get_exception(self, frame): - return self.cast_adr_to_int(llimpl.frame_exception(frame)) + def get_exception(self): + return self.cast_adr_to_int(llimpl.get_exception()) - def get_exc_value(self, frame): - return llimpl.frame_exc_value(frame) + def get_exc_value(self): + return llimpl.get_exc_value() + + def set_overflow_error(self): + llimpl.set_overflow_error() @staticmethod def sizeof(S): @@ -246,7 +249,7 @@ def do_arraylen_gc(self, args): array = args[0].getptr_base() - return history.BoxInt(llimpl.do_arraylen_gc(array)) + return history.BoxInt(llimpl.do_arraylen_gc(array, 0)) def do_strlen(self, args): string = args[0].getptr_base() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Fri Mar 6 16:34:44 2009 @@ -3,7 +3,7 @@ import py from pypy.rlib.rarithmetic import ovfcheck, r_uint -from pypy.jit.metainterp.history import BoxInt, ConstInt, BoxPtr +from pypy.jit.metainterp.history import BoxInt, ConstInt from pypy.jit.metainterp.resoperation import rop @@ -130,19 +130,53 @@ # ---------- def do_int_add_ovf(cpu, args): - return BoxInt(ovfcheck(args[0].getint() + args[1].getint())) + x = args[0].getint() + y = args[1].getint() + try: + z = ovfcheck(x + y) + except OverflowError: + cpu.set_overflow_error() + z = 0 + return BoxInt(z) def do_int_sub_ovf(cpu, args): - return BoxInt(ovfcheck(args[0].getint() - args[1].getint())) + x = args[0].getint() + y = args[1].getint() + try: + z = ovfcheck(x - y) + except OverflowError: + cpu.set_overflow_error() + z = 0 + return BoxInt(z) def do_int_mul_ovf(cpu, args): - return BoxInt(ovfcheck(args[0].getint() * args[1].getint())) + x = args[0].getint() + y = args[1].getint() + try: + z = ovfcheck(x * y) + except OverflowError: + cpu.set_overflow_error() + z = 0 + return BoxInt(z) def do_int_neg_ovf(cpu, args): - return BoxInt(ovfcheck(-args[0].getint())) + x = args[0].getint() + try: + z = ovfcheck(-x) + except OverflowError: + cpu.set_overflow_error() + z = 0 + return BoxInt(z) def do_int_mod_ovf(cpu, args): - return BoxInt(ovfcheck(args[0].getint() % args[1].getint())) + x = args[0].getint() + y = args[1].getint() + try: + z = ovfcheck(x % y) + except OverflowError: + cpu.set_overflow_error() + z = 0 + return BoxInt(z) # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 16:34:44 2009 @@ -820,7 +820,7 @@ try: if guard_failure.guard_op.opnum in (rop.GUARD_EXCEPTION, rop.GUARD_NO_EXCEPTION): - self.raise_exception_upon_guard_failure(guard_failure) + self.raise_exception_upon_guard_failure() self.interpret() assert False, "should always raise" except GenerateMergePoint, gmp: @@ -954,9 +954,9 @@ self.rebuild_state_after_failure(guard_op.key, newboxes) return boxes_from_frame - def raise_exception_upon_guard_failure(self, guard_failure): - etype = self.cpu.get_exception(guard_failure.frame) - evalue = self.cpu.get_exc_value(guard_failure.frame) + def raise_exception_upon_guard_failure(self): + etype = self.cpu.get_exception() + evalue = self.cpu.get_exc_value() self.handle_exception(etype, evalue) def handle_exception(self, etype, evalue): From fijal at codespeak.net Fri Mar 6 16:35:41 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 16:35:41 +0100 (CET) Subject: [pypy-svn] r62650 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306153541.F30BF168483@codespeak.net> Author: fijal Date: Fri Mar 6 16:35:38 2009 New Revision: 62650 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: finish bits to be able to run test_runner Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 6 16:35:38 2009 @@ -7,7 +7,8 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, - arg_pos, lower_byte, stack_pos, Perform) + arg_pos, lower_byte, stack_pos, Perform, + RETURN) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.support import gc_malloc_fnaddr @@ -529,15 +530,15 @@ # self.gen_call(op, arglocs, resloc) # self.mc.MOVZX(eax, eax) -genop_discard_list = [None] * rop._LAST -genop_list = [None] * rop._LAST -genop_guard_list = [None] * rop._LAST +genop_discard_list = [None] * (RETURN + 1) +genop_list = [None] * (RETURN + 1) +genop_guard_list = [None] * (RETURN + 1) for name, value in Assembler386.__dict__.iteritems(): if name.startswith('genop_'): opname = name[len('genop_'):] - if opname == 'malloc_varsize': - num = MALLOC_VARSIZE + if opname == 'return': + num = RETURN else: num = getattr(rop, opname.upper()) if value.func_code.co_argcount == 3: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 16:35:38 2009 @@ -17,6 +17,8 @@ WORD = 4 FRAMESIZE = 1024 # XXX should not be a constant at all!! +RETURN = rop._LAST + 1 + class TempBox(Box): def __init__(self): pass @@ -779,7 +781,7 @@ def _unpack_fielddescr(self, fielddescr): from pypy.jit.backend.x86.runner import CPU386 - ofs, size, _ = CPU386.unpack_fielddescr(arraydescr) + ofs, size, _ = CPU386.unpack_fielddescr(fielddescr) return imm(ofs), imm(size) def consider_setfield_gc(self, op, ignored): @@ -949,12 +951,15 @@ self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] -oplist = [None] * rop._LAST +oplist = [None] * (RETURN + 1) for name, value in RegAlloc.__dict__.iteritems(): if name.startswith('consider_'): name = name[len('consider_'):] - num = getattr(rop, name.upper()) + if name == 'return': + num = RETURN + else: + num = getattr(rop, name.upper()) oplist[num] = value def arg_pos(i): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 16:35:38 2009 @@ -514,6 +514,13 @@ rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem return BoxPtr(self.cast_int_to_gcref(res)) + def do_strsetitem(self, args): + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + index = args[1].getint() + v = args[2].getint() + a = args[0].getptr(llmemory.GCREF) + rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) + # ------------------- helpers and descriptions -------------------- @staticmethod Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 16:35:38 2009 @@ -4,7 +4,7 @@ from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, Box) from pypy.jit.backend.x86.runner import CPU, GuardFailed -from pypy.jit.backend.x86.regalloc import WORD +from pypy.jit.backend.x86.regalloc import WORD, RETURN from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop import ctypes @@ -71,7 +71,7 @@ results = [result] operations = [mp, ResOperation(opnum, livevarlist, result), - ResOperation(rop.RETURN, results, None)] + ResOperation(RETURN, results, None)] if operations[1].is_guard(): operations[1].liveboxes = [] self.cpu.compile_operations(operations, verbose=False) From arigo at codespeak.net Fri Mar 6 16:45:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 16:45:35 +0100 (CET) Subject: [pypy-svn] r62651 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090306154535.A09D6168465@codespeak.net> Author: arigo Date: Fri Mar 6 16:45:34 2009 New Revision: 62651 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Rename this field. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 16:45:34 2009 @@ -530,7 +530,7 @@ instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) - instnode.vdesc = op.desc + instnode.vdesc = op.vdesc continue elif op.is_always_pure(): for arg in op.args: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 16:45:34 2009 @@ -519,7 +519,7 @@ op = self.generate_guard(pc, rop.GUARD_NONVIRTUALIZED, box, [clsbox, guard_field]) if op: - op.desc = vdesc + op.vdesc = vdesc @arguments("box") def opimpl_keepalive(self, box): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Fri Mar 6 16:45:34 2009 @@ -15,7 +15,7 @@ liveboxes = None # for 'guard_nonvirtualizable' - desc = None + vdesc = None def __init__(self, opnum, args, result): assert isinstance(opnum, int) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Fri Mar 6 16:45:34 2009 @@ -97,7 +97,7 @@ ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], None), ResOperation('jump', [sum2, fr], None), ] - ops[1].desc = xy_desc + ops[1].vdesc = xy_desc def test_A_find_nodes(): spec = PerfectSpecializer(Loop(A.ops)) @@ -148,7 +148,7 @@ ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), ResOperation('jump', [fr], None), ] - ops[1].desc = xy_desc + ops[1].vdesc = xy_desc def test_B_intersect_input_and_output(): spec = PerfectSpecializer(Loop(B.ops)) @@ -185,7 +185,7 @@ # ResOperation('jump', [fr], None), ] - ops[1].desc = xy_desc + ops[1].vdesc = xy_desc def test_C_intersect_input_and_output(): spec = PerfectSpecializer(Loop(C.ops)) @@ -224,7 +224,7 @@ ResOperation('setitem', [None, l, ConstInt(0), v2], None), ResOperation('jump', [fr], None), ] - ops[1].desc = xy_desc + ops[1].vdesc = xy_desc def test_D_intersect_input_and_output(): py.test.skip("XXX") From cfbolz at codespeak.net Fri Mar 6 17:16:00 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 6 Mar 2009 17:16:00 +0100 (CET) Subject: [pypy-svn] r62653 - pypy/branch/unicodedata-compression Message-ID: <20090306161600.6B0E4168478@codespeak.net> Author: cfbolz Date: Fri Mar 6 17:15:59 2009 New Revision: 62653 Removed: pypy/branch/unicodedata-compression/ Log: kill merged branch From tverwaes at codespeak.net Fri Mar 6 17:20:34 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 17:20:34 +0100 (CET) Subject: [pypy-svn] r62654 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306162034.BA05B16847F@codespeak.net> Author: tverwaes Date: Fri Mar 6 17:20:34 2009 New Revision: 62654 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_meta.py pypy/trunk/pypy/lang/gameboy/video_mode.py pypy/trunk/pypy/lang/gameboy/video_register.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: lots of refactorings which now allow the window to be draw separately as well... what was that jmario coder thinking? :) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Mar 6 17:20:34 2009 @@ -78,7 +78,7 @@ return tile_group, tile_map_index & 0x1F def get_selected_tile_data_space(self): - if self.control.background_and_window_lower_tile_data_selected: + if self.control.lower_tile_data_selected: return self.tile_data_0 else: return self.tile_data_1 @@ -457,10 +457,10 @@ self.driver.update_gb_display() def tile_index_flip(self): - if self.control.background_and_window_lower_tile_data_selected: - return 0x00 + if self.control.lower_tile_data_selected: + return 0 else: - return 0x80 + return 1 << 7 # First and last 128 tiles are swapped. def draw_window(self, window, line_y, line): if window.enabled: Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 17:20:34 2009 @@ -68,8 +68,20 @@ def update_screen(self): for y in range(self.height): line = self.screen[y] + for i in range(len(line)): + line[i] = 0x00 self.gameboy.video.draw_window(self.get_window(), y, line) +class WindowPreview(PreviewWindow): + def get_window(self): + # XXX Broken for now + return self.gameboy.video.window + +class BackgroundPreview(PreviewWindow): + def get_window(self): + return self.gameboy.video.background + + class MapViewer(VideoMetaWindow): def __init__(self, gameboy): self.map_x = 32 @@ -104,15 +116,6 @@ def get_map(self): return self.gameboy.video.tile_map_1 -class WindowPreview(PreviewWindow): - def get_window(self): - # XXX Broken for now - return self.gameboy.video.window - -class BackgroundPreview(PreviewWindow): - def get_window(self): - return self.gameboy.video.background - class SpriteWindow(VideoMetaWindow): def __init__(self, gameboy): self.sprites_y = 8 Modified: pypy/trunk/pypy/lang/gameboy/video_mode.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_mode.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_mode.py Fri Mar 6 17:20:34 2009 @@ -144,11 +144,10 @@ self.video.v_blank_interrupt_flag.set_pending() def emulate_v_blank_other(self): - if self.video.line_y < 153: + if self.video.line_y <= GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE: self.emulate_v_blank_mode_1() else: self.video.line_y = 0 - self.video.window.line_y = 0 self.set_between_end() self.emulate_hblank_line_y_compare() Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Fri Mar 6 17:20:34 2009 @@ -91,21 +91,21 @@ self.reset() def reset(self): - self.lcd_enabled = True - self.window.upper_tile_map_selected = False - self.window.enabled = False - self.background_and_window_lower_tile_data_selected = True - self.background.upper_tile_map_selected = False - self.big_sprites = False - self.sprites_enabled = False - self.background.enabled = True + self.lcd_enabled = True + self.window.upper_tile_map_selected = False + self.window.enabled = False + self.lower_tile_data_selected = True + self.background.upper_tile_map_selected = False + self.background.enabled = True + self.big_sprites = False + self.sprites_enabled = False def read(self): value = 0 value += int(self.lcd_enabled) << 7 value += int(self.window.upper_tile_map_selected) << 6 value += int(self.window.enabled) << 5 - value += int(self.background_and_window_lower_tile_data_selected) << 4 + value += int(self.lower_tile_data_selected) << 4 value += int(self.background.upper_tile_map_selected) << 3 value += int(self.big_sprites) << 2 value += int(self.sprites_enabled) << 1 @@ -132,16 +132,12 @@ was_enabled = self.window.enabled self.window.enabled = bool(value & (1 << 5)) - if not was_enabled and self.window.enabled: - self.window.switch_on() - - self.window.upper_tile_map_selected = bool(value & (1 << 6)) - self.background_and_window_lower_tile_data_selected = \ - bool(value & (1 << 4)) - self.background.upper_tile_map_selected = bool(value & (1 << 3)) - self.big_sprites = bool(value & (1 << 2)) - self.sprites_enabled = bool(value & (1 << 1)) - self.background.enabled = bool(value & (1 << 0)) + self.window.upper_tile_map_selected = bool(value & (1 << 6)) + self.lower_tile_data_selected = bool(value & (1 << 4)) + self.background.upper_tile_map_selected = bool(value & (1 << 3)) + self.big_sprites = bool(value & (1 << 2)) + self.sprites_enabled = bool(value & (1 << 1)) + self.background.enabled = bool(value & (1 << 0)) if previous_big_sprites != self.big_sprites: self.video.update_sprite_size() Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Mar 6 17:20:34 2009 @@ -249,7 +249,9 @@ class Drawable(object): def __init__(self, video): - self.video = video + self.video = video + self.enabled = False + self.upper_tile_map_selected = False self.reset() def get_tile_map_space(self): @@ -282,28 +284,20 @@ def reset(self): self.x = 0 self.y = 0 - self.line_y = 0 - self.enabled = False - self.upper_tile_map_selected = False - - def switch_on(self): - if self.line_y == 0 and self.video.line_y > self.y: - self.line_y = GAMEBOY_SCREEN_HEIGHT def draw_clean_line(self, line): pass def draw_line(self, line_y, tile_data, tile_index_flip, line): - if line_y >= self.y and self.x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE-1 and \ - self.line_y < GAMEBOY_SCREEN_HEIGHT: + relative_y = line_y - self.y + if relative_y >= 0 and relative_y < GAMEBOY_SCREEN_HEIGHT: tile_map = self.get_tile_map_space() - tile_group = tile_map[self.line_y >> 3] + tile_group = tile_map[relative_y >> 3] self.draw_tiles(self.x + 1, tile_group, - self.line_y, tile_data, + relative_y, tile_data, tile_index_flip, line) - self.line_y += 1 # ----------------------------------------------------------------------------- @@ -314,8 +308,6 @@ # be displayed in the left upper corner of the screen. self.scroll_x = 0 self.scroll_y = 0 - self.enabled = True - self.upper_tile_map_selected = False def draw_clean_line(self, line): for x in range(len(line)): From fijal at codespeak.net Fri Mar 6 17:27:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 17:27:42 +0100 (CET) Subject: [pypy-svn] r62655 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306162742.9681116849E@codespeak.net> Author: fijal Date: Fri Mar 6 17:27:38 2009 New Revision: 62655 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: a bit of progress. some tests pass (but some don't!). Let's start killing! Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 17:27:38 2009 @@ -718,7 +718,7 @@ return ops + [Perform(op, arglocs, eax)] else: self.free_regs = REGS[:] - return ops + [PerformDiscard(op, arglocs)] + return ops + [Perform(op, arglocs, eax)] def consider_call(self, op, ignored): args = [op.args[0]] + op.args[2:] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 17:27:38 2009 @@ -11,7 +11,7 @@ from pypy.jit.metainterp import history from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) -from pypy.jit.backend.x86.assembler import Assembler386, WORD +from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.x86.executor import execute @@ -19,12 +19,17 @@ GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) +VOID = 0 +PTR = 1 +INT = 2 + class CPU386(object): debug = True BOOTSTRAP_TP = lltype.FuncType([lltype.Signed, lltype.Ptr(rffi.CArray(lltype.Signed))], lltype.Signed) + return_value_box = None def __init__(self, rtyper, stats, translate_support_code=False, mixlevelann=None): @@ -56,6 +61,7 @@ if rtyper is not None: # for tests self.lltype2vtable = rtyper.lltype_to_vtable_mapping() self._setup_ovf_error() + self.generated_mps = [None] * 10 def _setup_ovf_error(self): if self.translate_support_code: @@ -116,6 +122,7 @@ guard_op, 'to the jit') gf = GuardFailed(self, frame_addr, guard_op) self.metainterp.handle_guard_failure(gf) + self.return_value_box = gf.return_value_box if self.debug: if gf.return_addr == self.assembler.generic_return_addr: llop.debug_print(lltype.Void, 'continuing at generic return address') @@ -258,8 +265,24 @@ else: raise ValueError('get_valuebox_from_int: %s' % (type,)) - def execute_operations_in_new_frame(self, name, startmp, valueboxes, - result_type): + def _get_mp_for_call(self, argnum): + if argnum >= len(self.generated_mps): + self.generated_mps += [None] * len(self.generated_mps) + actual = self.generated_mps[argnum] + if actual is not None: + return actual + args = [BoxInt(0) for i in range(argnum + 1)] + result = BoxInt(0) + operations = [ + ResOperation(rop.MERGE_POINT, args, None), + ResOperation(rop.CALL, args, result), + ResOperation(RETURN, [result], None)] + self.compile_operations(operations) + self.generated_mps[argnum] = operations + return operations + + def execute_operations_in_new_frame(self, name, operations, valueboxes): + startmp = operations[0] func = self.get_bootstrap_code(startmp) # turn all the values into integers TP = rffi.CArray(lltype.Signed) @@ -270,25 +293,24 @@ v = self.get_box_value_as_int(box) values_as_int[i] = v # debug info - values_repr = ", ".join([str(values_as_int[i]) for i in - range(len(valueboxes))]) if self.debug: + values_repr = ", ".join([str(values_as_int[i]) for i in + range(len(valueboxes))]) llop.debug_print(lltype.Void, 'exec:', name, values_repr) self.keepalives_index = len(self.keepalives) res = self.execute_call(startmp, func, values_as_int) - if result_type == 'void': + if self.return_value_box is None: if self.debug: llop.debug_print(lltype.Void, " => void result") res = None else: if self.debug: llop.debug_print(lltype.Void, " => ", res) - res = self.get_valuebox_from_int(result_type, res) keepalive_until_here(valueboxes) self.keepalives_index = oldindex del self.keepalives[oldindex:] - return res + return self.return_value_box def execute_call(self, startmp, func, values_as_int): # help flow objspace @@ -521,6 +543,12 @@ a = args[0].getptr(llmemory.GCREF) rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) + def do_call(self, args): + calldescr = args[1].getint() + num_args, tp = self.unpack_calldescr(calldescr) + mp = self._get_mp_for_call(num_args) + self.execute_operations_in_new_frame('call', mp, args) + # ------------------- helpers and descriptions -------------------- @staticmethod @@ -559,7 +587,17 @@ @staticmethod def calldescrof(argtypes, resulttype): - return 3 + if resulttype is lltype.Void: + rt = VOID + elif isinstance(resulttype, lltype.Ptr): + rt = PTR + else: + rt = INT + return (len(argtypes) << 2) + rt + + @staticmethod + def unpack_calldescr(calldescr): + return calldescr >> 2, calldescr & 0x4 @staticmethod def fielddescrof(S, fieldname): @@ -609,6 +647,8 @@ return hex(x) class GuardFailed(object): + return_value_box = None + def __init__(self, cpu, frame, guard_op): self.cpu = cpu self.frame = frame @@ -619,6 +659,7 @@ if return_value_box is not None: frame = getframe(self.frame) frame[0] = self.cpu.convert_box_to_int(return_value_box) + self.return_value_box = return_value_box self.return_addr = self.cpu.assembler.generic_return_addr def make_ready_for_continuing_at(self, merge_point): @@ -631,3 +672,5 @@ CPU = CPU386 +import pypy.jit.metainterp.executor +pypy.jit.metainterp.executor.make_execute_list(CPU) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 17:27:38 2009 @@ -505,3 +505,25 @@ # cpu.do_strsetitem([x, BoxInt(4), BoxInt(ord('/'))]) assert x.getptr(lltype.Ptr(rstr.STR)).chars[4] == '/' + + def test_do_call(self): + from pypy.rpython.annlowlevel import llhelper + cpu = self.cpu + # + def func(c): + return chr(ord(c) + 1) + FPTR = lltype.Ptr(lltype.FuncType([lltype.Char], lltype.Char)) + func_ptr = llhelper(FPTR, func) + calldescr = cpu.calldescrof([lltype.Char], lltype.Char) + x = cpu.do_call( + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(func_ptr))), + ConstInt(calldescr), + BoxInt(ord('A'))]) + assert x.value == ord('B') + + def test_executor(self): + cpu = self.cpu + x = execute(cpu, rop.INT_ADD, [BoxInt(100), ConstInt(42)]) + assert x.value == 142 + s = execute(cpu, rop.NEWSTR, [BoxInt(8)]) + assert len(s.getptr(lltype.Ptr(rstr.STR)).chars) == 8 From tverwaes at codespeak.net Fri Mar 6 17:56:58 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 17:56:58 +0100 (CET) Subject: [pypy-svn] r62656 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306165658.3A6871684B5@codespeak.net> Author: tverwaes Date: Fri Mar 6 17:56:55 2009 New Revision: 62656 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_meta.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: further disentangling classes Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Mar 6 17:56:55 2009 @@ -7,7 +7,8 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy.video_meta import TileDataWindow, SpriteWindow,\ WindowPreview, BackgroundPreview,\ - MapAViewer, MapBViewer + MapAViewer, MapBViewer,\ + SpritesWindow from pypy.lang.gameboy import constants import time @@ -122,13 +123,15 @@ self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def create_meta_windows(self, gameboy): - self.meta_windows = [TileDataWindow(gameboy), - SpriteWindow(gameboy), - WindowPreview(gameboy), - BackgroundPreview(gameboy), - MapAViewer(gameboy), - MapBViewer(gameboy)] + upper_meta_windows = [TileDataWindow(gameboy), + SpriteWindow(gameboy), + WindowPreview(gameboy)] + lower_meta_windows = [BackgroundPreview(gameboy), + MapAViewer(gameboy), + MapBViewer(gameboy), + SpritesWindow(gameboy)] + self.meta_windows = upper_meta_windows + lower_meta_windows for window in self.meta_windows: window.set_origin(self.width, 0) self.height = max(self.height, window.height) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Mar 6 17:56:55 2009 @@ -20,13 +20,13 @@ self.driver = video_driver self.v_blank_interrupt_flag = interrupt.v_blank self.lcd_interrupt_flag = interrupt.lcd - self.window = Window(self) - self.background = Background(self) + self.create_tile_maps() + self.window = Window(self.tile_maps) + self.background = Background(self.tile_maps) self.status = StatusRegister(self) self.control = ControlRegister(self, self.window, self.background) self.memory = memory - self.create_tile_maps() self.create_tiles() self.create_sprites() self.reset() @@ -473,23 +473,23 @@ def draw_line(self): self.draw_window(self.background, self.line_y, self.line) self.draw_window(self.window, self.line_y, self.line) - self.draw_sprites_line() + self.draw_sprites(self.line_y, self.line) self.send_pixels_line_to_driver() - def draw_sprites_line(self): + def draw_sprites(self, line_y, line): if not self.control.sprites_enabled: return - count = self.scan_sprites() + count = self.scan_sprites(line_y) lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): sprite = self.shown_sprites[index] - sprite.draw(self.line, self.line_y, lastx) + sprite.draw(line, line_y, lastx) lastx = sprite.x - def scan_sprites(self): + def scan_sprites(self, line_y): # search active shown_sprites count = 0 for sprite in self.sprites: - if sprite.is_shown_on_line(self.line_y): + if sprite.is_shown_on_line(line_y): self.shown_sprites[count] = sprite count += 1 if count >= SPRITES_PER_LINE: Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 17:56:55 2009 @@ -33,7 +33,8 @@ for x in range(self.width): self.gameboy.video_driver.draw_pixel(x + self.x, y + self.y, - self.gameboy.video.palette[self.screen[y][x]]) + self.gameboy.video.palette[ + self.screen[y][x]]) def clear_screen(self): for line in self.screen: @@ -56,13 +57,13 @@ line = self.screen[y_offset + y_id * SPRITE_SIZE] tile.draw(line, x_id * SPRITE_SIZE, y_offset) -class PreviewWindow(VideoMetaWindow): +class LogicWindow(VideoMetaWindow): def __init__(self, gameboy): VideoMetaWindow.__init__(self, gameboy, SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE, GAMEBOY_SCREEN_HEIGHT) - def get_window(self): + def draw_line(self, y, line): raise Exception("Not Implemented") def update_screen(self): @@ -70,11 +71,21 @@ line = self.screen[y] for i in range(len(line)): line[i] = 0x00 - self.gameboy.video.draw_window(self.get_window(), y, line) + self.draw_line(y, line) + +class PreviewWindow(LogicWindow): + def get_window(self): + raise Exception("Not Implemented") + + def draw_line(self, y, line): + self.gameboy.video.draw_window(self.get_window(), y, line) + +class SpritesWindow(LogicWindow): + def draw_line(self, y, line): + self.gameboy.video.draw_sprites(y, line) class WindowPreview(PreviewWindow): def get_window(self): - # XXX Broken for now return self.gameboy.video.window class BackgroundPreview(PreviewWindow): Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Mar 6 17:56:55 2009 @@ -248,17 +248,14 @@ # ----------------------------------------------------------------------------- class Drawable(object): - def __init__(self, video): - self.video = video + def __init__(self, tile_maps): + self.tile_maps = tile_maps self.enabled = False self.upper_tile_map_selected = False self.reset() def get_tile_map_space(self): - if self.upper_tile_map_selected: - return self.video.tile_map_1 - else: - return self.video.tile_map_0 + return self.tile_maps[self.upper_tile_map_selected] def reset(self): raise Exception("Not implemented") @@ -314,11 +311,11 @@ line[x] = 0x00 def draw_line(self, line_y, tile_data, tile_index_flip, line): - y = (self.scroll_y + line_y) & 0xFF + relative_y = (self.scroll_y + line_y) & 0xFF x = self.scroll_x tile_map = self.get_tile_map_space() - tile_group = tile_map[y >> 3] + tile_group = tile_map[relative_y >> 3] self.draw_tiles(8 - (x % 8), tile_group, - y, tile_data, + relative_y, tile_data, tile_index_flip, line, x >> 3) From fijal at codespeak.net Fri Mar 6 18:08:13 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 18:08:13 +0100 (CET) Subject: [pypy-svn] r62657 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306170813.253AF168483@codespeak.net> Author: fijal Date: Fri Mar 6 18:08:12 2009 New Revision: 62657 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: a bit of progress. remove again RETURN, in favor of a failing guard. should more or less work by now, but do_call explodes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 6 18:08:12 2009 @@ -7,8 +7,7 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, - arg_pos, lower_byte, stack_pos, Perform, - RETURN) + arg_pos, lower_byte, stack_pos, Perform) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.support import gc_malloc_fnaddr @@ -419,7 +418,7 @@ genop_catch = genop_merge_point - def genop_return(self, op, locs): + def xxx_genop_return(self, op, locs): if op.args: loc = locs[0] if loc is not eax: @@ -530,17 +529,14 @@ # self.gen_call(op, arglocs, resloc) # self.mc.MOVZX(eax, eax) -genop_discard_list = [None] * (RETURN + 1) -genop_list = [None] * (RETURN + 1) -genop_guard_list = [None] * (RETURN + 1) +genop_discard_list = [None] * rop._LAST +genop_list = [None] * rop._LAST +genop_guard_list = [None] * rop._LAST for name, value in Assembler386.__dict__.iteritems(): if name.startswith('genop_'): opname = name[len('genop_'):] - if opname == 'return': - num = RETURN - else: - num = getattr(rop, opname.upper()) + num = getattr(rop, opname.upper()) if value.func_code.co_argcount == 3: genop_discard_list[num] = value elif value.func_code.co_argcount == 5: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 18:08:12 2009 @@ -17,8 +17,6 @@ WORD = 4 FRAMESIZE = 1024 # XXX should not be a constant at all!! -RETURN = rop._LAST + 1 - class TempBox(Box): def __init__(self): pass @@ -580,7 +578,7 @@ self.eventually_free_vars(op.liveboxes + op.args) return ops + [PerformDiscard(op, [x, y] + locs)] - def consider_return(self, op, ignored): + def xxx_consider_return(self, op, ignored): if op.args: arglocs = [self.loc(op.args[0])] self.eventually_free_var(op.args[0]) @@ -951,15 +949,12 @@ self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] -oplist = [None] * (RETURN + 1) +oplist = [None] * rop._LAST for name, value in RegAlloc.__dict__.iteritems(): if name.startswith('consider_'): name = name[len('consider_'):] - if name == 'return': - num = RETURN - else: - num = getattr(rop, name.upper()) + num = getattr(rop, name.upper()) oplist[num] = value def arg_pos(i): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 18:08:12 2009 @@ -11,7 +11,7 @@ from pypy.jit.metainterp import history from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) -from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN +from pypy.jit.backend.x86.assembler import Assembler386, WORD from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.x86.executor import execute @@ -29,6 +29,7 @@ BOOTSTRAP_TP = lltype.FuncType([lltype.Signed, lltype.Ptr(rffi.CArray(lltype.Signed))], lltype.Signed) + return_value_box = None def __init__(self, rtyper, stats, translate_support_code=False, @@ -148,81 +149,81 @@ def get_exc_value(self, frame): return self.cast_int_to_gcref(self.assembler._exception_data[1]) - def execute_operation(self, opnum, valueboxes, result_type): - xxx - if execute[opnum] is not None: - return execute[opnum](valueboxes) +# def execute_operation(self, opnum, valueboxes, result_type): +# xxx +# if execute[opnum] is not None: +# return execute[opnum](valueboxes) - # mostly a hack: fall back to compiling and executing the single - # operation. - key = [] - for valuebox in valueboxes: - if isinstance(valuebox, Box): - key.append(valuebox.type) - else: - key.append(str(valuebox.get_())) - mp = self.get_compiled_single_operation(opnum, result_type, - key, valueboxes) - res = self.execute_operations_in_new_frame(opname[opnum], mp, - valueboxes, - result_type) - if not self.translate_support_code: - if self.assembler._exception_data[0] != 0: - TP = lltype.Ptr(rclass.OBJECT_VTABLE) - TP_V = lltype.Ptr(rclass.OBJECT) - exc_t_a = self.cast_int_to_adr(self.get_exception(None)) - exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) - exc_v_a = self.get_exc_value(None) - exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) - # clean up the exception - self.assembler._exception_data[0] = 0 - raise LLException(exc_type, exc_val) - # otherwise exception data is set correctly, no problem at all - return res - - def get_compiled_single_operation(self, opnum, result_type, key, - valueboxes): - xxx - real_key = '%d,%s' % (opnum, result_type) + ','.join(key) - try: - return self._compiled_ops[real_key] - except KeyError: - livevarlist = [] - i = 0 - # clonebox below is necessary, because sometimes we know - # that the value is constant (ie ArrayDescr), but we're not - # going to get the contant. So instead we get a box with correct - # value - for box in valueboxes: - if box.type == 'int': - box = valueboxes[i].clonebox() - elif box.type == 'ptr': - box = valueboxes[i].clonebox() - else: - raise ValueError(type) - livevarlist.append(box) - i += 1 - mp = ResOperation(rop.MERGE_POINT, livevarlist, None) - if result_type == 'void': - result = None - elif result_type == 'int': - result = history.BoxInt() - elif result_type == 'ptr': - result = history.BoxPtr() - else: - raise ValueError(result_type) - if result is None: - results = [] - else: - results = [result] - operations = [mp, - ResOperation(opnum, livevarlist, result), - ResOperation(rop.RETURN, results, None)] - if operations[1].is_guard(): - operations[1].liveboxes = [] - self.compile_operations(operations, verbose=False) - self._compiled_ops[real_key] = mp - return mp +# # mostly a hack: fall back to compiling and executing the single +# # operation. +# key = [] +# for valuebox in valueboxes: +# if isinstance(valuebox, Box): +# key.append(valuebox.type) +# else: +# key.append(str(valuebox.get_())) +# mp = self.get_compiled_single_operation(opnum, result_type, +# key, valueboxes) +# res = self.execute_operations_in_new_frame(opname[opnum], mp, +# valueboxes, +# result_type) +# if not self.translate_support_code: +# if self.assembler._exception_data[0] != 0: +# TP = lltype.Ptr(rclass.OBJECT_VTABLE) +# TP_V = lltype.Ptr(rclass.OBJECT) +# exc_t_a = self.cast_int_to_adr(self.get_exception(None)) +# exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) +# exc_v_a = self.get_exc_value(None) +# exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) +# # clean up the exception +# self.assembler._exception_data[0] = 0 +# raise LLException(exc_type, exc_val) +# # otherwise exception data is set correctly, no problem at all +# return res + +# def get_compiled_single_operation(self, opnum, result_type, key, +# valueboxes): +# xxx +# real_key = '%d,%s' % (opnum, result_type) + ','.join(key) +# try: +# return self._compiled_ops[real_key] +# except KeyError: +# livevarlist = [] +# i = 0 +# # clonebox below is necessary, because sometimes we know +# # that the value is constant (ie ArrayDescr), but we're not +# # going to get the contant. So instead we get a box with correct +# # value +# for box in valueboxes: +# if box.type == 'int': +# box = valueboxes[i].clonebox() +# elif box.type == 'ptr': +# box = valueboxes[i].clonebox() +# else: +# raise ValueError(type) +# livevarlist.append(box) +# i += 1 +# mp = ResOperation(rop.MERGE_POINT, livevarlist, None) +# if result_type == 'void': +# result = None +# elif result_type == 'int': +# result = history.BoxInt() +# elif result_type == 'ptr': +# result = history.BoxPtr() +# else: +# raise ValueError(result_type) +# if result is None: +# results = [] +# else: +# results = [result] +# operations = [mp, +# ResOperation(opnum, livevarlist, result), +# ResOperation(rop.RETURN, results, None)] +# if operations[1].is_guard(): +# operations[1].liveboxes = [] +# self.compile_operations(operations, verbose=False) +# self._compiled_ops[real_key] = mp +# return mp def compile_operations(self, operations, guard_op=None, verbose=True): self.assembler.assemble(operations, guard_op, verbose=verbose) @@ -258,9 +259,9 @@ raise ValueError('get_box_value_as_int, wrong arg') def get_valuebox_from_int(self, type, x): - if type == 'int': + if type == INT: return history.BoxInt(x) - elif type == 'ptr': + elif type == PTR: return history.BoxPtr(self.cast_int_to_gcref(x)) else: raise ValueError('get_valuebox_from_int: %s' % (type,)) @@ -271,12 +272,13 @@ actual = self.generated_mps[argnum] if actual is not None: return actual - args = [BoxInt(0) for i in range(argnum + 1)] + args = [BoxInt(0) for i in range(argnum + 3)] result = BoxInt(0) operations = [ ResOperation(rop.MERGE_POINT, args, None), - ResOperation(rop.CALL, args, result), - ResOperation(RETURN, [result], None)] + ResOperation(rop.CALL, args[:-1], result), + ResOperation(rop.GUARD_FALSE, [args[-1]], None)] + operations[-1].liveboxes = [result] self.compile_operations(operations) self.generated_mps[argnum] = operations return operations @@ -303,7 +305,6 @@ if self.return_value_box is None: if self.debug: llop.debug_print(lltype.Void, " => void result") - res = None else: if self.debug: llop.debug_print(lltype.Void, " => ", res) @@ -547,7 +548,7 @@ calldescr = args[1].getint() num_args, tp = self.unpack_calldescr(calldescr) mp = self._get_mp_for_call(num_args) - self.execute_operations_in_new_frame('call', mp, args) + return self.execute_operations_in_new_frame('call', mp, args + [BoxInt(1)]) # ------------------- helpers and descriptions -------------------- Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 18:08:12 2009 @@ -4,7 +4,7 @@ from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, Box) from pypy.jit.backend.x86.runner import CPU, GuardFailed -from pypy.jit.backend.x86.regalloc import WORD, RETURN +from pypy.jit.backend.x86.regalloc import WORD from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop import ctypes @@ -20,7 +20,10 @@ self.recordedvalues = [ gf.cpu.getvaluebox(gf.frame, gf.guard_op, i).value for i in range(len(gf.guard_op.liveboxes))] - gf.make_ready_for_return(BoxInt(42)) + if len(gf.guard_op.liveboxes) > 0: + gf.make_ready_for_return(gf.cpu.getvaluebox(gf.frame, gf.guard_op, 0)) + else: + gf.make_ready_for_return(None) MY_VTABLE = lltype.Struct('my_vtable') # for tests only @@ -39,13 +42,14 @@ class TestX86(object): def setup_class(cls): cls.cpu = CPU(rtyper=None, stats=FakeStats()) + cls.cpu.set_meta_interp(FakeMetaInterp()) def execute_operation(self, opname, valueboxes, result_type): key = [opname, result_type] mp = self.get_compiled_single_operation(opname, result_type, valueboxes) boxes = [box for box in valueboxes if isinstance(box, Box)] - res = self.cpu.execute_operations_in_new_frame(opname, mp, boxes, - result_type) + res = self.cpu.execute_operations_in_new_frame(opname, mp, boxes + + [BoxInt(1)]) return res def get_compiled_single_operation(self, opnum, result_type, valueboxes): @@ -54,9 +58,10 @@ if isinstance(box, Box): box = box.clonebox() livevarlist.append(box) - mp = ResOperation(rop.MERGE_POINT, - [box for box in livevarlist if isinstance(box, Box)], - None) + args = [box for box in livevarlist if isinstance(box, Box)] + checker = BoxInt(1) + args.append(checker) + mp = ResOperation(rop.MERGE_POINT, args, None) if result_type == 'void': result = None elif result_type == 'int': @@ -71,11 +76,12 @@ results = [result] operations = [mp, ResOperation(opnum, livevarlist, result), - ResOperation(RETURN, results, None)] + ResOperation(rop.GUARD_FALSE, [checker], None)] + operations[-1].liveboxes = results if operations[1].is_guard(): operations[1].liveboxes = [] self.cpu.compile_operations(operations, verbose=False) - return mp + return operations def test_int_binary_ops(self): @@ -136,10 +142,9 @@ operations[-1].jump_target = startmp operations[-2].liveboxes = [t, u, z] cpu.compile_operations(operations) - res = self.cpu.execute_operations_in_new_frame('foo', startmp, - [BoxInt(0), BoxInt(10)], - 'int') - assert res.value == 42 + res = self.cpu.execute_operations_in_new_frame('foo', operations, + [BoxInt(0), BoxInt(10)]) + assert res.value == 0 gf = cpu.metainterp.gf assert cpu.metainterp.recordedvalues == [0, True, 55] assert gf.guard_op is operations[-2] From tverwaes at codespeak.net Fri Mar 6 18:22:28 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 18:22:28 +0100 (CET) Subject: [pypy-svn] r62658 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306172228.C29281684EB@codespeak.net> Author: tverwaes Date: Fri Mar 6 18:22:22 2009 New Revision: 62658 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_meta.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixing sprite preview color definitely have to crop screen :) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Mar 6 18:22:22 2009 @@ -78,10 +78,7 @@ return tile_group, tile_map_index & 0x1F def get_selected_tile_data_space(self): - if self.control.lower_tile_data_selected: - return self.tile_data_0 - else: - return self.tile_data_1 + return self.tile_data[not self.control.lower_tile_data_selected] def get_tile_map(self, address): tile_group, group_index = self.select_tile_group_for(address) Modified: pypy/trunk/pypy/lang/gameboy/video_meta.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_meta.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_meta.py Fri Mar 6 18:22:22 2009 @@ -67,10 +67,9 @@ raise Exception("Not Implemented") def update_screen(self): + self.clear_screen() for y in range(self.height): line = self.screen[y] - for i in range(len(line)): - line[i] = 0x00 self.draw_line(y, line) class PreviewWindow(LogicWindow): @@ -149,5 +148,4 @@ for x in range(SPRITE_SIZE): x += x_id * SPRITE_SIZE - line[x] = line[x] << 1 # Colors of sprites are in - # another range of the palette. + line[x] = (line[x] << 1) | sprite.tile_mask() Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Mar 6 18:22:22 2009 @@ -196,19 +196,17 @@ draw_y = self.get_draw_y(line_y) tile.draw_for_sprite(self, line, draw_y, lastx) + def tile_mask(self): + return (self.palette_number << 2) +\ + (self.object_behind_background << 3) + # ----------------------------------------------------------------------------- class Tile(object): def __init__(self): self.data = [0x00 for i in range(2*SPRITE_SIZE)] - - def draw(self, line, x, y): - pattern = self.get_pattern_at(y << 1) - for i in range(SPRITE_SIZE): - color = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 - line[x + i] = color - + def set_tile_data(self, data): self.data = data @@ -225,25 +223,29 @@ return self.get_data_at(address) +\ (self.get_data_at(address + 1) << 8) + def draw(self, line, x, y): + pattern = self.get_pattern_at(y << 1) + for i in range(SPRITE_SIZE): + color = (pattern >> (SPRITE_SIZE - 1 - i)) & 0x0101 + line[x + i] = color + def draw_for_sprite(self, sprite, line, y, lastx): if sprite.x_flipped: convert, offset = 1, 0 # 0-7 else: convert, offset = -1, SPRITE_SIZE # 7-0 - y = y << 1 # 2 bytes per line - pattern = self.get_pattern_at(y) << 1 - mask = (sprite.palette_number << 2) +\ - (sprite.object_behind_background << 3) + pattern = self.get_pattern_at(y << 1) + mask = sprite.tile_mask() for i in range(SPRITE_SIZE): - color = (pattern >> i) & 0x0202 + color = (pattern >> i) & 0x0101 x = sprite.x + offset + i*convert - if bool(color): + if color: if sprite.x + SPRITE_SIZE > lastx: # Overlapped. line[x] &= 0x0101 - line[x] |= color | mask + line[x] |= (color << 1) | mask # ----------------------------------------------------------------------------- From fijal at codespeak.net Fri Mar 6 18:28:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 18:28:17 +0100 (CET) Subject: [pypy-svn] r62659 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306172817.2EDD71684B5@codespeak.net> Author: fijal Date: Fri Mar 6 18:28:12 2009 New Revision: 62659 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: good, support calls of different sizes as well. thanks armin :) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 6 18:28:12 2009 @@ -500,6 +500,10 @@ return recovery_code_addr def genop_call(self, op, arglocs, resloc): + sizeloc = arglocs[0] + assert isinstance(sizeloc, IMM32) + size = sizeloc.value + arglocs = arglocs[1:] extra_on_stack = 0 for i in range(len(op.args) - 1, 0, -1): # op.args[1] is a calldesc @@ -519,6 +523,10 @@ x = arglocs[0] self.mc.CALL(x) self.mc.ADD(esp, imm(WORD * extra_on_stack)) + if size == 1: + self.mc.AND(eax, imm(0xff)) + elif size == 2: + self.mc.AND(eax, imm(0xffff)) #def genop_call__1(self, op, arglocs, resloc): # self.gen_call(op, arglocs, resloc) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 18:28:12 2009 @@ -719,8 +719,12 @@ return ops + [Perform(op, arglocs, eax)] def consider_call(self, op, ignored): + from pypy.jit.backend.x86.runner import CPU386 args = [op.args[0]] + op.args[2:] - return self._call(op, [self.loc(arg) for arg in args]) + calldescr = op.args[1].getint() + _, size, _ = CPU386.unpack_calldescr(calldescr) + return self._call(op, [imm(size)] + + [self.loc(arg) for arg in args]) consider_call_pure = consider_call Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 18:28:12 2009 @@ -62,7 +62,7 @@ if rtyper is not None: # for tests self.lltype2vtable = rtyper.lltype_to_vtable_mapping() self._setup_ovf_error() - self.generated_mps = [None] * 10 + self.generated_mps = {} def _setup_ovf_error(self): if self.translate_support_code: @@ -266,13 +266,13 @@ else: raise ValueError('get_valuebox_from_int: %s' % (type,)) - def _get_mp_for_call(self, argnum): - if argnum >= len(self.generated_mps): - self.generated_mps += [None] * len(self.generated_mps) - actual = self.generated_mps[argnum] - if actual is not None: - return actual + def _get_mp_for_call(self, argnum, calldescr): + try: + return self.generated_mps[calldescr] + except KeyError: + pass args = [BoxInt(0) for i in range(argnum + 3)] + args[1].value = calldescr result = BoxInt(0) operations = [ ResOperation(rop.MERGE_POINT, args, None), @@ -280,7 +280,7 @@ ResOperation(rop.GUARD_FALSE, [args[-1]], None)] operations[-1].liveboxes = [result] self.compile_operations(operations) - self.generated_mps[argnum] = operations + self.generated_mps[calldescr] = operations return operations def execute_operations_in_new_frame(self, name, operations, valueboxes): @@ -546,8 +546,8 @@ def do_call(self, args): calldescr = args[1].getint() - num_args, tp = self.unpack_calldescr(calldescr) - mp = self._get_mp_for_call(num_args) + num_args, size, ptr = self.unpack_calldescr(calldescr) + mp = self._get_mp_for_call(num_args, calldescr) return self.execute_operations_in_new_frame('call', mp, args + [BoxInt(1)]) # ------------------- helpers and descriptions -------------------- @@ -589,16 +589,22 @@ @staticmethod def calldescrof(argtypes, resulttype): if resulttype is lltype.Void: - rt = VOID - elif isinstance(resulttype, lltype.Ptr): - rt = PTR + size = 0 else: - rt = INT - return (len(argtypes) << 2) + rt + size = symbolic.get_size(resulttype) + res = (len(argtypes) << 4) + size + if isinstance(resulttype, lltype.Ptr): + return ~res + return res @staticmethod def unpack_calldescr(calldescr): - return calldescr >> 2, calldescr & 0x4 + if calldescr < 0: + calldescr = ~calldescr + ptr = True + else: + ptr = False + return calldescr >> 4, calldescr & 0xf, ptr @staticmethod def fielddescrof(S, fieldname): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 18:28:12 2009 @@ -7,6 +7,7 @@ from pypy.jit.backend.x86.regalloc import WORD from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp.executor import execute import ctypes import sys From tverwaes at codespeak.net Fri Mar 6 18:36:56 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 6 Mar 2009 18:36:56 +0100 (CET) Subject: [pypy-svn] r62660 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090306173656.096B61684FC@codespeak.net> Author: tverwaes Date: Fri Mar 6 18:36:51 2009 New Revision: 62660 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: nicer layouting of meta-windows Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Mar 6 18:36:51 2009 @@ -123,19 +123,29 @@ self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def create_meta_windows(self, gameboy): - upper_meta_windows = [TileDataWindow(gameboy), + upper_meta_windows = [SpritesWindow(gameboy), SpriteWindow(gameboy), - WindowPreview(gameboy)] - lower_meta_windows = [BackgroundPreview(gameboy), + TileDataWindow(gameboy), + ] + lower_meta_windows = [ + WindowPreview(gameboy), + BackgroundPreview(gameboy), MapAViewer(gameboy), - MapBViewer(gameboy), - SpritesWindow(gameboy)] + MapBViewer(gameboy)] self.meta_windows = upper_meta_windows + lower_meta_windows - for window in self.meta_windows: + for window in upper_meta_windows: window.set_origin(self.width, 0) self.height = max(self.height, window.height) self.width += window.width + second_x = 0 + second_y = self.height + for window in lower_meta_windows: + window.set_origin(second_x, second_y) + second_x += window.width + self.width = max(self.width, second_x) + self.height = max(self.height, second_y + window.height) + def update_display(self): if use_rsdl: From arigo at codespeak.net Fri Mar 6 18:47:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 6 Mar 2009 18:47:03 +0100 (CET) Subject: [pypy-svn] r62661 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/llgraph/test metainterp metainterp/test Message-ID: <20090306174703.38C411684E1@codespeak.net> Author: arigo Date: Fri Mar 6 18:46:59 2009 New Revision: 62661 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Rewrite the operations that take an always-constant int argument (fielddescr, arraydescr, calldescr) to pass this as an integer on the ResOperation class directly ('descr'). This changes many operations that now take one argument less. I hope I fixed everything about them... but I may have forgotten something in optimize.py. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Mar 6 18:46:59 2009 @@ -4,6 +4,7 @@ when executing on top of the llinterpreter. """ +import sys from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, @@ -82,45 +83,44 @@ 'uint_ne' : (('int', 'int'), 'bool'), 'uint_gt' : (('int', 'int'), 'bool'), 'uint_ge' : (('int', 'int'), 'bool'), - 'new_with_vtable' : (('int', 'ptr'), 'ptr'), - 'new' : (('int',), 'ptr'), - 'new_array' : (('int', 'int'), 'ptr'), + 'new_with_vtable' : (('ptr',), 'ptr'), + 'new' : ((), 'ptr'), + 'new_array' : (('int',), 'ptr'), 'oononnull' : (('ptr',), 'bool'), 'ooisnull' : (('ptr',), 'bool'), 'oois' : (('ptr', 'ptr'), 'bool'), 'ooisnot' : (('ptr', 'ptr'), 'bool'), - 'setfield_gc' : (('ptr', 'fieldname', 'intorptr'), None), - 'getfield_gc' : (('ptr', 'fieldname'), 'intorptr'), - 'getfield_gc_pure': (('ptr', 'fieldname'), 'intorptr'), - 'setfield_raw' : (('ptr', 'fieldname', 'intorptr'), None), - 'getfield_raw' : (('ptr', 'fieldname'), 'intorptr'), - 'getfield_raw_pure': (('ptr', 'fieldname'), 'intorptr'), - 'setarrayitem_gc' : (('ptr', 'int', 'int', 'intorptr'), None), - 'getarrayitem_gc' : (('ptr', 'int', 'int'), 'intorptr'), - 'getarrayitem_gc_pure' : (('ptr', 'int', 'int'), 'intorptr'), - 'arraylen_gc' : (('ptr', 'int'), 'int'), - 'call' : (('ptr', 'int', 'varargs'), 'intorptr'), - 'call_pure' : (('ptr', 'int', 'varargs'), 'intorptr'), + 'setfield_gc' : (('ptr', 'intorptr'), None), + 'getfield_gc' : (('ptr',), 'intorptr'), + 'getfield_gc_pure': (('ptr',), 'intorptr'), + 'setfield_raw' : (('ptr', 'intorptr'), None), + 'getfield_raw' : (('ptr',), 'intorptr'), + 'getfield_raw_pure': (('ptr',), 'intorptr'), + 'setarrayitem_gc' : (('ptr', 'int', 'intorptr'), None), + 'getarrayitem_gc' : (('ptr', 'int'), 'intorptr'), + 'getarrayitem_gc_pure' : (('ptr', 'int'), 'intorptr'), + 'arraylen_gc' : (('ptr',), 'int'), + 'call' : (('ptr', 'varargs'), 'intorptr'), + 'call_pure' : (('ptr', 'varargs'), 'intorptr'), 'guard_true' : (('bool',), None), 'guard_false' : (('bool',), None), 'guard_value' : (('int', 'int'), None), 'guard_class' : (('ptr', 'ptr'), None), 'guard_no_exception' : ((), None), 'guard_exception' : (('ptr',), 'ptr'), - 'guard_nonvirtualized' : (('ptr', 'ptr', 'int'), None), - 'guard_builtin' : (('ptr',), None), + 'guard_nonvirtualized' : (('ptr', 'ptr'), None), 'newstr' : (('int',), 'ptr'), 'strlen' : (('ptr',), 'int'), 'strgetitem' : (('ptr', 'int'), 'int'), 'strsetitem' : (('ptr', 'int', 'int'), None), - 'getitem' : (('void', 'ptr', 'int'), 'int'), - 'setitem' : (('void', 'ptr', 'int', 'int'), None), - 'newlist' : (('void', 'varargs'), 'ptr'), - 'append' : (('void', 'ptr', 'int'), None), - 'insert' : (('void', 'ptr', 'int', 'int'), None), - 'pop' : (('void', 'ptr',), 'int'), - 'len' : (('void', 'ptr',), 'int'), - 'listnonzero' : (('void', 'ptr',), 'int'), + #'getitem' : (('void', 'ptr', 'int'), 'int'), + #'setitem' : (('void', 'ptr', 'int', 'int'), None), + #'newlist' : (('void', 'varargs'), 'ptr'), + #'append' : (('void', 'ptr', 'int'), None), + #'insert' : (('void', 'ptr', 'int', 'int'), None), + #'pop' : (('void', 'ptr',), 'int'), + #'len' : (('void', 'ptr',), 'int'), + #'listnonzero' : (('void', 'ptr',), 'int'), } # ____________________________________________________________ @@ -135,10 +135,11 @@ return '\n'.join(lines) class Operation(object): - def __init__(self, opnum): + def __init__(self, opnum, descr): self.opnum = opnum self.args = [] self.result = None + self.descr = descr self.livevars = [] # for guards only def __repr__(self): @@ -179,19 +180,16 @@ types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): - if len(lst) >= 2: - extraarg = lst[1] - else: - extraarg = None if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, memocast, extraarg)) + res_l.append('(%s)' % repr1(elem, tp, memocast)) else: - res_l.append(repr1(elem, tp, memocast, extraarg)) + res_l.append(repr1(elem, tp, memocast)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, memocast, extraarg): +def repr1(x, tp, memocast): if tp == "intorptr": - if extraarg % 2: + TYPE = lltype.typeOf(x) + if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc': tp = "ptr" else: tp = "int" @@ -221,8 +219,8 @@ elif tp == 'bool': assert x == 0 or x == 1 return str(bool(x)) - elif tp == 'fieldname': - return str(symbolic.TokenToField[x/2][1]) + #elif tp == 'fieldname': + # return str(symbolic.TokenToField[x/2][1]) else: raise NotImplementedError("tp = %s" % tp) @@ -250,9 +248,9 @@ _variables.append(v) return r -def compile_add(loop, opnum): +def compile_add(loop, opnum, descr): loop = _from_opaque(loop) - loop.operations.append(Operation(opnum)) + loop.operations.append(Operation(opnum, descr)) def compile_add_var(loop, intvar): loop = _from_opaque(loop) @@ -367,7 +365,8 @@ _stats.exec_jumps += 1 continue try: - result = self.execute_operation(op.opnum, args, verbose) + result = self.execute_operation(op.opnum, args, op.descr, + verbose) #verbose = self.verbose assert (result is None) == (op.result is None) if op.result is not None: @@ -405,7 +404,7 @@ self.failed_guard_op = op return op.failnum - def execute_operation(self, opnum, values, verbose): + def execute_operation(self, opnum, values, descr, verbose): """Execute a single operation. """ ophandler = self.OPHANDLERS[opnum] @@ -419,17 +418,13 @@ for i in range(len(values)): if isinstance(values[i], ComputedIntSymbolic): values[i] = values[i].compute_fn() - res = ophandler(self, *values) + res = ophandler(self, descr, *values) if verbose: argtypes, restype = TYPES[opname] if res is None: resdata = '' else: - if len(values) >= 2: - extraarg = values[1] - else: - extraarg = None - resdata = '-> ' + repr1(res, restype, self.memocast, extraarg) + resdata = '-> ' + repr1(res, restype, self.memocast) # fish the types log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, self.memocast), resdata)) @@ -456,13 +451,13 @@ name = 'do_' + opname.lower() try: impl = globals()[name] # do_arraylen_gc etc. - def op(self, *args): - return impl(*args) + def op(self, descr, *args): + return impl(descr, *args) # except KeyError: from pypy.jit.backend.llgraph import llimpl impl = getattr(executor, name) # do_int_add etc. - def _op_default_implementation(self, *args): + def _op_default_implementation(self, descr, *args): # for all operations implemented in execute.py boxedargs = [] for x in args: @@ -477,57 +472,15 @@ # Frame.OPHANDLERS[opnum] = op - def op_guard_true(self, value): + def op_guard_true(self, _, value): if not value: raise GuardFailed - def op_guard_false(self, value): + def op_guard_false(self, _, value): if value: raise GuardFailed - op_guard_nonzero = op_guard_true - op_guard_iszero = op_guard_false - - def op_guard_nonnull(self, ptr): - if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = cast_int_to_adr(self.memocast, ptr) - if not ptr: - raise GuardFailed - - def op_guard_isnull(self, ptr): - if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = cast_int_to_adr(self.memocast, ptr) - if ptr: - raise GuardFailed - - def op_guard_lt(self, value1, value2): - if value1 >= value2: - raise GuardFailed - - def op_guard_le(self, value1, value2): - if value1 > value2: - raise GuardFailed - - def op_guard_eq(self, value1, value2): - if value1 != value2: - raise GuardFailed - - def op_guard_ne(self, value1, value2): - if value1 == value2: - raise GuardFailed - - def op_guard_gt(self, value1, value2): - if value1 <= value2: - raise GuardFailed - - def op_guard_ge(self, value1, value2): - if value1 < value2: - raise GuardFailed - - op_guard_is = op_guard_eq - op_guard_isnot = op_guard_ne - - def op_guard_class(self, value, expected_class): + def op_guard_class(self, _, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( cast_int_to_adr(self.memocast, expected_class), @@ -535,23 +488,23 @@ if value.typeptr != expected_class: raise GuardFailed - def op_guard_value(self, value, expected_value): + def op_guard_value(self, _, value, expected_value): if value != expected_value: raise GuardFailed - def op_guard_nonvirtualized(self, value, expected_class, - for_accessing_field): - self.op_guard_class(value, expected_class) + def op_guard_nonvirtualized(self, for_accessing_field, + value, expected_class): + self.op_guard_class(-1, value, expected_class) if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control - def op_guard_no_exception(self): + def op_guard_no_exception(self, _): global _last_exception_handled _last_exception_handled = True if _last_exception: raise GuardFailed - def op_guard_exception(self, expected_exception): + def op_guard_exception(self, _, expected_exception): global _last_exception_handled _last_exception_handled = True expected_exception = llmemory.cast_adr_to_ptr( @@ -569,19 +522,19 @@ # ---------- # delegating to the builtins do_xxx() (done automatically for simple cases) - def op_getarrayitem_gc(self, array, arraydescr, index): + def op_getarrayitem_gc(self, arraydescr, array, index): if arraydescr & 1: return do_getarrayitem_gc_ptr(array, index) else: return do_getarrayitem_gc_int(array, index, self.memocast) - def op_getfield_gc(self, struct, fielddescr): + def op_getfield_gc(self, fielddescr, struct): if fielddescr & 1: return do_getfield_gc_ptr(struct, fielddescr) else: return do_getfield_gc_int(struct, fielddescr, self.memocast) - def op_getfield_raw(self, struct, fielddescr): + def op_getfield_raw(self, fielddescr, struct): if fielddescr & 1: return do_getfield_raw_ptr(struct, fielddescr) else: @@ -593,25 +546,25 @@ value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) return result - def op_setarrayitem_gc(self, array, arraydescr, index, newvalue): + def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): if arraydescr & 1: do_setarrayitem_gc_ptr(array, index, newvalue) else: do_setarrayitem_gc_int(array, index, newvalue, self.memocast) - def op_setfield_gc(self, struct, fielddescr, newvalue): + def op_setfield_gc(self, fielddescr, struct, newvalue): if fielddescr & 1: do_setfield_gc_ptr(struct, fielddescr, newvalue) else: do_setfield_gc_int(struct, fielddescr, newvalue, self.memocast) - def op_setfield_raw(self, struct, fielddescr, newvalue): + def op_setfield_raw(self, fielddescr, struct, newvalue): if fielddescr & 1: do_setfield_raw_ptr(struct, fielddescr, newvalue) else: do_setfield_raw_int(struct, fielddescr, newvalue, self.memocast) - def op_call(self, func, calldescr, *args): + def op_call(self, calldescr, func, *args): global _last_exception, _last_exception_handled _call_args[:] = args try: @@ -621,7 +574,7 @@ except LLException, e: _last_exception = e _last_exception_handled = False - if calldescr == -1: + if calldescr == sys.maxint: return None elif calldescr & 1: return lltype.nullptr(llmemory.GCREF) @@ -779,15 +732,15 @@ # ____________________________________________________________ -def do_arraylen_gc(array, ignored): +def do_arraylen_gc(arraydescr, array): array = array._obj.container return array.getlength() -def do_strlen(string): +def do_strlen(_, string): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return len(str.chars) -def do_strgetitem(string, index): +def do_strgetitem(_, string, index): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) return ord(str.chars[index]) @@ -873,11 +826,11 @@ newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_newstr(length): +def do_newstr(_, length): x = rstr.mallocstr(length) return cast_to_ptr(x) -def do_strsetitem(string, index, newvalue): +def do_strsetitem(_, string, index, newvalue): str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string) str.chars[index] = chr(newvalue) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Fri Mar 6 18:46:59 2009 @@ -2,6 +2,7 @@ Minimal-API wrapper around the llinterpreter to run operations. """ +import sys from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rpython.llinterp import LLInterpreter from pypy.jit.metainterp import history @@ -63,7 +64,7 @@ op._compiled = c op._opindex = j j += 1 - llimpl.compile_add(c, op.opnum) + llimpl.compile_add(c, op.opnum, op.descr) for x in op.args: if isinstance(x, history.Box): llimpl.compile_add_var(c, var2index[x]) @@ -214,7 +215,7 @@ @staticmethod def calldescrof(ARGS, RESULT): if RESULT is lltype.Void: - return -1 + return sys.maxint token = history.getkind(RESULT) if token == 'ptr': return 1 @@ -223,7 +224,7 @@ @staticmethod def typefor(fielddesc): - if fielddesc == -1: + if fielddesc == sys.maxint: return 'void' if fielddesc % 2: return 'ptr' @@ -247,32 +248,30 @@ # ---------- the backend-dependent operations ---------- - def do_arraylen_gc(self, args): + def do_arraylen_gc(self, args, arraydescr): array = args[0].getptr_base() - return history.BoxInt(llimpl.do_arraylen_gc(array, 0)) + return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array)) - def do_strlen(self, args): + def do_strlen(self, args, descr=0): string = args[0].getptr_base() - return history.BoxInt(llimpl.do_strlen(string)) + return history.BoxInt(llimpl.do_strlen(0, string)) - def do_strgetitem(self, args): + def do_strgetitem(self, args, descr=0): string = args[0].getptr_base() index = args[1].getint() - return history.BoxInt(llimpl.do_strgetitem(string, index)) + return history.BoxInt(llimpl.do_strgetitem(0, string, index)) - def do_getarrayitem_gc(self, args): + def do_getarrayitem_gc(self, args, arraydescr): array = args[0].getptr_base() - arraydescr = args[1].getint() - index = args[2].getint() + index = args[1].getint() if self.typefor(arraydescr) == 'ptr': return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) else: return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, self.memo_cast)) - def do_getfield_gc(self, args): + def do_getfield_gc(self, args, fielddescr): struct = args[0].getptr_base() - fielddescr = args[1].getint() if self.typefor(fielddescr) == 'ptr': return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, fielddescr)) @@ -281,9 +280,8 @@ fielddescr, self.memo_cast)) - def do_getfield_raw(self, args): + def do_getfield_raw(self, args, fielddescr): struct = self.cast_int_to_adr(args[0].getint()) - fielddescr = args[1].getint() if self.typefor(fielddescr) == 'ptr': return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, fielddescr)) @@ -292,71 +290,64 @@ fielddescr, self.memo_cast)) - def do_new(self, args): - size = args[0].getint() + def do_new(self, args, size): return history.BoxPtr(llimpl.do_new(size)) - def do_new_with_vtable(self, args): - size = args[0].getint() - vtable = args[1].getint() + def do_new_with_vtable(self, args, size): + vtable = args[0].getint() result = llimpl.do_new(size) llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable, vtable, self.memo_cast) return history.BoxPtr(result) - def do_new_array(self, args): - size = args[0].getint() - count = args[1].getint() + def do_new_array(self, args, size): + count = args[0].getint() return history.BoxPtr(llimpl.do_new_array(size, count)) - def do_setarrayitem_gc(self, args): + def do_setarrayitem_gc(self, args, arraydescr): array = args[0].getptr_base() - arraydescr = args[1].getint() - index = args[2].getint() + index = args[1].getint() if self.typefor(arraydescr) == 'ptr': - newvalue = args[3].getptr_base() + newvalue = args[2].getptr_base() llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) else: - newvalue = args[3].getint() + newvalue = args[2].getint() llimpl.do_setarrayitem_gc_int(array, index, newvalue, self.memo_cast) - def do_setfield_gc(self, args): + def do_setfield_gc(self, args, fielddescr): struct = args[0].getptr_base() - fielddescr = args[1].getint() if self.typefor(fielddescr) == 'ptr': - newvalue = args[2].getptr_base() + newvalue = args[1].getptr_base() llimpl.do_setfield_gc_ptr(struct, fielddescr, newvalue) else: - newvalue = args[2].getint() + newvalue = args[1].getint() llimpl.do_setfield_gc_int(struct, fielddescr, newvalue, self.memo_cast) - def do_setfield_raw(self, args): + def do_setfield_raw(self, args, fielddescr): struct = self.cast_int_to_adr(args[0].getint()) - fielddescr = args[1].getint() if self.typefor(fielddescr) == 'ptr': - newvalue = args[2].getptr_base() + newvalue = args[1].getptr_base() llimpl.do_setfield_raw_ptr(struct, fielddescr, newvalue) else: - newvalue = args[2].getint() + newvalue = args[1].getint() llimpl.do_setfield_raw_int(struct, fielddescr, newvalue, self.memo_cast) - def do_newstr(self, args): + def do_newstr(self, args, descr=0): length = args[0].getint() - return history.BoxPtr(llimpl.do_newstr(length)) + return history.BoxPtr(llimpl.do_newstr(0, length)) - def do_strsetitem(self, args): + def do_strsetitem(self, args, descr=0): string = args[0].getptr_base() index = args[1].getint() newvalue = args[2].getint() - llimpl.do_strsetitem(string, index, newvalue) + llimpl.do_strsetitem(0, string, index, newvalue) - def do_call(self, args): + def do_call(self, args, calldescr): func = args[0].getint() - calldescr = args[1].getint() - for arg in args[2:]: + for arg in args[1:]: if (isinstance(arg, history.BoxPtr) or isinstance(arg, history.ConstPtr)): llimpl.do_call_pushptr(arg.getptr_base()) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Mar 6 18:46:59 2009 @@ -133,25 +133,26 @@ cpu = CPU(None) # A = lltype.GcArray(lltype.Char) - descrbox_A = ConstInt(cpu.arraydescrof(A)) + descr_A = cpu.arraydescrof(A) a = lltype.malloc(A, 5) x = cpu.do_arraylen_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a))], + descr_A) assert x.value == 5 # a[2] = 'Y' x = cpu.do_getarrayitem_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A, - BoxInt(2)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), BoxInt(2)], + descr_A) assert x.value == ord('Y') # B = lltype.GcArray(lltype.Ptr(A)) - descrbox_B = ConstInt(cpu.arraydescrof(B)) + descr_B = cpu.arraydescrof(B) b = lltype.malloc(B, 4) b[3] = a x = cpu.do_getarrayitem_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, - BoxInt(3)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), BoxInt(3)], + descr_B) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # @@ -170,29 +171,28 @@ s = lltype.malloc(S) s.x = 'Z' x = cpu.do_getfield_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_x)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))], + descrfld_x) assert x.value == ord('Z') # cpu.do_setfield_gc( [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_x), - BoxInt(ord('4'))]) + BoxInt(ord('4'))], + descrfld_x) assert s.x == '4' # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a x = cpu.do_getfield_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_y)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))], + descrfld_y) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # s.y = lltype.nullptr(A) cpu.do_setfield_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_y), - x]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), x], + descrfld_y) assert s.y == a # RS = lltype.Struct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) @@ -200,58 +200,56 @@ rs = lltype.malloc(RS, immortal=True) rs.x = '?' x = cpu.do_getfield_raw( - [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_rx)]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs)))], + descrfld_rx) assert x.value == ord('?') # cpu.do_setfield_raw( [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_rx), - BoxInt(ord('!'))]) + BoxInt(ord('!'))], + descrfld_rx) assert rs.x == '!' # descrfld_ry = cpu.fielddescrof(RS, 'y') rs.y = a x = cpu.do_getfield_raw( - [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_ry)]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs)))], + descrfld_ry) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # rs.y = lltype.nullptr(A) cpu.do_setfield_raw( - [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_ry), - x]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), x], + descrfld_ry) assert rs.y == a # descrsize = cpu.sizeof(S) - x = cpu.do_new( - [BoxInt(descrsize)]) + x = cpu.do_new([], descrsize) assert isinstance(x, BoxPtr) x.getptr(lltype.Ptr(S)) # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) x = cpu.do_new_with_vtable( - [BoxInt(descrsize2), - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))], + descrsize2) assert isinstance(x, BoxPtr) assert x.getptr(rclass.OBJECTPTR).typeptr == vtable2 # arraydescr = cpu.arraydescrof(A) - x = cpu.do_new_array( - [BoxInt(arraydescr), BoxInt(7)]) + x = cpu.do_new_array([BoxInt(7)], arraydescr) assert isinstance(x, BoxPtr) assert len(x.getptr(lltype.Ptr(A))) == 7 # cpu.do_setarrayitem_gc( - [x, descrbox_A, BoxInt(5), BoxInt(ord('*'))]) + [x, BoxInt(5), BoxInt(ord('*'))], descr_A) assert x.getptr(lltype.Ptr(A))[5] == '*' # cpu.do_setarrayitem_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, - BoxInt(1), x]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), + BoxInt(1), x], + descr_B) assert b[1] == x.getptr(lltype.Ptr(A)) # x = cpu.do_newstr([BoxInt(5)]) @@ -272,8 +270,8 @@ calldescr = cpu.calldescrof([lltype.Char], lltype.Char) x = cpu.do_call( [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(func_ptr))), - ConstInt(calldescr), - BoxInt(ord('A'))]) + BoxInt(ord('A'))], + calldescr) assert x.value == ord('B') def test_executor(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Mar 6 18:46:59 2009 @@ -498,10 +498,10 @@ # store the vtable as an address -- that's fine, because the # GC doesn't need to follow them self.emit('new_with_vtable', - self.const_position(self.cpu.sizeof(STRUCT)), + self.cpu.sizeof(STRUCT), self.const_position(vtable)) else: - self.emit('new', self.const_position(self.cpu.sizeof(STRUCT))) + self.emit('new', self.cpu.sizeof(STRUCT)) self.register_var(op.result) def serialize_op_malloc_varsize(self, op): @@ -513,7 +513,7 @@ ARRAY = op.args[0].value arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('new_array') - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(op.args[2])) self.register_var(op.result) @@ -540,7 +540,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(self.const_position(offset)) + self.emit(offset) self.register_var(op.result) #self._eventualy_builtin(op.result) @@ -558,7 +558,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(self.const_position(offset)) + self.emit(offset) self.emit(self.var_position(v_value)) def is_typeptr_getset(self, op): @@ -577,7 +577,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('getarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(op.args[1])) self.register_var(op.result) @@ -587,7 +587,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('setarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(op.args[1])) self.emit(self.var_position(op.args[2])) @@ -668,13 +668,12 @@ def handle_residual_call(self, op): self.minimize_variables() - args = [x for x in op.args[1:] if x.concretetype is not lltype.Void] + args = [x for x in op.args if x.concretetype is not lltype.Void] argtypes = [v.concretetype for v in args] resulttype = op.result.concretetype calldescr = self.cpu.calldescrof(argtypes, resulttype) self.emit('residual_call_%s' % getkind(resulttype)) - self.emit(self.var_position(op.args[0])) - self.emit(self.const_position(calldescr)) + self.emit(calldescr) self.emit_varargs(args) self.register_var(op.result) @@ -720,9 +719,8 @@ opname = 'residual_call_%s' % getkind(resulttype) calldescr = self.cpu.calldescrof(argtypes, resulttype) self.emit(opname) - self.emit(self.var_position(c_func)) - self.emit(self.const_position(calldescr)) - self.emit_varargs(args) + self.emit(calldescr) + self.emit_varargs([c_func] + args) self.register_var(op.result) def handle_list_call(self, op, oopspec_name, args, TP): @@ -745,7 +743,7 @@ v_default.value != TP.TO.OF._defl()): return False # variable or non-null initial value self.emit('new_array') - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(args[0])) self.register_var(op.result) return True @@ -764,7 +762,7 @@ return False self.emit('setarrayitem_gc') self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(index)) self.emit(self.var_position(args[2])) self.register_var(op.result) @@ -774,7 +772,7 @@ oopspec_name == 'list.len_foldable'): self.emit('arraylen_gc') self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.register_var(op.result) return True # @@ -786,7 +784,7 @@ return False self.emit(opname) self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(index)) self.register_var(op.result) return True @@ -811,7 +809,7 @@ else: self.emit('check_neg_index') self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(arraydescr) self.emit(self.var_position(args[1])) v_posindex = Variable('posindex') v_posindex.concretetype = lltype.Signed @@ -853,7 +851,7 @@ self.emit('guard_nonvirtualized') self.emit(self.var_position(op.args[0])) self.emit(self.get_position(virtualizabledesc)) - self.emit(self.const_position(guard_field)) + self.emit(guard_field) # ---------- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Fri Mar 6 18:46:59 2009 @@ -13,34 +13,34 @@ # ____________________________________________________________ -def do_int_add(cpu, args): +def do_int_add(cpu, args, descr=0): return ConstInt(args[0].getint() + args[1].getint()) -def do_int_sub(cpu, args): +def do_int_sub(cpu, args, descr=0): return ConstInt(args[0].getint() - args[1].getint()) -def do_int_mul(cpu, args): +def do_int_mul(cpu, args, descr=0): return ConstInt(args[0].getint() * args[1].getint()) -def do_int_floordiv(cpu, args): +def do_int_floordiv(cpu, args, descr=0): return ConstInt(args[0].getint() // args[1].getint()) -def do_int_mod(cpu, args): +def do_int_mod(cpu, args, descr=0): return ConstInt(args[0].getint() % args[1].getint()) -def do_int_and(cpu, args): +def do_int_and(cpu, args, descr=0): return ConstInt(args[0].getint() & args[1].getint()) -def do_int_or(cpu, args): +def do_int_or(cpu, args, descr=0): return ConstInt(args[0].getint() | args[1].getint()) -def do_int_xor(cpu, args): +def do_int_xor(cpu, args, descr=0): return ConstInt(args[0].getint() ^ args[1].getint()) -def do_int_rshift(cpu, args): +def do_int_rshift(cpu, args, descr=0): return ConstInt(args[0].getint() >> args[1].getint()) -def do_int_lshift(cpu, args): +def do_int_lshift(cpu, args, descr=0): return ConstInt(args[0].getint() << args[1].getint()) do_uint_add = do_int_add @@ -49,63 +49,63 @@ # ---------- -def do_int_lt(cpu, args): +def do_int_lt(cpu, args, descr=0): return ConstInt(args[0].getint() < args[1].getint()) -def do_int_le(cpu, args): +def do_int_le(cpu, args, descr=0): return ConstInt(args[0].getint() <= args[1].getint()) -def do_int_eq(cpu, args): +def do_int_eq(cpu, args, descr=0): return ConstInt(args[0].getint() == args[1].getint()) -def do_int_ne(cpu, args): +def do_int_ne(cpu, args, descr=0): return ConstInt(args[0].getint() != args[1].getint()) -def do_int_gt(cpu, args): +def do_int_gt(cpu, args, descr=0): return ConstInt(args[0].getint() > args[1].getint()) -def do_int_ge(cpu, args): +def do_int_ge(cpu, args, descr=0): return ConstInt(args[0].getint() >= args[1].getint()) -def do_uint_lt(cpu, args): +def do_uint_lt(cpu, args, descr=0): return ConstInt(r_uint(args[0].getint()) < r_uint(args[1].getint())) -def do_uint_le(cpu, args): +def do_uint_le(cpu, args, descr=0): return ConstInt(r_uint(args[0].getint()) <= r_uint(args[1].getint())) do_uint_eq = do_int_eq do_uint_ne = do_int_ne -def do_uint_gt(cpu, args): +def do_uint_gt(cpu, args, descr=0): return ConstInt(r_uint(args[0].getint()) > r_uint(args[1].getint())) -def do_uint_ge(cpu, args): +def do_uint_ge(cpu, args, descr=0): return ConstInt(r_uint(args[0].getint()) >= r_uint(args[1].getint())) # ---------- -def do_int_is_true(cpu, args): +def do_int_is_true(cpu, args, descr=0): return ConstInt(bool(args[0].getint())) -def do_int_neg(cpu, args): +def do_int_neg(cpu, args, descr=0): return ConstInt(-args[0].getint()) -def do_int_invert(cpu, args): +def do_int_invert(cpu, args, descr=0): return ConstInt(~args[0].getint()) -def do_bool_not(cpu, args): +def do_bool_not(cpu, args, descr=0): return ConstInt(not args[0].getint()) -def do_oononnull(cpu, args): +def do_oononnull(cpu, args, descr=0): return ConstInt(bool(args[0].getptr_base())) -def do_ooisnull(cpu, args): +def do_ooisnull(cpu, args, descr=0): return ConstInt(not args[0].getptr_base()) -def do_oois(cpu, args): +def do_oois(cpu, args, descr=0): return ConstInt(args[0].getptr_base() == args[1].getptr_base()) -def do_ooisnot(cpu, args): +def do_ooisnot(cpu, args, descr=0): return ConstInt(args[0].getptr_base() != args[1].getptr_base()) # ---------- @@ -129,7 +129,7 @@ # ---------- -def do_int_add_ovf(cpu, args): +def do_int_add_ovf(cpu, args, descr=0): x = args[0].getint() y = args[1].getint() try: @@ -139,7 +139,7 @@ z = 0 return BoxInt(z) -def do_int_sub_ovf(cpu, args): +def do_int_sub_ovf(cpu, args, descr=0): x = args[0].getint() y = args[1].getint() try: @@ -149,7 +149,7 @@ z = 0 return BoxInt(z) -def do_int_mul_ovf(cpu, args): +def do_int_mul_ovf(cpu, args, descr=0): x = args[0].getint() y = args[1].getint() try: @@ -159,7 +159,7 @@ z = 0 return BoxInt(z) -def do_int_neg_ovf(cpu, args): +def do_int_neg_ovf(cpu, args, descr=0): x = args[0].getint() try: z = ovfcheck(-x) @@ -168,7 +168,7 @@ z = 0 return BoxInt(z) -def do_int_mod_ovf(cpu, args): +def do_int_mod_ovf(cpu, args, descr=0): x = args[0].getint() y = args[1].getint() try: @@ -206,7 +206,7 @@ return cpu._execute_list[opnum] get_execute_function._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, argboxes): +def execute(cpu, opnum, argboxes, descr=0): func = get_execute_function(cpu, opnum) - return func(cpu, argboxes) + return func(cpu, argboxes, descr) execute._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Fri Mar 6 18:46:59 2009 @@ -366,13 +366,13 @@ self.operations = [] class History(RunningMatcher): - def record(self, opnum, argboxes, resbox): - op = ResOperation(opnum, argboxes, resbox) + def record(self, opnum, argboxes, resbox, descr=0): + op = ResOperation(opnum, argboxes, resbox, descr) self.operations.append(op) return op class BlackHole(RunningMatcher): - def record(self, opnum, argboxes, resbox): + def record(self, opnum, argboxes, resbox, descr=0): return None def mp_eq(greenkey1, greenkey2): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 18:46:59 2009 @@ -67,7 +67,7 @@ ld = instnode.cls.source assert isinstance(ld, FixedList) alloc_offset = len(self.list_allocations) - ad = ConstInt(ld.arraydescr) + ad = ld.arraydescr if instnode.cursize == -1: # fish fish fish instnode.cursize = executor.execute(cpu, rop.ARRAYLEN_GC, @@ -87,7 +87,7 @@ ld = instnode.cls.source x = (alloc_offset + 1) << 16 assert isinstance(ld, FixedList) - self.setitems.append((x, ConstInt(ld.arraydescr), ofs, num)) + self.setitems.append((x, ld.arraydescr, ofs, num)) else: self.setfields.append((alloc_offset, ofs, num)) elif virtualized: @@ -313,8 +313,8 @@ def find_nodes_getarrayitem(self, op): instnode = self.getnode(op.args[0]) if instnode.cls is None: - instnode.cls = InstanceNode(FixedList(op.args[1].getint())) - fieldbox = op.args[2] + instnode.cls = InstanceNode(FixedList(op.descr)) + fieldbox = op.args[1] if self.getnode(fieldbox).const: item = self.getsource(fieldbox).getint() assert item >= 0 # XXX @@ -348,17 +348,17 @@ elif opnum == rop.NEW_WITH_VTABLE: box = op.result instnode = InstanceNode(box, escaped=False) - instnode.cls = InstanceNode(op.args[1], const=True) + instnode.cls = InstanceNode(op.args[0], const=True) self.nodes[box] = instnode self.first_escaping_op = False continue elif opnum == rop.NEW_ARRAY: box = op.result instnode = InstanceNode(box, escaped=False) - instnode.cls = InstanceNode(FixedList(op.args[0].getint())) + instnode.cls = InstanceNode(FixedList(op.descr)) self.nodes[box] = instnode - if self.getnode(op.args[1]).const: - instnode.cursize = op.args[1].getint() + if self.getnode(op.args[0]).const: + instnode.cursize = op.args[0].getint() else: instnode.escaped = True continue @@ -393,45 +393,39 @@ continue elif opnum == rop.GETARRAYITEM_GC_PURE: instnode = self.getnode(op.args[0]) - if not instnode.const or not self.getnode(op.args[2]).const: + if not instnode.const or not self.getnode(op.args[1]).const: self.find_nodes_getarrayitem(op) continue elif opnum == rop.SETARRAYITEM_GC: instnode = self.getnode(op.args[0]) if instnode.cls is None: - instnode.cls = InstanceNode(FixedList(op.args[1].getint())) - fieldbox = op.args[2] + instnode.cls = InstanceNode(FixedList(op.descr)) + fieldbox = op.args[1] if self.getnode(fieldbox).const: item = self.getsource(fieldbox).getint() assert item >= 0 # XXX self.find_nodes_setfield(instnode, item, - self.getnode(op.args[3])) + self.getnode(op.args[2])) else: instnode.escaped = True self.dependency_graph.append((instnode, - self.getnode(op.args[3]))) + self.getnode(op.args[2]))) continue elif opnum == rop.SETFIELD_GC: instnode = self.getnode(op.args[0]) - fieldbox = op.args[1] - assert isinstance(fieldbox, ConstInt) - field = fieldbox.getint() + field = op.descr self.find_nodes_setfield(instnode, field, - self.getnode(op.args[2])) + self.getnode(op.args[1])) continue elif opnum == rop.GETFIELD_GC: instnode = self.getnode(op.args[0]) - fieldbox = op.args[1] - assert isinstance(fieldbox, ConstInt) - field = fieldbox.getint() + field = op.descr box = op.result self.find_nodes_getfield(instnode, field, box) continue elif opnum == rop.GETFIELD_GC_PURE: instnode = self.getnode(op.args[0]) - fieldbox = op.args[1] - assert isinstance(fieldbox, ConstInt) - field = fieldbox.getint() + field = op.descr if not instnode.const: box = op.result self.find_nodes_getfield(instnode, field, box) @@ -631,7 +625,7 @@ isinstance(node.cls.source, FixedList)): ld = node.cls.source assert isinstance(ld, FixedList) - ad = ConstInt(ld.arraydescr) + ad = ld.arraydescr storage.setitems.append((index, ad, ofs, fieldindex)) else: storage.setfields.append((index, ofs, fieldindex)) @@ -788,27 +782,25 @@ continue elif opnum == rop.GETFIELD_GC: instnode = self.nodes[op.args[0]] - ofs = op.args[1].getint() - if self.optimize_getfield(instnode, ofs, op.result): + if self.optimize_getfield(instnode, op.descr, op.result): continue # otherwise we need this getfield, but it does not # invalidate caches elif opnum == rop.GETFIELD_GC_PURE: instnode = self.nodes[op.args[0]] if not instnode.const: - ofs = op.args[1].getint() - if self.optimize_getfield(instnode, ofs, op.result): + if self.optimize_getfield(instnode, op.descr, op.result): continue elif opnum == rop.GETARRAYITEM_GC: instnode = self.nodes[op.args[0]] - ofsbox = self.getsource(op.args[2]) + ofsbox = self.getsource(op.args[1]) if isinstance(ofsbox, ConstInt): ofs = ofsbox.getint() if self.optimize_getfield(instnode, ofs, op.result): continue elif opnum == rop.GETARRAYITEM_GC_PURE: instnode = self.nodes[op.args[0]] - ofsbox = self.getsource(op.args[2]) + ofsbox = self.getsource(op.args[1]) if not instnode.const: if isinstance(ofsbox, ConstInt): ofs = ofsbox.getint() @@ -833,7 +825,7 @@ instnode = self.nodes[op.result] if not instnode.escaped: instnode.virtual = True - instnode.cursize = op.args[1].getint() + instnode.cursize = op.args[0].getint() continue ## elif opname == 'newlist': ## instnode = self.nodes[op.results[0]] @@ -877,19 +869,19 @@ ## continue elif opnum == rop.SETFIELD_GC: instnode = self.nodes[op.args[0]] - valuenode = self.nodes[op.args[2]] - ofs = op.args[1].getint() - self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) + valuenode = self.nodes[op.args[1]] + ofs = op.descr + self.optimize_setfield(instnode, ofs, valuenode, op.args[1]) continue elif opnum == rop.SETARRAYITEM_GC: instnode = self.nodes[op.args[0]] if instnode.cls is None: - instnode.cls = InstanceNode(FixedList(op.args[1].getint())) - ofsbox = self.getsource(op.args[2]) + instnode.cls = InstanceNode(FixedList(op.descr)) + ofsbox = self.getsource(op.args[1]) if isinstance(ofsbox, ConstInt): ofs = ofsbox.getint() - valuenode = self.getnode(op.args[3]) - self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) + valuenode = self.getnode(op.args[2]) + self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue ## elif opname == 'setitem': ## instnode = self.nodes[op.args[1]] @@ -966,13 +958,12 @@ isinstance(node.cls.source, FixedList)): ld = node.cls.source assert isinstance(ld, FixedList) - ad = ConstInt(ld.arraydescr) newoperations.append(ResOperation(rop.SETARRAYITEM_GC, - [node.source, ad, ConstInt(ofs), valuenode.source], - None)) + [node.source, ConstInt(ofs), valuenode.source], + None, ld.arraydescr)) else: newoperations.append(ResOperation(rop.SETFIELD_GC, - [node.source, ConstInt(ofs), valuenode.source], None)) + [node.source, valuenode.source], None, ofs)) node.dirtyfields = {} node.cleanfields = {} @@ -1023,17 +1014,17 @@ for vtable in storage.allocations: if metainterp.cpu.translate_support_code: vtable_addr = metainterp.cpu.cast_int_to_adr(vtable) - sizebox = ConstInt(metainterp.class_sizes[vtable_addr]) + size = metainterp.class_sizes[vtable_addr] else: - sizebox = ConstInt(metainterp.class_sizes[vtable]) + size = metainterp.class_sizes[vtable] vtablebox = ConstInt(vtable) instbox = metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - [sizebox, vtablebox]) + [vtablebox], size) allocated_boxes.append(instbox) for ad, lgt in storage.list_allocations: sizebox = ConstInt(lgt) listbox = metainterp.execute_and_record(rop.NEW_ARRAY, - [ad, sizebox]) + [sizebox], ad) allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: fieldbox = box_from_index(allocated_boxes, allocated_lists, @@ -1042,14 +1033,14 @@ boxes_from_frame, index_in_alloc) metainterp.execute_and_record(rop.SETFIELD_GC, - [box, ConstInt(ofs), fieldbox]) + [box, fieldbox], ofs) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) metainterp.execute_and_record(rop.SETARRAYITEM_GC, - [box, ad, ConstInt(ofs), itembox]) + [box, ConstInt(ofs), itembox], ad) ## if storage.setitems: ## #history.execute_and_record('guard_no_exception', [], 'void', False) ## # XXX this needs to check for exceptions somehow Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 18:46:59 2009 @@ -310,37 +310,38 @@ except KeyError: pass - @arguments("constbox") - def opimpl_new(self, sizebox): - self.execute(rop.NEW, [sizebox]) - - @arguments("constbox", "constbox") - def opimpl_new_with_vtable(self, sizebox, vtablebox): - self.execute(rop.NEW_WITH_VTABLE, [sizebox, vtablebox]) - - @arguments("constbox", "box") - def opimpl_new_array(self, itemsizebox, countbox): - self.execute(rop.NEW_ARRAY, [itemsizebox, countbox]) + @arguments("int") + def opimpl_new(self, size): + self.execute(rop.NEW, [], descr=size) + + @arguments("int", "constbox") + def opimpl_new_with_vtable(self, size, vtablebox): + self.execute(rop.NEW_WITH_VTABLE, [vtablebox], descr=size) + + @arguments("int", "box") + def opimpl_new_array(self, itemsize, countbox): + self.execute(rop.NEW_ARRAY, [countbox], descr=itemsize) - @arguments("box", "constbox", "box") + @arguments("box", "int", "box") def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): - self.execute(rop.GETARRAYITEM_GC, [arraybox, arraydesc, indexbox]) + self.execute(rop.GETARRAYITEM_GC, [arraybox, indexbox], + descr=arraydesc) - @arguments("box", "constbox", "box") + @arguments("box", "int", "box") def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): - self.execute(rop.GETARRAYITEM_GC_PURE, - [arraybox, arraydesc, indexbox]) + self.execute(rop.GETARRAYITEM_GC_PURE, [arraybox, indexbox], + descr=arraydesc) - @arguments("box", "constbox", "box", "box") + @arguments("box", "int", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): - self.execute(rop.SETARRAYITEM_GC, [arraybox, arraydesc, - indexbox, itembox]) + self.execute(rop.SETARRAYITEM_GC, [arraybox, indexbox, itembox], + descr=arraydesc) - @arguments("box", "constbox") + @arguments("box", "int") def opimpl_arraylen_gc(self, arraybox, arraydesc): - self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc]) + self.execute(rop.ARRAYLEN_GC, [arraybox], descr=arraydesc) - @arguments("orgpc", "box", "constbox", "box") + @arguments("orgpc", "box", "int", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): negbox = self.metainterp.execute_and_record( rop.INT_LT, [indexbox, ConstInt(0)]) @@ -348,7 +349,7 @@ if negbox.getint(): # the index is < 0; add the array length to it lenbox = self.metainterp.execute_and_record( - rop.ARRAYLEN_GC, [arraybox, arraydesc]) + rop.ARRAYLEN_GC, [arraybox], descr=arraydesc) indexbox = self.metainterp.execute_and_record( rop.INT_ADD, [indexbox, lenbox]) self.make_result_box(indexbox) @@ -370,25 +371,25 @@ self.execute(rop.OOISNOT, [box1, box2]) - @arguments("box", "constbox") + @arguments("box", "int") def opimpl_getfield_gc(self, box, fielddesc): - self.execute(rop.GETFIELD_GC, [box, fielddesc]) - @arguments("box", "constbox") + self.execute(rop.GETFIELD_GC, [box], descr=fielddesc) + @arguments("box", "int") def opimpl_getfield_gc_pure(self, box, fielddesc): - self.execute(rop.GETFIELD_GC_PURE, [box, fielddesc]) - @arguments("box", "constbox", "box") + self.execute(rop.GETFIELD_GC_PURE, [box], descr=fielddesc) + @arguments("box", "int", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute(rop.SETFIELD_GC, [box, fielddesc, valuebox]) + self.execute(rop.SETFIELD_GC, [box, valuebox], descr=fielddesc) - @arguments("box", "constbox") + @arguments("box", "int") def opimpl_getfield_raw(self, box, fielddesc): - self.execute(rop.GETFIELD_RAW, [box, fielddesc]) - @arguments("box", "constbox") + self.execute(rop.GETFIELD_RAW, [box], descr=fielddesc) + @arguments("box", "int") def opimpl_getfield_raw_pure(self, box, fielddesc): - self.execute(rop.GETFIELD_RAW_PURE, [box, fielddesc]) - @arguments("box", "constbox", "box") + self.execute(rop.GETFIELD_RAW_PURE, [box], descr=fielddesc) + @arguments("box", "int", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute(rop.SETFIELD_RAW, [box, fielddesc, valuebox]) + self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc) @arguments("bytecode", "varargs") def opimpl_call(self, callee, varargs): @@ -396,25 +397,24 @@ f.setup_call(varargs) return True - @arguments("box", "constbox", "varargs") - def opimpl_residual_call_int(self, funcbox, calldescr, varargs): - args = [funcbox, calldescr] + varargs - return self.execute_with_exc(rop.CALL, args, returnsBoxInt) - - @arguments("box", "constbox", "varargs") - def opimpl_residual_call_ptr(self, funcbox, calldescr, varargs): - args = [funcbox, calldescr] + varargs - return self.execute_with_exc(rop.CALL, args, returnsBoxPtr) - - @arguments("box", "constbox", "varargs") - def opimpl_residual_call_void(self, funcbox, calldescr, varargs): - args = [funcbox, calldescr] + varargs - return self.execute_with_exc(rop.CALL, args, returnsNone) - - @arguments("box", "constbox", "varargs") - def opimpl_residual_call_pure(self, funcbox, calldescr, varargs): - args = [funcbox, calldescr] + varargs - self.execute(rop.CALL_PURE, args) + @arguments("int", "varargs") + def opimpl_residual_call_int(self, calldescr, varargs): + return self.execute_with_exc(rop.CALL, varargs, returnsBoxInt, + descr=calldescr) + + @arguments("int", "varargs") + def opimpl_residual_call_ptr(self, calldescr, varargs): + return self.execute_with_exc(rop.CALL, varargs, returnsBoxPtr, + descr=calldescr) + + @arguments("int", "varargs") + def opimpl_residual_call_void(self, calldescr, varargs): + return self.execute_with_exc(rop.CALL, varargs, returnsNone, + descr=calldescr) + + @arguments("int", "varargs") + def opimpl_residual_call_pure(self, calldescr, varargs): + self.execute(rop.CALL_PURE, varargs, descr=calldescr) ## @arguments("fixedlist", "box", "box") ## def opimpl_list_getitem(self, descr, listbox, indexbox): @@ -513,13 +513,14 @@ ## 'len', [builtin.len_func, box], 'int') ## self.generate_guard(pc, "guard_len", box, [intbox]) - @arguments("orgpc", "box", "virtualizabledesc", "constbox") + @arguments("orgpc", "box", "virtualizabledesc", "int") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) op = self.generate_guard(pc, rop.GUARD_NONVIRTUALIZED, box, - [clsbox, guard_field]) + [clsbox]) if op: op.vdesc = vdesc + op.descr = guard_field @arguments("box") def opimpl_keepalive(self, box): @@ -653,15 +654,16 @@ cls = llmemory.cast_ptr_to_adr(obj.typeptr) return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) - def execute(self, opnum, argboxes): - resbox = self.metainterp.execute_and_record(opnum, argboxes) + def execute(self, opnum, argboxes, descr=0): + resbox = self.metainterp.execute_and_record(opnum, argboxes, descr) if resbox is not None: self.make_result_box(resbox) execute._annspecialcase_ = 'specialize:arg(1)' - def execute_with_exc(self, opnum, argboxes, makeresbox): + def execute_with_exc(self, opnum, argboxes, makeresbox, descr=0): try: - resbox = executor.execute(self.metainterp.cpu, opnum, argboxes) + resbox = executor.execute(self.metainterp.cpu, opnum, argboxes, + descr) except Exception, e: if not we_are_translated(): if not isinstance(e, LLException): @@ -678,7 +680,7 @@ etype = lltype.nullptr(rclass.OBJECT_VTABLE) evalue = lltype.nullptr(rclass.OBJECT) # record the operation in the history - self.metainterp.history.record(opnum, argboxes, resbox) + self.metainterp.history.record(opnum, argboxes, resbox, descr) if resbox is not None: self.make_result_box(resbox) type_as_int = self.metainterp.cpu.cast_adr_to_int( @@ -765,9 +767,9 @@ return False return True - def execute_and_record(self, opnum, argboxes): + def execute_and_record(self, opnum, argboxes, descr=0): # execute the operation first - resbox = executor.execute(self.cpu, opnum, argboxes) + resbox = executor.execute(self.cpu, opnum, argboxes, descr) # check if the operation can be constant-folded away canfold = False if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST: @@ -782,7 +784,7 @@ assert resbox is None or isinstance(resbox, Box) # record the operation if not constant-folded away if not canfold: - self.history.record(opnum, argboxes, resbox) + self.history.record(opnum, argboxes, resbox, descr) return resbox execute_and_record._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Fri Mar 6 18:46:59 2009 @@ -17,12 +17,16 @@ # for 'guard_nonvirtualizable' vdesc = None - def __init__(self, opnum, args, result): + def __init__(self, opnum, args, result, descr=0): assert isinstance(opnum, int) self.opnum = opnum self.args = list(args) assert not isinstance(result, list) self.result = result + # for 'call', 'new', 'getfield_gc'...: the descr is a number provided + # by the backend holding details about the type of the operation + assert isinstance(descr, int) + self.descr = descr def __repr__(self): if self.result is not None: @@ -36,7 +40,7 @@ return result def clone(self): - op = ResOperation(self.opnum, self.args, self.result) + op = ResOperation(self.opnum, self.args, self.result, self.descr) op.specnodes = self.specnodes op.key = self.key return op Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Fri Mar 6 18:46:59 2009 @@ -127,7 +127,7 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox, ConstInt(ofs)]) + [valuebox], ofs) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): @@ -163,7 +163,7 @@ else: box = subspecnode.box.clonebox() oplist.append(ResOperation(rop.GETFIELD_GC, - [instnode.source, ConstInt(ofs)], box)) + [instnode.source], box, ofs)) newboxlist.append(box) class DelayedFixedListSpecNode(DelayedSpecNode): @@ -176,7 +176,7 @@ newboxlist.append(instnode.source) cls = self.known_class assert isinstance(cls, FixedList) - ad = ConstInt(cls.arraydescr) + arraydescr = cls.arraydescr for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) if oplist is None: @@ -188,7 +188,7 @@ else: box = subspecnode.box.clonebox() oplist.append(ResOperation(rop.GETARRAYITEM_GC, - [instnode.source, ad, ConstInt(ofs)], box)) + [instnode.source, ConstInt(ofs)], box, arraydescr)) newboxlist.append(box) def extract_runtime_data(self, cpu, valuebox, resultlist): @@ -199,10 +199,9 @@ cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr - ad = ConstInt(arraydescr) for ofs, subspecnode in self.fields: fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ad, ConstInt(ofs)]) + [valuebox, ConstInt(ofs)], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualizableSpecNode(VirtualizedSpecNode): @@ -248,7 +247,7 @@ for ofs, subspecnode in self.fields: cls = self.known_class assert isinstance(cls, FixedList) - ad = ConstInt(cls.arraydescr) + arraydescr = cls.arraydescr fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ad, ConstInt(ofs)]) + [valuebox, ConstInt(ofs)], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Fri Mar 6 18:46:59 2009 @@ -18,13 +18,13 @@ l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lst)) e0 = BoxInt(0) e1 = BoxInt(0) - ad = ConstInt(cpu.arraydescrof(TP)) + ad = cpu.arraydescrof(TP) ops = [ ResOperation(rop.MERGE_POINT, [l], None), - ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e0), - ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e0], None), - ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e1), - ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e1], None), + ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e0, ad), + ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e0], None, ad), + ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e1, ad), + ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e1], None, ad), ResOperation(rop.JUMP, [l], None), ] @@ -48,7 +48,7 @@ spec.optimize_loop(None) equaloplists(spec.loop.operations, [ ResOperation(rop.MERGE_POINT, [A.l, A.e0], None), - ResOperation(rop.SETARRAYITEM_GC, [A.l, A.ad, ConstInt(0), A.e0], None), + ResOperation(rop.SETARRAYITEM_GC, [A.l, ConstInt(0), A.e0], None, A.ad), ResOperation(rop.JUMP, [A.l, A.e0], None) ]) @@ -60,13 +60,13 @@ e3 = BoxInt(0) ops = [ ResOperation(rop.MERGE_POINT, [l], None), - ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e0), + ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e0, ad), ResOperation(rop.INT_ADD, [e0, ConstInt(1)], e1), - ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e1], None), + ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e1], None, ad), ResOperation(-123, [e1], None), - ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e2), + ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e2, ad), ResOperation(rop.INT_ADD, [e2, ConstInt(1)], e3), - ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e3], None), + ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e3], None, ad), ResOperation(rop.JUMP, [l], None), ] @@ -78,11 +78,11 @@ equaloplists(spec.loop.operations, [ ResOperation(rop.MERGE_POINT, [B.l, B.e0], None), ResOperation(rop.INT_ADD, [B.e0, ConstInt(1)], B.e1), - ResOperation(rop.SETARRAYITEM_GC, [B.l, B.ad, ConstInt(0), B.e1], None), + ResOperation(rop.SETARRAYITEM_GC, [B.l, ConstInt(0), B.e1], None, B.ad), ResOperation(-123, [B.e1], None), - ResOperation(rop.GETARRAYITEM_GC, [B.l, B.ad, ConstInt(0)], B.e2), + ResOperation(rop.GETARRAYITEM_GC, [B.l, ConstInt(0)], B.e2, B.ad), ResOperation(rop.INT_ADD, [B.e2, ConstInt(1)], B.e3), - ResOperation(rop.SETARRAYITEM_GC, [B.l, B.ad, ConstInt(0), B.e3], None), + ResOperation(rop.SETARRAYITEM_GC, [B.l, ConstInt(0), B.e3], None, B.ad), ResOperation(rop.JUMP, [B.l, B.e3], None), ]) @@ -94,13 +94,13 @@ e2 = BoxInt(0) ops = [ ResOperation(rop.MERGE_POINT, [l], None), - ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e0), + ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e0, ad), ResOperation(rop.INT_ADD, [e0, ConstInt(1)], e1), - ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e1], None), + ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e1], None, ad), ResOperation(-123, [e1], None), - ResOperation(rop.GETARRAYITEM_GC, [l, ad, ConstInt(0)], e2), + ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e2, ad), ResOperation(rop.INT_ADD, [e2, ConstInt(1)], e3), - ResOperation(rop.SETARRAYITEM_GC, [l, ad, ConstInt(0), e3], None), + ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e3], None, ad), ResOperation(rop.JUMP, [l], None), ] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Mar 6 18:46:59 2009 @@ -63,18 +63,19 @@ for x, y in zip(op1.args, op2.args): assert x == y or y == x # for ANY object :-( assert op1.result == op2.result + assert op1.descr == op2.descr assert len(oplist1) == len(oplist2) print '-'*57 #finally: # Box._extended_display = saved return True -def ResOperation(opname, args, result): +def ResOperation(opname, args, result, descr=0): if opname == 'escape': opnum = -123 # random number not in the list else: opnum = getattr(rop, opname.upper()) - return resoperation.ResOperation(opnum, args, result) + return resoperation.ResOperation(opnum, args, result, descr) # ____________________________________________________________ @@ -82,7 +83,6 @@ ofs_next = runner.CPU.fielddescrof(NODE, 'next') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) - sizebox = ConstInt(size_of_node) # startnode = lltype.malloc(NODE) startnode.value = 20 @@ -97,14 +97,13 @@ sum2 = BoxInt(0 + startnode.value) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [sizebox, - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), ResOperation('jump', [sum2, n2], None), ] @@ -148,15 +147,14 @@ locals().update(A.__dict__) # :-) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('escape', [n1], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), ResOperation('escape', [n2], None), # <== escaping ResOperation('jump', [sum2, n2], None), ] @@ -188,13 +186,12 @@ ResOperation('merge_point', [B.sum, B.n1], None), # guard_class is gone ResOperation('escape', [B.n1], None), - ResOperation('getfield_gc', [B.n1, ConstInt(B.ofs_value)], B.v), + ResOperation('getfield_gc', [B.n1], B.v, B.ofs_value), ResOperation('int_sub', [B.v, ConstInt(1)], B.v2), ResOperation('int_add', [B.sum, B.v], B.sum2), - ResOperation('new_with_vtable', [ConstInt(B.size_of_node), - ConstAddr(node_vtable, cpu)], B.n2), - ResOperation('setfield_gc', [B.n2, ConstInt(B.ofs_value), B.v2], - None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], B.n2, + B.size_of_node), + ResOperation('setfield_gc', [B.n2, B.v2], None, B.ofs_value), ResOperation('escape', [B.n2], None), # <== escaping ResOperation('jump', [B.sum2, B.n2], None), ]) @@ -205,16 +202,15 @@ locals().update(A.__dict__) # :-) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('escape', [n1], None), # <== escaping - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), ResOperation('escape', [n1], None), # <== escaping - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), ResOperation('jump', [sum2, n2], None), ] @@ -245,14 +241,13 @@ ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone ResOperation('escape', [C.n1], None), # <== escaping - ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], C.v), + ResOperation('getfield_gc', [C.n1], C.v, C.ofs_value), ResOperation('int_sub', [C.v, ConstInt(1)], C.v2), ResOperation('int_add', [C.sum, C.v], C.sum2), ResOperation('escape', [C.n1], None), # <== escaping - ResOperation('new_with_vtable', [ConstInt(C.size_of_node), - ConstAddr(node_vtable, cpu)], C.n2), - ResOperation('setfield_gc', [C.n2, ConstInt(C.ofs_value), C.v2], - None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], C.n2, + C.size_of_node), + ResOperation('setfield_gc', [C.n2, C.v2], None, C.ofs_value), ResOperation('jump', [C.sum2, C.n2], None), ]) @@ -262,15 +257,14 @@ locals().update(A.__dict__) # :-) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu), - sizebox], None), + ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu)], None), # the only difference is different vtable ^^^^^^^^^^^^ - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), ResOperation('jump', [sum2, n2], None), ] @@ -285,14 +279,13 @@ locals().update(A.__dict__) # :-) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), ResOperation('guard_true', [v2], None), ResOperation('jump', [sum2, n2], None), ] @@ -327,8 +320,8 @@ self.cpu.translate_support_code = False self.ops = [] - def execute_and_record(self, opnum, args): - self.ops.append((opnum, args)) + def execute_and_record(self, opnum, args, descr): + self.ops.append((opnum, args, descr)) return 'stuff' spec = PerfectSpecializer(Loop(E.ops)) @@ -343,8 +336,8 @@ newboxes = rebuild_boxes_from_guard_failure(guard_op, fake_metainterp, [v_sum_b, v_v_b]) expected = [ - (rop.NEW_WITH_VTABLE, [E.sizebox, ConstInt(vt)]), - (rop.SETFIELD_GC, ['stuff', ConstInt(E.ofs_value), v_v_b]) + (rop.NEW_WITH_VTABLE, [ConstInt(vt)], E.size_of_node), + (rop.SETFIELD_GC, ['stuff', v_v_b], E.ofs_value) ] assert expected == fake_metainterp.ops assert newboxes == [v_sum_b, 'stuff'] @@ -361,14 +354,13 @@ vbool3 = BoxInt(1) ops = [ ResOperation('merge_point', [sum, n1, n3], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), ResOperation('ooisnot', [n2, n3], vbool1), ResOperation('guard_true', [vbool1], None), ResOperation('ooisnull', [n2], vbool2), @@ -436,18 +428,16 @@ v4 = BoxInt(124) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), - ConstInt(123)], None), - ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], v3), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, ConstInt(123)], None, ofs_value), + ResOperation('getfield_gc', [n2], v3, ofs_value), ResOperation('int_add', [v3, ConstInt(1)], v4), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v4], None), + ResOperation('setfield_gc', [n2, v4], None, ofs_value), ResOperation('guard_true', [v2], None), ResOperation('jump', [sum2, n2], None), ] @@ -490,13 +480,13 @@ v2 = BoxInt(nextnode.value) ops = [ ResOperation('merge_point', [n0], None), - ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], n1), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('getfield_gc', [n0], n1, ofs_next), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), - ResOperation('setfield_gc', [n0, ConstInt(ofs_next), n2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), + ResOperation('setfield_gc', [n0, n2], None, ofs_next), ResOperation('jump', [n0], None), ] @@ -522,9 +512,9 @@ n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) ops = [ ResOperation('merge_point', [n0], None), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n0], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, n0], None, ofs_next), ResOperation('jump', [n2], None), ] @@ -550,10 +540,10 @@ n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) ops = [ ResOperation('merge_point', [n0], None), - ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], n1), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n1], None), + ResOperation('getfield_gc', [n0], n1, ofs_next), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, n1], None, ofs_next), ResOperation('jump', [n2], None), ] @@ -573,12 +563,11 @@ v3 = BoxInt(4) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('getfield_gc', [n1], v3, ofs_value), ResOperation('int_add', [sum2, v3], sum3), ResOperation('escape', [n1], None), ResOperation('jump', [sum3, n1], None), @@ -596,7 +585,7 @@ ResOperation('int_add', [K0.sum, K0.v], K0.sum2), ResOperation('int_add', [K0.sum2, K0.v], K0.sum3), ResOperation('escape', [K0.n1], None), - ResOperation('getfield_gc', [K0.n1, ConstInt(K0.ofs_value)], v4), + ResOperation('getfield_gc', [K0.n1], v4, K0.ofs_value), ResOperation('jump', [K0.sum3, K0.n1, v4], None), ]) @@ -607,13 +596,12 @@ v3 = BoxInt(4) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('setfield_gc', [n1, ConstInt(ofs_value), sum], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('setfield_gc', [n1, sum], None, ofs_value), + ResOperation('getfield_gc', [n1], v3, ofs_value), ResOperation('int_add', [sum2, v3], sum3), ResOperation('escape', [n1], None), ResOperation('jump', [sum3, n1], None), @@ -630,10 +618,9 @@ ResOperation('int_sub', [K1.v, ConstInt(1)], K1.v2), ResOperation('int_add', [K1.sum, K1.v], K1.sum2), ResOperation('int_add', [K1.sum2, K1.sum], K1.sum3), - ResOperation('setfield_gc', [K1.n1, ConstInt(K1.ofs_value), K1.sum], - None), + ResOperation('setfield_gc', [K1.n1, K1.sum], None, K1.ofs_value), ResOperation('escape', [K1.n1], None), - ResOperation('getfield_gc', [K1.n1, ConstInt(K1.ofs_value)], v4), + ResOperation('getfield_gc', [K1.n1], v4, K1.ofs_value), ResOperation('jump', [K1.sum3, K1.n1, v4], None), ]) @@ -644,12 +631,11 @@ v3 = BoxInt(4) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('getfield_gc', [n1], v3, ofs_value), ResOperation('int_add', [sum2, v3], sum3), ResOperation('jump', [sum3, n1], None), ] @@ -675,13 +661,12 @@ v3 = BoxInt(4) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), ResOperation('escape', [n1], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v3), + ResOperation('getfield_gc', [n1], v3, ofs_value), ResOperation('int_add', [sum2, v3], sum3), ResOperation('jump', [sum3, n1], None), ] @@ -696,7 +681,7 @@ ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), ResOperation('int_add', [L.sum, L.v], L.sum2), ResOperation('escape', [L.n1], None), - ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], L.v3), + ResOperation('getfield_gc', [L.n1], L.v3, L.ofs_value), ResOperation('int_add', [L.sum2, L.v3], L.sum3), ResOperation('jump', [L.sum3, L.n1, L.v3], None), ]) @@ -709,9 +694,8 @@ v3 = BoxInt(4) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), ResOperation('escape', [n1], None), @@ -729,7 +713,7 @@ ResOperation('int_sub', [M.v, ConstInt(1)], M.v2), ResOperation('int_add', [M.sum, M.v], M.sum2), ResOperation('escape', [M.n1], None), - ResOperation('getfield_gc', [M.n1, ConstInt(M.ofs_value)], v4), + ResOperation('getfield_gc', [M.n1], v4, M.ofs_value), ResOperation('jump', [M.sum2, M.n1, v4], None), ]) @@ -741,9 +725,8 @@ v3 = BoxInt(4) ops = [ ResOperation('merge_point', [sum, n1], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), ResOperation('escape', [n1], None), @@ -761,7 +744,7 @@ ResOperation('int_sub', [N.v, ConstInt(1)], N.v2), ResOperation('int_add', [N.sum, N.v], N.sum2), ResOperation('escape', [N.n1], None), - ResOperation('getfield_gc', [N.n1, ConstInt(N.ofs_value)], v4), + ResOperation('getfield_gc', [N.n1], v4, N.ofs_value), ResOperation('jump', [N.sum2, N.n1, v4], None), ]) @@ -772,10 +755,8 @@ ops = [ ResOperation('merge_point', [], None), ResOperation('escape', [], n1), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('jump', [], None), ] ops[-3].liveboxes = [] @@ -790,8 +771,8 @@ ResOperation('merge_point', [], None), ResOperation('escape', [], O1.n1), # only the first guard_class is left - ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu), - O1.sizebox], None), + ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu)], + None), ResOperation('jump', [], None), ]) @@ -803,8 +784,7 @@ ops = [ ResOperation('merge_point', [], None), ResOperation('escape', [], n1), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('oononnull', [n1], v1), ResOperation('guard_true', [v1], None), ResOperation('jump', [], None), @@ -820,8 +800,8 @@ equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O2.n1), - ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu), - O2.sizebox], None), + ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu)], + None), # the oononnull and guard_true are gone, because we know they # return True -- as there was already a guard_class done on n1 ResOperation('jump', [], None), @@ -835,8 +815,7 @@ ops = [ ResOperation('merge_point', [], None), ResOperation('escape', [], n1), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('oois', [n1, ConstPtr(lltype.nullptr(llmemory.GCREF.TO))], v1), ResOperation('guard_false', [v1], None), @@ -853,8 +832,8 @@ equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O3.n1), - ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu), - O3.sizebox], None), + ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu)], + None), # the oois and guard_false are gone, because we know they # return False -- as there was already a guard_class done on n1 ResOperation('jump', [], None), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Fri Mar 6 18:46:59 2009 @@ -85,16 +85,16 @@ sum2 = BoxInt(0 + frame.node.value) ops = [ ResOperation('merge_point', [sum, fr], None), - ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], None), - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], + None, ofs_node), + ResOperation('getfield_gc', [fr], n1, ofs_node), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), ResOperation('int_add', [sum, v], sum2), - ResOperation('new_with_vtable', [ConstInt(size_of_node), - ConstAddr(node_vtable, cpu)], n2), - ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None), - ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], None), + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + size_of_node), + ResOperation('setfield_gc', [n2, v2], None, ofs_value), + ResOperation('setfield_gc', [fr, n2], None, ofs_node), ResOperation('jump', [sum2, fr], None), ] ops[1].vdesc = xy_desc @@ -142,10 +142,10 @@ v = BoxInt(13) ops = [ ResOperation('merge_point', [fr], None), - ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], None), - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], + None, ofs_node), + ResOperation('getfield_gc', [fr], n1, ofs_node), + ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('jump', [fr], None), ] ops[1].vdesc = xy_desc @@ -171,17 +171,16 @@ sizebox = ConstInt(cpu.sizeof(NODE)) ops = [ ResOperation('merge_point', [fr], None), - ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), - ConstInt(ofs_node)], None), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], + None, ofs_node), # - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), - sizebox], None), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v), + ResOperation('getfield_gc', [fr], n1, ofs_node), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), + ResOperation('getfield_gc', [n1], v, ofs_value), # - ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n2), + ResOperation('getfield_gc', [fr], n2, ofs_node), ResOperation('guard_class', [n2, ConstAddr(node_vtable, cpu)], None), - ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], v2), + ResOperation('getfield_gc', [n2], v2, ofs_value), # ResOperation('jump', [fr], None), ] From fijal at codespeak.net Fri Mar 6 20:02:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 20:02:35 +0100 (CET) Subject: [pypy-svn] r62663 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306190235.2287B16850C@codespeak.net> Author: fijal Date: Fri Mar 6 20:02:34 2009 New Revision: 62663 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: a bit of progress. still some weird failures though :( Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 6 20:02:34 2009 @@ -7,7 +7,8 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, - arg_pos, lower_byte, stack_pos, Perform) + arg_pos, lower_byte, stack_pos, Perform, + RETURN) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.support import gc_malloc_fnaddr @@ -387,8 +388,14 @@ base_loc, ofs_loc, value_loc, scale_loc, baseofs = arglocs assert isinstance(baseofs, IMM32) assert isinstance(scale_loc, IMM32) - self.mc.MOV(addr_add(base_loc, ofs_loc, baseofs.value, scale_loc.value), - value_loc) + if scale_loc.value == 2: + self.mc.MOV(addr_add(base_loc, ofs_loc, baseofs.value, + scale_loc.value), value_loc) + elif scale_loc.value == 0: + self.mc.MOV(addr_add8(base_loc, ofs_loc, baseofs.value, + scale_loc.value), lower_byte(value_loc)) + else: + raise NotImplementedError("scale = %d" % scale) def genop_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs @@ -418,7 +425,7 @@ genop_catch = genop_merge_point - def xxx_genop_return(self, op, locs): + def genop_return(self, op, locs): if op.args: loc = locs[0] if loc is not eax: @@ -506,16 +513,14 @@ arglocs = arglocs[1:] extra_on_stack = 0 for i in range(len(op.args) - 1, 0, -1): - # op.args[1] is a calldesc - if i != 1: - v = op.args[i] - loc = arglocs[len(arglocs) - 1 - extra_on_stack] - if not isinstance(loc, MODRM): - self.mc.PUSH(loc) - else: - # we need to add a bit, ble - self.mc.PUSH(stack_pos(loc.position + extra_on_stack)) - extra_on_stack += 1 + v = op.args[i] + loc = arglocs[i] + if not isinstance(loc, MODRM): + self.mc.PUSH(loc) + else: + # we need to add a bit, ble + self.mc.PUSH(stack_pos(loc.position + extra_on_stack)) + extra_on_stack += 1 if isinstance(op.args[0], Const): x = rel32(self.cpu.get_box_value_as_int(op.args[0])) else: @@ -537,14 +542,17 @@ # self.gen_call(op, arglocs, resloc) # self.mc.MOVZX(eax, eax) -genop_discard_list = [None] * rop._LAST +genop_discard_list = [None] * (RETURN + 1) genop_list = [None] * rop._LAST genop_guard_list = [None] * rop._LAST for name, value in Assembler386.__dict__.iteritems(): if name.startswith('genop_'): opname = name[len('genop_'):] - num = getattr(rop, opname.upper()) + if opname == 'return': + num = RETURN + else: + num = getattr(rop, opname.upper()) if value.func_code.co_argcount == 3: genop_discard_list[num] = value elif value.func_code.co_argcount == 5: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 20:02:34 2009 @@ -17,6 +17,8 @@ WORD = 4 FRAMESIZE = 1024 # XXX should not be a constant at all!! +RETURN = rop._LAST + class TempBox(Box): def __init__(self): pass @@ -578,7 +580,7 @@ self.eventually_free_vars(op.liveboxes + op.args) return ops + [PerformDiscard(op, [x, y] + locs)] - def xxx_consider_return(self, op, ignored): + def consider_return(self, op, ignored): if op.args: arglocs = [self.loc(op.args[0])] self.eventually_free_var(op.args[0]) @@ -720,19 +722,19 @@ def consider_call(self, op, ignored): from pypy.jit.backend.x86.runner import CPU386 - args = [op.args[0]] + op.args[2:] - calldescr = op.args[1].getint() - _, size, _ = CPU386.unpack_calldescr(calldescr) + calldescr = op.descr + numargs, size, _ = CPU386.unpack_calldescr(calldescr) + assert numargs == len(op.args) return self._call(op, [imm(size)] + - [self.loc(arg) for arg in args]) + [self.loc(arg) for arg in op.args]) consider_call_pure = consider_call def consider_new(self, op, ignored): - return self._call(op, [self.loc(arg) for arg in op.args]) + return self._call(op, [imm(op.descr)]) def consider_new_with_vtable(self, op, ignored): - return self._call(op, [self.loc(arg) for arg in op.args]) + return self._call(op, [imm(op.descr), self.loc(op.args[0])]) def consider_newstr(self, op, ignored): ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] @@ -766,8 +768,8 @@ return res def consider_new_array(self, op, ignored): - size_of_field, basesize = self._unpack_arraydescr(op.args[0].getint()) - return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[1], + size_of_field, basesize = self._unpack_arraydescr(op.descr) + return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[0], op.result) def consider_oononnull(self, op, ignored): @@ -788,9 +790,9 @@ def consider_setfield_gc(self, op, ignored): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) - value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) - self.eventually_free_vars([op.args[0], op.args[1], op.args[2]]) + ofs_loc, size_loc = self._unpack_fielddescr(op.descr) + value_loc, ops2 = self.make_sure_var_in_reg(op.args[1], op.args) + self.eventually_free_vars(op.args) return (ops0 + ops2 + [PerformDiscard(op, [base_loc, ofs_loc, size_loc, value_loc])]) @@ -803,21 +805,19 @@ [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) def consider_setarrayitem_gc(self, op, ignored): - scale, ofs = self._unpack_arraydescr(op.args[1].getint()) - assert scale == 2 - args = [op.args[0], op.args[2], op.args[3]] - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[2], args) - value_loc, ops2 = self.make_sure_var_in_reg(op.args[3], args) + scale, ofs = self._unpack_arraydescr(op.descr) + base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) + value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) self.eventually_free_vars(op.args) return (ops0 + ops2 + ops1 + [PerformDiscard(op, [base_loc, ofs_loc, value_loc, imm(scale), imm(ofs)])]) def consider_getfield_gc(self, op, ignored): - ofs_loc, size_loc = self._unpack_fielddescr(op.args[1].getint()) + ofs_loc, size_loc = self._unpack_fielddescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - self.eventually_free_vars([op.args[0], op.args[1]]) + self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) return (ops0 + more_ops + [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) @@ -825,10 +825,9 @@ consider_getfield_gc_pure = consider_getfield_gc def consider_getarrayitem_gc(self, op, ignored): - scale, ofs = self._unpack_arraydescr(op.args[1].getint()) - args = [op.args[0], op.args[2]] - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[2], args) + scale, ofs = self._unpack_arraydescr(op.descr) + base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) return (ops0 + ops1 + more_ops + @@ -953,12 +952,15 @@ self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] -oplist = [None] * rop._LAST +oplist = [None] * (RETURN + 1) for name, value in RegAlloc.__dict__.iteritems(): if name.startswith('consider_'): name = name[len('consider_'):] - num = getattr(rop, name.upper()) + if name == 'return': + num = RETURN + else: + num = getattr(rop, name.upper()) oplist[num] = value def arg_pos(i): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 20:02:34 2009 @@ -11,7 +11,7 @@ from pypy.jit.metainterp import history from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) -from pypy.jit.backend.x86.assembler import Assembler386, WORD +from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.x86.executor import execute @@ -30,7 +30,7 @@ lltype.Ptr(rffi.CArray(lltype.Signed))], lltype.Signed) - return_value_box = None + return_value_type = 0 def __init__(self, rtyper, stats, translate_support_code=False, mixlevelann=None): @@ -123,7 +123,7 @@ guard_op, 'to the jit') gf = GuardFailed(self, frame_addr, guard_op) self.metainterp.handle_guard_failure(gf) - self.return_value_box = gf.return_value_box + self.return_value_type = gf.return_value_type if self.debug: if gf.return_addr == self.assembler.generic_return_addr: llop.debug_print(lltype.Void, 'continuing at generic return address') @@ -141,12 +141,12 @@ def set_meta_interp(self, metainterp): self.metainterp = metainterp - def get_exception(self, frame): + def get_exception(self): res = self.assembler._exception_data[0] self.assembler._exception_data[0] = 0 return res - def get_exc_value(self, frame): + def get_exc_value(self): return self.cast_int_to_gcref(self.assembler._exception_data[1]) # def execute_operation(self, opnum, valueboxes, result_type): @@ -271,14 +271,12 @@ return self.generated_mps[calldescr] except KeyError: pass - args = [BoxInt(0) for i in range(argnum + 3)] - args[1].value = calldescr + args = [BoxInt(0) for i in range(argnum)] result = BoxInt(0) operations = [ ResOperation(rop.MERGE_POINT, args, None), - ResOperation(rop.CALL, args[:-1], result), - ResOperation(rop.GUARD_FALSE, [args[-1]], None)] - operations[-1].liveboxes = [result] + ResOperation(rop.CALL, args, result, calldescr), + ResOperation(RETURN, [result], None)] self.compile_operations(operations) self.generated_mps[calldescr] = operations return operations @@ -302,16 +300,18 @@ self.keepalives_index = len(self.keepalives) res = self.execute_call(startmp, func, values_as_int) - if self.return_value_box is None: + if self.return_value_type == VOID: if self.debug: llop.debug_print(lltype.Void, " => void result") + res = None else: if self.debug: llop.debug_print(lltype.Void, " => ", res) + res = self.get_valuebox_from_int(self.return_value_type, res) keepalive_until_here(valueboxes) self.keepalives_index = oldindex del self.keepalives[oldindex:] - return self.return_value_box + return res def execute_call(self, startmp, func, values_as_int): # help flow objspace @@ -396,13 +396,12 @@ # ------------------- backend-specific ops ------------------------ - def do_arraylen_gc(self, args): + def do_arraylen_gc(self, args, arraydescr): gcref = args[0].getptr(llmemory.GCREF) return BoxInt(rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[0]) - def do_getarrayitem_gc(self, args): - arraydescr = args[1].getint() - field = args[2].getint() + def do_getarrayitem_gc(self, args, arraydescr): + field = args[1].getint() gcref = args[0].getptr(llmemory.GCREF) if arraydescr < 0: ptr = True @@ -423,9 +422,8 @@ else: raise NotImplementedError("size = %d" % size) - def do_setarrayitem_gc(self, args): - arraydescr = args[1].getint() - field = args[2].getint() + def do_setarrayitem_gc(self, args, arraydescr): + field = args[1].getint() gcref = args[0].getptr(llmemory.GCREF) if arraydescr < 0: ptr = True @@ -434,25 +432,25 @@ shift, ofs = self.unpack_arraydescr(arraydescr) size = 1 << shift if size == 1: - v = args[3].getint() + v = args[2].getint() rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[ofs + field] = chr(v) elif size == WORD: a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) if not ptr: - a[ofs/WORD + field] = args[3].getint() + a[ofs/WORD + field] = args[2].getint() else: - p = args[3].getptr(llmemory.GCREF) + p = args[2].getptr(llmemory.GCREF) a[ofs/WORD + field] = self.cast_gcref_to_int(p) else: raise NotImplementedError("size = %d" % size) - def do_strlen(self, args): + def do_strlen(self, args, descr=0): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) gcref = args[0].getptr(llmemory.GCREF) v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] return BoxInt(v) - def do_strgetitem(self, args): + def do_strgetitem(self, args, descr=0): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) gcref = args[0].getptr(llmemory.GCREF) i = args[1].getint() @@ -474,13 +472,11 @@ raise NotImplementedError("size = %d" % size) return BoxInt(v) - def do_getfield_gc(self, args): - fielddescr = args[1].getint() + def do_getfield_gc(self, args, fielddescr): gcref = args[0].getptr(llmemory.GCREF) return self._base_do_getfield(gcref, fielddescr) - def do_getfield_raw(self, args): - fielddescr = args[1].getint() + def do_getfield_raw(self, args, fielddescr): return self._base_do_getfield(args[0].getint(), fielddescr) @specialize.argtype(2) @@ -502,33 +498,31 @@ else: raise NotImplementedError("size = %d" % size) - def do_setfield_gc(self, args): - fielddescr = args[1].getint() + def do_setfield_gc(self, args, fielddescr): gcref = args[0].getptr(llmemory.GCREF) - self._base_do_setfield(fielddescr, gcref, args[2]) + self._base_do_setfield(fielddescr, gcref, args[1]) - def do_setfield_raw(self, args): - fielddescr = args[1].getint() - self._base_do_setfield(fielddescr, args[0].getint(), args[2]) + def do_setfield_raw(self, args, fielddescr): + self._base_do_setfield(fielddescr, args[0].getint(), args[1]) - def do_new(self, args): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(args[0].getint()) + def do_new(self, args, descrsize): + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize) return BoxPtr(self.cast_int_to_gcref(res)) - def do_new_with_vtable(self, args): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(args[0].getint()) - rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[1].getint() + def do_new_with_vtable(self, args, descrsize): + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize) + rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[0].getint() return BoxPtr(self.cast_int_to_gcref(res)) - def do_new_array(self, args): - size_of_field, ofs = self.unpack_arraydescr(args[0].getint()) - num_elem = args[1].getint() + def do_new_array(self, args, arraydescr): + size_of_field, ofs = self.unpack_arraydescr(arraydescr) + num_elem = args[0].getint() size = ofs + (1 << size_of_field) * num_elem res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = num_elem return BoxPtr(self.cast_int_to_gcref(res)) - def do_newstr(self, args): + def do_newstr(self, args, descr=0): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) assert itemsize == 1 num_elem = args[0].getint() @@ -537,18 +531,23 @@ rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem return BoxPtr(self.cast_int_to_gcref(res)) - def do_strsetitem(self, args): + def do_strsetitem(self, args, descr=0): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) index = args[1].getint() v = args[2].getint() a = args[0].getptr(llmemory.GCREF) rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v) - def do_call(self, args): - calldescr = args[1].getint() + def do_call(self, args, calldescr): num_args, size, ptr = self.unpack_calldescr(calldescr) mp = self._get_mp_for_call(num_args, calldescr) - return self.execute_operations_in_new_frame('call', mp, args + [BoxInt(1)]) + if size == 0: + self.return_value_type = VOID + elif ptr: + self.return_value_type = PTR + else: + self.return_value_type = INT + return self.execute_operations_in_new_frame('call', mp, args) # ------------------- helpers and descriptions -------------------- @@ -654,7 +653,7 @@ return hex(x) class GuardFailed(object): - return_value_box = None + return_value_type = 0 def __init__(self, cpu, frame, guard_op): self.cpu = cpu @@ -666,7 +665,13 @@ if return_value_box is not None: frame = getframe(self.frame) frame[0] = self.cpu.convert_box_to_int(return_value_box) - self.return_value_box = return_value_box + if (isinstance(return_value_box, ConstInt) or + isinstance(return_value_box, BoxInt)): + self.return_value_type = INT + else: + self.return_value_type = PTR + else: + self.return_value_type = VOID self.return_addr = self.cpu.assembler.generic_return_addr def make_ready_for_continuing_at(self, merge_point): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 20:02:34 2009 @@ -45,15 +45,17 @@ cls.cpu = CPU(rtyper=None, stats=FakeStats()) cls.cpu.set_meta_interp(FakeMetaInterp()) - def execute_operation(self, opname, valueboxes, result_type): + def execute_operation(self, opname, valueboxes, result_type, descr=0): key = [opname, result_type] - mp = self.get_compiled_single_operation(opname, result_type, valueboxes) + mp = self.get_compiled_single_operation(opname, result_type, valueboxes, + descr) boxes = [box for box in valueboxes if isinstance(box, Box)] res = self.cpu.execute_operations_in_new_frame(opname, mp, boxes + [BoxInt(1)]) return res - def get_compiled_single_operation(self, opnum, result_type, valueboxes): + def get_compiled_single_operation(self, opnum, result_type, valueboxes, + descr): livevarlist = [] for box in valueboxes: if isinstance(box, Box): @@ -78,6 +80,7 @@ operations = [mp, ResOperation(opnum, livevarlist, result), ResOperation(rop.GUARD_FALSE, [checker], None)] + operations[1].descr = descr operations[-1].liveboxes = results if operations[1].is_guard(): operations[1].liveboxes = [] @@ -114,13 +117,13 @@ cpu = self.cpu u = lltype.malloc(U) u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) - ofs_box = ConstInt(cpu.fielddescrof(S, 'value')) + ofs = cpu.fielddescrof(S, 'value') assert self.execute_operation(rop.SETFIELD_GC, - [u_box, ofs_box, BoxInt(3)], - 'void') == None + [u_box, BoxInt(3)], + 'void', ofs) == None assert u.parent.parent.value == 3 u.parent.parent.value += 100 - assert (self.execute_operation(rop.GETFIELD_GC, [u_box, ofs_box], 'int') + assert (self.execute_operation(rop.GETFIELD_GC, [u_box], 'int', ofs) .value == 103) def test_execute_operations_in_env(self): @@ -250,18 +253,18 @@ TP = lltype.GcArray(lltype.Signed) ofs = symbolic.get_field_token(TP, 'length')[0] - descr = ConstInt(self.cpu.arraydescrof(TP)) + descr = self.cpu.arraydescrof(TP) - res = self.execute_operation(rop.NEW_ARRAY, [descr, ConstInt(10)], - 'ptr') + res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)], + 'ptr', descr) assert allocs[0] == 10*WORD + ofs + WORD resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) assert resbuf[ofs/WORD] == 10 # ------------------------------------------------------------ - res = self.execute_operation(rop.NEW_ARRAY, [descr, BoxInt(10)], - 'ptr') + res = self.execute_operation(rop.NEW_ARRAY, [BoxInt(10)], + 'ptr', descr) assert allocs[0] == 10*WORD + ofs + WORD resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) assert resbuf[ofs/WORD] == 10 @@ -287,26 +290,26 @@ TP = lltype.GcArray(lltype.Signed) ofs = symbolic.get_field_token(TP, 'length')[0] itemsofs = symbolic.get_field_token(TP, 'items')[0] - descr = ConstInt(self.cpu.arraydescrof(TP)) - res = self.execute_operation(rop.NEW_ARRAY, [descr, ConstInt(10)], - 'ptr') + descr = self.cpu.arraydescrof(TP) + res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)], + 'ptr', descr) resbuf = ctypes.cast(res.value.intval, ctypes.POINTER(ctypes.c_int)) assert resbuf[ofs/WORD] == 10 - self.execute_operation(rop.SETARRAYITEM_GC, [res, descr, + self.execute_operation(rop.SETARRAYITEM_GC, [res, ConstInt(2), BoxInt(38)], - 'void') + 'void', descr) assert resbuf[itemsofs/WORD + 2] == 38 - self.execute_operation(rop.SETARRAYITEM_GC, [res, descr, + self.execute_operation(rop.SETARRAYITEM_GC, [res, BoxInt(3), BoxInt(42)], - 'void') + 'void', descr) assert resbuf[itemsofs/WORD + 3] == 42 - r = self.execute_operation(rop.GETARRAYITEM_GC, [res, descr, - ConstInt(2)], 'int') + r = self.execute_operation(rop.GETARRAYITEM_GC, [res, ConstInt(2)], + 'int', descr) assert r.value == 38 - r = self.execute_operation(rop.GETARRAYITEM_GC, [res, descr, - BoxInt(3)], 'int') + r = self.execute_operation(rop.GETARRAYITEM_GC, [res, BoxInt(3)], + 'int', descr) assert r.value == 42 def test_getfield_setfield(self): @@ -316,34 +319,39 @@ ('c1', lltype.Char), ('c2', lltype.Char), ('c3', lltype.Char)) - res = self.execute_operation(rop.NEW, [ConstInt(self.cpu.sizeof(TP))], - 'ptr') - ofs_s = ConstInt(self.cpu.fielddescrof(TP, 's')) - ofs_f = ConstInt(self.cpu.fielddescrof(TP, 'f')) - ofs_u = ConstInt(self.cpu.fielddescrof(TP, 'u')) - ofsc1 = ConstInt(self.cpu.fielddescrof(TP, 'c1')) - ofsc2 = ConstInt(self.cpu.fielddescrof(TP, 'c2')) - ofsc3 = ConstInt(self.cpu.fielddescrof(TP, 'c3')) - self.execute_operation(rop.SETFIELD_GC, [res, ofs_s, ConstInt(3)], 'void') + res = self.execute_operation(rop.NEW, [], + 'ptr', self.cpu.sizeof(TP)) + ofs_s = self.cpu.fielddescrof(TP, 's') + ofs_f = self.cpu.fielddescrof(TP, 'f') + ofs_u = self.cpu.fielddescrof(TP, 'u') + ofsc1 = self.cpu.fielddescrof(TP, 'c1') + ofsc2 = self.cpu.fielddescrof(TP, 'c2') + ofsc3 = self.cpu.fielddescrof(TP, 'c3') + self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(3)], 'void', + ofs_s) # XXX ConstFloat #self.execute_operation(rop.SETFIELD_GC, [res, ofs_f, 1e100], 'void') # XXX we don't support shorts (at all) #self.execute_operation(rop.SETFIELD_GC, [res, ofs_u, ConstInt(5)], 'void') - s = self.execute_operation(rop.GETFIELD_GC, [res, ofs_s], 'int') + s = self.execute_operation(rop.GETFIELD_GC, [res], 'int', ofs_s) assert s.value == 3 - self.execute_operation(rop.SETFIELD_GC, [res, ofs_s, BoxInt(3)], 'void') - s = self.execute_operation(rop.GETFIELD_GC, [res, ofs_s], 'int') + self.execute_operation(rop.SETFIELD_GC, [res, BoxInt(3)], 'void', + ofs_s) + s = self.execute_operation(rop.GETFIELD_GC, [res], 'int', ofs_s) assert s.value == 3 #u = self.execute_operation(rop.GETFIELD_GC, [res, ofs_u], 'int') #assert u.value == 5 - self.execute_operation(rop.SETFIELD_GC, [res, ofsc1, ConstInt(1)], 'void') - self.execute_operation(rop.SETFIELD_GC, [res, ofsc2, ConstInt(2)], 'void') - self.execute_operation(rop.SETFIELD_GC, [res, ofsc3, ConstInt(3)], 'void') - c = self.execute_operation(rop.GETFIELD_GC, [res, ofsc1], 'int') + self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(1)], 'void', + ofsc1) + self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(2)], 'void', + ofsc2) + self.execute_operation(rop.SETFIELD_GC, [res, ConstInt(3)], 'void', + ofsc3) + c = self.execute_operation(rop.GETFIELD_GC, [res], 'int', ofsc1) assert c.value == 1 - c = self.execute_operation(rop.GETFIELD_GC, [res, ofsc2], 'int') + c = self.execute_operation(rop.GETFIELD_GC, [res], 'int', ofsc2) assert c.value == 2 - c = self.execute_operation(rop.GETFIELD_GC, [res, ofsc3], 'int') + c = self.execute_operation(rop.GETFIELD_GC, [res], 'int', ofsc3) assert c.value == 3 def test_ovf_ops(self): @@ -381,25 +389,26 @@ cpu = self.cpu # A = lltype.GcArray(lltype.Char) - descrbox_A = ConstInt(cpu.arraydescrof(A)) + descr_A = cpu.arraydescrof(A) a = lltype.malloc(A, 5) x = cpu.do_arraylen_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a))], + descr_A) assert x.value == 5 # a[2] = 'Y' x = cpu.do_getarrayitem_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), descrbox_A, - BoxInt(2)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a)), BoxInt(2)], + descr_A) assert x.value == ord('Y') # B = lltype.GcArray(lltype.Ptr(A)) - descrbox_B = ConstInt(cpu.arraydescrof(B)) + descr_B = cpu.arraydescrof(B) b = lltype.malloc(B, 4) b[3] = a x = cpu.do_getarrayitem_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, - BoxInt(3)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), BoxInt(3)], + descr_B) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # @@ -418,29 +427,28 @@ s = lltype.malloc(S) s.x = 'Z' x = cpu.do_getfield_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_x)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))], + descrfld_x) assert x.value == ord('Z') # cpu.do_setfield_gc( [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_x), - BoxInt(ord('4'))]) + BoxInt(ord('4'))], + descrfld_x) assert s.x == '4' # descrfld_y = cpu.fielddescrof(S, 'y') s.y = a x = cpu.do_getfield_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_y)]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))], + descrfld_y) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # s.y = lltype.nullptr(A) cpu.do_setfield_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), - BoxInt(descrfld_y), - x]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)), x], + descrfld_y) assert s.y == a # RS = lltype.Struct('S', ('x', lltype.Char), ('y', lltype.Ptr(A))) @@ -448,61 +456,57 @@ rs = lltype.malloc(RS, immortal=True) rs.x = '?' x = cpu.do_getfield_raw( - [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_rx)]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs)))], + descrfld_rx) assert x.value == ord('?') # cpu.do_setfield_raw( [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_rx), - BoxInt(ord('!'))]) + BoxInt(ord('!'))], + descrfld_rx) assert rs.x == '!' # descrfld_ry = cpu.fielddescrof(RS, 'y') rs.y = a x = cpu.do_getfield_raw( - [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_ry)]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs)))], + descrfld_ry) assert isinstance(x, BoxPtr) assert x.getptr(lltype.Ptr(A)) == a # rs.y = lltype.nullptr(A) cpu.do_setfield_raw( - [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), - BoxInt(descrfld_ry), - x]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(rs))), x], + descrfld_ry) assert rs.y == a # descrsize = cpu.sizeof(S) - x = cpu.do_new( - [BoxInt(descrsize)]) + x = cpu.do_new([], descrsize) assert isinstance(x, BoxPtr) x.getptr(lltype.Ptr(S)) # descrsize2 = cpu.sizeof(rclass.OBJECT) vtable2 = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) x = cpu.do_new_with_vtable( - [BoxInt(descrsize2), - BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))]) + [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(vtable2)))], + descrsize2) assert isinstance(x, BoxPtr) - # well.... - assert (rffi.cast(rffi.CArrayPtr(lltype.Signed), - x.getptr(llmemory.GCREF))[0]) + # well... #assert x.getptr(rclass.OBJECTPTR).typeptr == vtable2 # arraydescr = cpu.arraydescrof(A) - x = cpu.do_new_array( - [BoxInt(arraydescr), BoxInt(7)]) + x = cpu.do_new_array([BoxInt(7)], arraydescr) assert isinstance(x, BoxPtr) assert len(x.getptr(lltype.Ptr(A))) == 7 # cpu.do_setarrayitem_gc( - [x, descrbox_A, BoxInt(5), BoxInt(ord('*'))]) + [x, BoxInt(5), BoxInt(ord('*'))], descr_A) assert x.getptr(lltype.Ptr(A))[5] == '*' # cpu.do_setarrayitem_gc( - [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), descrbox_B, - BoxInt(1), x]) + [BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, b)), + BoxInt(1), x], + descr_B) assert b[1] == x.getptr(lltype.Ptr(A)) # x = cpu.do_newstr([BoxInt(5)]) @@ -520,11 +524,11 @@ return chr(ord(c) + 1) FPTR = lltype.Ptr(lltype.FuncType([lltype.Char], lltype.Char)) func_ptr = llhelper(FPTR, func) - calldescr = cpu.calldescrof([lltype.Char], lltype.Char) + calldescr = cpu.calldescrof([FPTR, lltype.Char], lltype.Char) x = cpu.do_call( [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(func_ptr))), - ConstInt(calldescr), - BoxInt(ord('A'))]) + BoxInt(ord('A'))], + calldescr) assert x.value == ord('B') def test_executor(self): From fijal at codespeak.net Fri Mar 6 20:07:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 20:07:52 +0100 (CET) Subject: [pypy-svn] r62664 - in pypy/branch/pyjitpl5/pypy/jit: backend/x86 backend/x86/test metainterp Message-ID: <20090306190752.105E3168499@codespeak.net> Author: fijal Date: Fri Mar 6 20:07:51 2009 New Revision: 62664 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: aha! find out who is calling calldescr with function as well as arg Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 20:07:51 2009 @@ -724,7 +724,7 @@ from pypy.jit.backend.x86.runner import CPU386 calldescr = op.descr numargs, size, _ = CPU386.unpack_calldescr(calldescr) - assert numargs == len(op.args) + assert numargs == len(op.args) - 1 return self._call(op, [imm(size)] + [self.loc(arg) for arg in op.args]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 20:07:51 2009 @@ -271,7 +271,7 @@ return self.generated_mps[calldescr] except KeyError: pass - args = [BoxInt(0) for i in range(argnum)] + args = [BoxInt(0) for i in range(argnum + 1)] result = BoxInt(0) operations = [ ResOperation(rop.MERGE_POINT, args, None), Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Fri Mar 6 20:07:51 2009 @@ -524,7 +524,7 @@ return chr(ord(c) + 1) FPTR = lltype.Ptr(lltype.FuncType([lltype.Char], lltype.Char)) func_ptr = llhelper(FPTR, func) - calldescr = cpu.calldescrof([FPTR, lltype.Char], lltype.Char) + calldescr = cpu.calldescrof([lltype.Char], lltype.Char) x = cpu.do_call( [BoxInt(cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(func_ptr))), BoxInt(ord('A'))], Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Mar 6 20:07:51 2009 @@ -671,7 +671,7 @@ args = [x for x in op.args if x.concretetype is not lltype.Void] argtypes = [v.concretetype for v in args] resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes, resulttype) + calldescr = self.cpu.calldescrof(argtypes[1:], resulttype) self.emit('residual_call_%s' % getkind(resulttype)) self.emit(calldescr) self.emit_varargs(args) From fijal at codespeak.net Fri Mar 6 20:16:24 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 20:16:24 +0100 (CET) Subject: [pypy-svn] r62665 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090306191624.EDDFF168499@codespeak.net> Author: fijal Date: Fri Mar 6 20:16:24 2009 New Revision: 62665 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: Fix this one Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Mar 6 20:16:24 2009 @@ -33,9 +33,9 @@ operations[1].liveboxes = [i, flag] cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', startmp, - [BoxInt(0), BoxInt(1)], 'int') - assert res.value == 42 + res = cpu.execute_operations_in_new_frame('foo', operations, + [BoxInt(0), BoxInt(1)]) + assert res.value == 5 assert meta_interp.recordedvalues == [5, False] # assert stuff regalloc = cpu.assembler._regalloc @@ -92,11 +92,10 @@ cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', startmp, + res = cpu.execute_operations_in_new_frame('foo', operations, [BoxInt(1), BoxInt(1), - BoxInt(0), BoxInt(1)], - 'int') - assert res.value == 42 + BoxInt(0), BoxInt(1)]) + assert res.value == 6 assert meta_interp.recordedvalues == f() def test_loop_with_const_and_var_swap(): @@ -121,11 +120,10 @@ cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', operations[0], + res = cpu.execute_operations_in_new_frame('foo', operations, [BoxInt(1), BoxInt(2), - BoxInt(3), BoxInt(10)], - 'int') - assert res.value == 42 + BoxInt(3), BoxInt(10)]) + assert res.value == 0 assert meta_interp.recordedvalues == [0, 1, 3, 2, 0] def test_bool_optimizations(): From fijal at codespeak.net Fri Mar 6 20:16:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 20:16:47 +0100 (CET) Subject: [pypy-svn] r62666 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090306191647.1C96E1684B5@codespeak.net> Author: fijal Date: Fri Mar 6 20:16:46 2009 New Revision: 62666 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: make sure we're able to write down negative numbers. possibly not rpython Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Mar 6 20:16:46 2009 @@ -8,7 +8,7 @@ from pypy.jit.metainterp.history import Const, getkind from pypy.jit.metainterp import heaptracker, support, history -import py +import py, sys from pypy.tool.ansi_print import ansi_log log = py.log.Producer('jitcodewriter') py.log.setconsumer('jitcodewriter', ansi_log) @@ -911,7 +911,8 @@ return "tlabel(%r)" % (self.name, ) def encode_int(index): - assert index >= 0 + if index < 0: + index += 2*(sys.maxint + 1) result = [] while True: byte = index & 0x7F Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Mar 6 20:16:46 2009 @@ -133,7 +133,7 @@ if not byte & 0x80: break self.pc = pc - return result + return intmask(result) _load_larger_int._dont_inline_ = True def load_3byte(self): From fijal at codespeak.net Fri Mar 6 23:15:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 23:15:15 +0100 (CET) Subject: [pypy-svn] r62667 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090306221515.C12C01684DB@codespeak.net> Author: fijal Date: Fri Mar 6 23:15:14 2009 New Revision: 62667 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: how possibly this could have worked? Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 23:15:14 2009 @@ -1,7 +1,7 @@ from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, ResOperation) -from pypy.jit.metainterp.history import Options, AbstractValue +from pypy.jit.metainterp.history import Options, AbstractValue, ConstPtr from pypy.jit.metainterp.specnode import (FixedClassSpecNode, #FixedListSpecNode, VirtualInstanceSpecNode, @@ -16,6 +16,7 @@ ) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import lltype, llmemory #from pypy.jit.metainterp.codewriter import ListDescr @@ -744,13 +745,15 @@ ## instnode = self.nodes[op.args[0]] ## instnode.cursize = op.args[1].getint() ## continue - elif (opnum == rop.GUARD_NO_EXCEPTION or - opnum == rop.GUARD_EXCEPTION): + elif opnum == rop.GUARD_NO_EXCEPTION: if not exception_might_have_happened: continue exception_might_have_happened = False newoperations.append(self.optimize_guard(op, cpu)) continue + elif opnum == rop.GUARD_EXCEPTION: + newoperations.append(self.optimize_guard(op, cpu)) + continue elif (opnum == rop.GUARD_TRUE or opnum == rop.GUARD_FALSE): instnode = self.nodes[op.args[0]] From fijal at codespeak.net Fri Mar 6 23:26:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 23:26:08 +0100 (CET) Subject: [pypy-svn] r62668 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090306222608.30DE61684DB@codespeak.net> Author: fijal Date: Fri Mar 6 23:26:07 2009 New Revision: 62668 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: make do_call raising exception Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 23:26:07 2009 @@ -547,7 +547,18 @@ self.return_value_type = PTR else: self.return_value_type = INT - return self.execute_operations_in_new_frame('call', mp, args) + result = self.execute_operations_in_new_frame('call', mp, args) + if not we_are_translated(): + exc = self.get_exception() + if exc: + TP = lltype.Ptr(rclass.OBJECT_VTABLE) + TP_V = lltype.Ptr(rclass.OBJECT) + exc_t_a = self.cast_int_to_adr(exc) + exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) + exc_v_a = self.get_exc_value() + exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) + raise LLException(exc_type, exc_val) + return result # ------------------- helpers and descriptions -------------------- From fijal at codespeak.net Fri Mar 6 23:26:24 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 23:26:24 +0100 (CET) Subject: [pypy-svn] r62669 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090306222624.3D0801684FC@codespeak.net> Author: fijal Date: Fri Mar 6 23:26:23 2009 New Revision: 62669 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: getaddr for ConstPtr Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Fri Mar 6 23:26:23 2009 @@ -202,6 +202,9 @@ def get_(self): return lltype.cast_ptr_to_int(self.value) + def getaddr(self, cpu): + return llmemory.cast_ptr_to_adr(self.value) + def equals(self, other): return self.value == other.getptr_base() From fijal at codespeak.net Fri Mar 6 23:28:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 23:28:23 +0100 (CET) Subject: [pypy-svn] r62670 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090306222823.706B91684FB@codespeak.net> Author: fijal Date: Fri Mar 6 23:28:23 2009 New Revision: 62670 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Log: minor changes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 6 23:28:23 2009 @@ -891,7 +891,7 @@ return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] def consider_arraylen_gc(self, op, ignored): - _, ofs = self._unpack_arraydescr(op.args[1].getint()) + _, ofs = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Fri Mar 6 23:28:23 2009 @@ -62,8 +62,8 @@ assert cpu.fielddescrof(S, 'y') & 0xffff == get_field_token(S, 'y')[0] assert cpu.fielddescrof(S, 'y') >> 16 == get_field_token(S, 'y')[1] A = lltype.GcArray(lltype.Char) - assert cpu.itemoffsetof(A) == get_array_token(A)[0] - assert cpu.arraylengthoffset(A) == get_array_token(A)[2] + #assert cpu.itemoffsetof(A) == get_array_token(A)[0] + #assert cpu.arraylengthoffset(A) == get_array_token(A)[2] def test_string(): STR = lltype.GcStruct('String', ('hash', lltype.Signed), From fijal at codespeak.net Fri Mar 6 23:29:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 23:29:15 +0100 (CET) Subject: [pypy-svn] r62671 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090306222915.055E71684DB@codespeak.net> Author: fijal Date: Fri Mar 6 23:29:15 2009 New Revision: 62671 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: seems we actually need this Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 6 23:29:15 2009 @@ -383,7 +383,7 @@ def sizeof(self, S): return symbolic.get_size(S) -# numof = sizeof + numof = sizeof # addresssuffix = str(symbolic.get_size(llmemory.Address)) # def itemoffsetof(self, A): From fijal at codespeak.net Fri Mar 6 23:35:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 6 Mar 2009 23:35:38 +0100 (CET) Subject: [pypy-svn] r62672 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090306223538.E874E1684DB@codespeak.net> Author: fijal Date: Fri Mar 6 23:35:38 2009 New Revision: 62672 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: trivial translation fixes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 6 23:35:38 2009 @@ -72,8 +72,8 @@ if instnode.cursize == -1: # fish fish fish instnode.cursize = executor.execute(cpu, rop.ARRAYLEN_GC, - [instnode.source, ad] - ).getint() + [instnode.source], + ad).getint() self.list_allocations.append((ad, instnode.cursize)) res = (alloc_offset + 1) << 16 else: @@ -142,13 +142,19 @@ node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - esc_self = self.vdesc and key not in self.vdesc.virtuals + if self.vdesc and key not in self.vdesc.virtuals: + esc_self = True + else: + esc_self = False node.escape_if_startbox(memo, esc_self) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: - esc_self = self.vdesc and key not in self.vdesc.virtuals + if self.vdesc and key not in self.vdesc.virtuals: + esc_self = True + else: + esc_self = False node.escape_if_startbox(memo, esc_self) def add_to_dependency_graph(self, other, dep_graph): From santagada at codespeak.net Sat Mar 7 00:24:47 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sat, 7 Mar 2009 00:24:47 +0100 (CET) Subject: [pypy-svn] r62674 - in pypy/trunk/pypy/translator/platform: . test Message-ID: <20090306232447.8B10016847F@codespeak.net> Author: santagada Date: Sat Mar 7 00:24:47 2009 New Revision: 62674 Added: pypy/trunk/pypy/translator/platform/test/test_darwin.py (contents, props changed) Modified: pypy/trunk/pypy/translator/platform/darwin.py Log: implemented support for frameworks on the darwin platform and a test for it. Modified: pypy/trunk/pypy/translator/platform/darwin.py ============================================================================== --- pypy/trunk/pypy/translator/platform/darwin.py (original) +++ pypy/trunk/pypy/translator/platform/darwin.py Sat Mar 7 00:24:47 2009 @@ -31,3 +31,16 @@ # currently __thread is not supported by Darwin gccs return False + def _frameworks(self, frameworks): + args = [] + for f in frameworks: + args.append('-framework') + args.append(f) + return args + + def _link_args_from_eci(self, eci): + args = super(Darwin, self)._link_args_from_eci(eci) + frameworks = self._frameworks(eci.frameworks) + include_dirs = self._includedirs(eci.include_dirs) + return (args + frameworks + include_dirs) + Added: pypy/trunk/pypy/translator/platform/test/test_darwin.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/translator/platform/test/test_darwin.py Sat Mar 7 00:24:47 2009 @@ -0,0 +1,38 @@ + +""" File containing darwin platform tests +""" + +import py +from pypy.tool.udir import udir +from pypy.translator.platform.darwin import Darwin +from pypy.translator.platform.test.test_platform import TestPlatform as BasicTest +from pypy.translator.tool.cbuild import ExternalCompilationInfo + +class TestDarwin(BasicTest): + platform = Darwin() + + def test_frameworks(self): + objcfile = udir.join('test_simple.m') + objcfile.write(r''' + #import + #include "test.h" + + int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSArray *args = [[NSProcessInfo processInfo] arguments]; + NSCountedSet *cset = [[NSCountedSet alloc] initWithArray:args]; + + printf("%d\n", XXX_STUFF); + + [cset release]; + [pool release]; + return 0; + } + ''') + includedir = py.magic.autopath().dirpath().join('include') + eci = ExternalCompilationInfo(frameworks=('Cocoa',), + include_dirs=(includedir,)) + executable = self.platform.compile([objcfile], eci) + res = self.platform.execute(executable) + self.check_res(res) + From santagada at codespeak.net Sat Mar 7 00:26:29 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sat, 7 Mar 2009 00:26:29 +0100 (CET) Subject: [pypy-svn] r62675 - pypy/trunk/pypy/rlib/rsdl Message-ID: <20090306232629.8FA25168483@codespeak.net> Author: santagada Date: Sat Mar 7 00:26:29 2009 New Revision: 62675 Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py pypy/trunk/pypy/rlib/rsdl/eci.py Log: removed tons of hacks on the eci code, and reverted a check that made some of test_video fail. Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RSDL.py Sat Mar 7 00:26:29 2009 @@ -227,7 +227,7 @@ # ------------------------------------------------------------------------------ -if sys.platform == 'darwin' and we_are_translated(): +if sys.platform == 'darwin': def Init(flags): if not we_are_translated(): from AppKit import NSApplication Modified: pypy/trunk/pypy/rlib/rsdl/eci.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/eci.py (original) +++ pypy/trunk/pypy/rlib/rsdl/eci.py Sat Mar 7 00:26:29 2009 @@ -6,20 +6,10 @@ def get_rsdl_compilation_info(): if sys.platform == 'darwin': eci = ExternalCompilationInfo( - includes = ['SDL.h', - #'Init.h', - #'SDLMain.m' - #'SDLMain.h'*/ - ], - include_dirs = ['/Library/Frameworks/SDL.framework/Headers', - #str(py.magic.autopath().dirpath().join('macosx-sdl-main')) - ], + includes = ['SDL.h'], + include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], link_extra = [ str(py.magic.autopath().dirpath().join('macosx-sdl-main/SDLMain.m')), - #'macosx-sdl-main/SDLMain.m', - '-I', '/Library/Frameworks/SDL.framework/Headers', - '-framework', 'Cocoa', - '-framework', 'SDL', ], frameworks = ['SDL', 'Cocoa'] ) From arigo at codespeak.net Sat Mar 7 10:15:33 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 10:15:33 +0100 (CET) Subject: [pypy-svn] r62682 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp Message-ID: <20090307091533.A183C168452@codespeak.net> Author: arigo Date: Sat Mar 7 10:15:31 2009 New Revision: 62682 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Fix execute(CALL) to also signal an exception via the mechanism of cpu.get_exception() instead of just raising it. That turns out to be a code simplification, too. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sat Mar 7 10:15:31 2009 @@ -347,9 +347,8 @@ """Execute all operations in a loop, possibly following to other loops as well. """ - global _last_exception, _last_exception_handled - _last_exception = None - _last_exception_handled = True + global _last_exception + assert _last_exception is None, "exception left behind" verbose = True while True: self.opindex += 1 @@ -380,7 +379,6 @@ % (RESTYPE,)) self.env[op.result] = x except GuardFailed: - assert _last_exception_handled if hasattr(op, 'jump_target'): # the guard already failed once, go to the # already-generated code @@ -499,23 +497,22 @@ raise GuardFailed # some other code is already in control def op_guard_no_exception(self, _): - global _last_exception_handled - _last_exception_handled = True if _last_exception: raise GuardFailed def op_guard_exception(self, _, expected_exception): - global _last_exception_handled - _last_exception_handled = True + global _last_exception expected_exception = llmemory.cast_adr_to_ptr( cast_int_to_adr(self.memocast, expected_exception), rclass.CLASSTYPE) assert expected_exception - if _last_exception: - got = _last_exception.args[0] + exc = _last_exception + if exc: + got = exc.args[0] if not rclass.ll_issubclass(got, expected_exception): raise GuardFailed - return _last_exception.args[1] + _last_exception = None + return exc.args[1] else: raise GuardFailed @@ -565,21 +562,14 @@ do_setfield_raw_int(struct, fielddescr, newvalue, self.memocast) def op_call(self, calldescr, func, *args): - global _last_exception, _last_exception_handled _call_args[:] = args - try: - res = _do_call_common(func, self.memocast) - _last_exception = None - return res - except LLException, e: - _last_exception = e - _last_exception_handled = False - if calldescr == sys.maxint: - return None - elif calldescr & 1: - return lltype.nullptr(llmemory.GCREF) - else: - return 0 + if calldescr == sys.maxint: + err_result = None + elif calldescr & 1: + err_result = lltype.nullptr(llmemory.GCREF.TO) + else: + err_result = 0 + return _do_call_common(func, self.memocast, err_result) # ____________________________________________________________ @@ -673,30 +663,31 @@ frame = _from_opaque(frame) return frame.returned_value +_last_exception = None + def get_exception(): - global _last_exception, _last_exception_handled - _last_exception_handled = True if _last_exception: return llmemory.cast_ptr_to_adr(_last_exception.args[0]) else: return llmemory.NULL def get_exc_value(): - global _last_exception, _last_exception_handled - _last_exception_handled = True if _last_exception: return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1]) else: return lltype.nullptr(llmemory.GCREF.TO) +def clear_exception(): + global _last_exception + _last_exception = None + def set_overflow_error(): - global _last_exception, _last_exception_handled + global _last_exception llframe = _llinterp.frame_class(None, None, _llinterp) try: llframe.make_llexception(OverflowError()) except LLException, e: _last_exception = e - _last_exception_handled = False else: assert 0, "should have raised" @@ -844,7 +835,9 @@ def do_call_pushptr(x): _call_args.append(x) -def _do_call_common(f, memocast): +def _do_call_common(f, memocast, err_result=None): + global _last_exception + assert _last_exception is None, "exception left behind" ptr = cast_int_to_adr(memocast, f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS @@ -864,20 +857,24 @@ assert len(ARGS) == len(args) if hasattr(ptr._obj, 'graph'): llinterp = _llinterp # it's a global set here by CPU.__init__() - result = llinterp.eval_graph(ptr._obj.graph, args) + try: + result = llinterp.eval_graph(ptr._obj.graph, args) + except LLException, e: + _last_exception = e + result = err_result else: - result = ptr._obj._callable(*args) + result = ptr._obj._callable(*args) # no exception support in this case return result def do_call_void(f, memocast): _do_call_common(f, memocast) def do_call_int(f, memocast): - x = _do_call_common(f, memocast) + x = _do_call_common(f, memocast, 0) return cast_to_int(x, memocast) def do_call_ptr(f, memocast): - x = _do_call_common(f, memocast) + x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO)) return cast_to_ptr(x) # ____________________________________________________________ @@ -957,6 +954,7 @@ setannotation(get_exception, annmodel.SomeAddress()) setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) +setannotation(clear_exception, annmodel.s_None) setannotation(set_overflow_error, annmodel.s_None) setannotation(new_memo_cast, s_MemoCast) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sat Mar 7 10:15:31 2009 @@ -178,6 +178,9 @@ def get_exc_value(self): return llimpl.get_exc_value() + def clear_exception(self): + llimpl.clear_exception() + def set_overflow_error(self): llimpl.set_overflow_error() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sat Mar 7 10:15:31 2009 @@ -672,7 +672,7 @@ argtypes = [v.concretetype for v in args] resulttype = op.result.concretetype calldescr = self.cpu.calldescrof(argtypes[1:], resulttype) - self.emit('residual_call_%s' % getkind(resulttype)) + self.emit('residual_call') self.emit(calldescr) self.emit_varargs(args) self.register_var(op.result) @@ -716,7 +716,7 @@ if oopspec_name.endswith('_foldable'): opname = 'residual_call_pure' # XXX not for possibly-raising calls else: - opname = 'residual_call_%s' % getkind(resulttype) + opname = 'residual_call' calldescr = self.cpu.calldescrof(argtypes, resulttype) self.emit(opname) self.emit(calldescr) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Mar 7 10:15:31 2009 @@ -241,7 +241,7 @@ exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): - return self.execute_with_exc(rop.%s, [b1, b2], returnsBoxInt) + return self.execute_with_exc(rop.%s, [b1, b2]) ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', @@ -257,7 +257,7 @@ exec py.code.Source(''' @arguments("box") def opimpl_%s(self, b): - return self.execute_with_exc(rop.%s, [b], returnsBoxInt) + return self.execute_with_exc(rop.%s, [b]) ''' % (_opimpl, _opimpl.upper())).compile() @arguments() @@ -398,19 +398,8 @@ return True @arguments("int", "varargs") - def opimpl_residual_call_int(self, calldescr, varargs): - return self.execute_with_exc(rop.CALL, varargs, returnsBoxInt, - descr=calldescr) - - @arguments("int", "varargs") - def opimpl_residual_call_ptr(self, calldescr, varargs): - return self.execute_with_exc(rop.CALL, varargs, returnsBoxPtr, - descr=calldescr) - - @arguments("int", "varargs") - def opimpl_residual_call_void(self, calldescr, varargs): - return self.execute_with_exc(rop.CALL, varargs, returnsNone, - descr=calldescr) + def opimpl_residual_call(self, calldescr, varargs): + return self.execute_with_exc(rop.CALL, varargs, descr=calldescr) @arguments("int", "varargs") def opimpl_residual_call_pure(self, calldescr, varargs): @@ -660,33 +649,17 @@ self.make_result_box(resbox) execute._annspecialcase_ = 'specialize:arg(1)' - def execute_with_exc(self, opnum, argboxes, makeresbox, descr=0): - try: - resbox = executor.execute(self.metainterp.cpu, opnum, argboxes, - descr) - except Exception, e: - if not we_are_translated(): - if not isinstance(e, LLException): - raise - etype, evalue = e.args[:2] - else: - evalue = cast_instance_to_base_ptr(e) - etype = evalue.typeptr - resbox = makeresbox() - else: - if not we_are_translated(): - self.metainterp._debug_history.append(['call', + def execute_with_exc(self, opnum, argboxes, descr=0): + cpu = self.metainterp.cpu + resbox = executor.execute(cpu, opnum, argboxes, descr) + if not we_are_translated(): + self.metainterp._debug_history.append(['call', argboxes[0], argboxes[1:]]) - etype = lltype.nullptr(rclass.OBJECT_VTABLE) - evalue = lltype.nullptr(rclass.OBJECT) # record the operation in the history self.metainterp.history.record(opnum, argboxes, resbox, descr) if resbox is not None: self.make_result_box(resbox) - type_as_int = self.metainterp.cpu.cast_adr_to_int( - llmemory.cast_ptr_to_adr(etype)) - value_as_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, evalue) - return self.metainterp.handle_exception(type_as_int, value_as_gcref) + return self.metainterp.handle_exception() # ____________________________________________________________ @@ -822,7 +795,7 @@ try: if guard_failure.guard_op.opnum in (rop.GUARD_EXCEPTION, rop.GUARD_NO_EXCEPTION): - self.raise_exception_upon_guard_failure() + self.handle_exception() self.interpret() assert False, "should always raise" except GenerateMergePoint, gmp: @@ -956,12 +929,10 @@ self.rebuild_state_after_failure(guard_op.key, newboxes) return boxes_from_frame - def raise_exception_upon_guard_failure(self): + def handle_exception(self): etype = self.cpu.get_exception() evalue = self.cpu.get_exc_value() - self.handle_exception(etype, evalue) - - def handle_exception(self, etype, evalue): + self.cpu.clear_exception() frame = self.framestack[-1] if etype: exception_box = ConstInt(etype) @@ -1020,8 +991,3 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args - - -def returnsBoxInt(): return BoxInt() -def returnsBoxPtr(): return BoxPtr() -def returnsNone(): return None From arigo at codespeak.net Sat Mar 7 10:23:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 10:23:39 +0100 (CET) Subject: [pypy-svn] r62683 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090307092339.E1B4F16845C@codespeak.net> Author: arigo Date: Sat Mar 7 10:23:38 2009 New Revision: 62683 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Introduce an exception that makes crashes more explicit. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sat Mar 7 10:23:38 2009 @@ -367,6 +367,8 @@ def __init__(self, cpu): self.cpu = cpu self.operations = [] + def record(self, opnum, argboxes, resbox, descr=0): + raise NotImplementedError class History(RunningMatcher): def record(self, opnum, argboxes, resbox, descr=0): @@ -444,6 +446,10 @@ graphs.append(graph) ResOpGraphPage(graphs, errmsg, highlightops).display() + +class CrashInJIT(Exception): + pass + # ---------------------------------------------------------------- class Options: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sat Mar 7 10:23:38 2009 @@ -142,7 +142,7 @@ import sys, pdb; pdb.post_mortem(sys.exc_info()[2]) else: print e - raise AssertionError("crash in JIT") + raise history.CrashInJIT("crash in JIT") crash_in_jit._dont_inline_ = True def maybe_enter_jit(*args): From fijal at codespeak.net Sat Mar 7 10:23:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 10:23:40 +0100 (CET) Subject: [pypy-svn] r62684 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090307092340.1CC92168452@codespeak.net> Author: fijal Date: Sat Mar 7 10:23:39 2009 New Revision: 62684 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/ri386.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Log: Translation fixes. ovf error is now handled correctly (by address, which survives translation) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sat Mar 7 10:23:39 2009 @@ -219,9 +219,11 @@ loc = locs[i] if isinstance(loc, REG): self.mc2.MOV(stack_pos(stacklocs[i]), loc) - self.mc2.MOV(eax, imm(self._ovf_error_vtable)) + ovf_error_vtable = self.cpu.cast_adr_to_int(self._ovf_error_vtable) + self.mc2.MOV(eax, imm(ovf_error_vtable)) self.mc2.MOV(addr_add(imm(self._exception_addr), imm(0)), eax) - self.mc2.MOV(eax, imm(self._ovf_error_inst)) + ovf_error_instance = self.cpu.cast_adr_to_int(self._ovf_error_inst) + self.mc2.MOV(eax, imm(ovf_error_instance)) self.mc2.MOV(addr_add(imm(self._exception_addr), imm(WORD)), eax) self.mc2.PUSH(esp) # frame address self.mc2.PUSH(imm(index)) # index of guard that failed @@ -392,10 +394,10 @@ self.mc.MOV(addr_add(base_loc, ofs_loc, baseofs.value, scale_loc.value), value_loc) elif scale_loc.value == 0: - self.mc.MOV(addr_add8(base_loc, ofs_loc, baseofs.value, + self.mc.MOV(addr8_add(base_loc, ofs_loc, baseofs.value, scale_loc.value), lower_byte(value_loc)) else: - raise NotImplementedError("scale = %d" % scale) + raise NotImplementedError("scale = %d" % scale_loc.value) def genop_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/ri386.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/ri386.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/ri386.py Sat Mar 7 10:23:39 2009 @@ -1,5 +1,5 @@ from pypy.rlib.rarithmetic import intmask -from pypy.rlib.objectmodel import ComputedIntSymbolic +from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated class OPERAND(object): _attrs_ = [] @@ -246,7 +246,8 @@ def imm(value): if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() - assert isinstance(value, int) + if not we_are_translated(): + assert type(value) is int if single_byte(value): return imm8(value) else: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sat Mar 7 10:23:39 2009 @@ -65,19 +65,13 @@ self.generated_mps = {} def _setup_ovf_error(self): - if self.translate_support_code: - self.assembler._ovf_error_vtable = 0 - self.assembler._ovf_error_inst = 0 - xxx - # do something here - else: - bk = self.rtyper.annotator.bookkeeper - clsdef = bk.getuniqueclassdef(OverflowError) - ovferror_repr = rclass.getclassrepr(self.rtyper, clsdef) - ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance( - self.rtyper, clsdef) - self.assembler._ovf_error_vtable = self.cast_ptr_to_int(ll_inst.typeptr) - self.assembler._ovf_error_inst = self.cast_ptr_to_int(ll_inst) + bk = self.rtyper.annotator.bookkeeper + clsdef = bk.getuniqueclassdef(OverflowError) + ovferror_repr = rclass.getclassrepr(self.rtyper, clsdef) + ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance( + self.rtyper, clsdef) + self.assembler._ovf_error_vtable = llmemory.cast_ptr_to_adr(ll_inst.typeptr) + self.assembler._ovf_error_inst = llmemory.cast_ptr_to_adr(ll_inst) def setup(self): self.assembler = Assembler386(self, self.translate_support_code) @@ -464,6 +458,7 @@ v = ord(rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[ofs]) elif size == 2: v = rffi.cast(rffi.CArrayPtr(rffi.USHORT), gcref)[ofs/2] + v = rffi.cast(lltype.Signed, v) elif size == WORD: v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs/WORD] if ptr: @@ -486,7 +481,7 @@ v = vbox.getint() rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[ofs] = chr(v) elif size == 2: - v = vbox.getint() + v = rffi.cast(rffi.USHORT, vbox.getint()) rffi.cast(rffi.CArrayPtr(rffi.USHORT), gcref)[ofs/2] = v elif size == WORD: a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Sat Mar 7 10:23:39 2009 @@ -10,6 +10,9 @@ GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) +def gc_malloc(size): + return llop.call_boehm_gc_alloc(llmemory.Address, size) + def gc_malloc_fnaddr(): """Returns the address of the Boehm 'malloc' function.""" if we_are_translated(): From arigo at codespeak.net Sat Mar 7 10:56:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 10:56:32 +0100 (CET) Subject: [pypy-svn] r62685 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090307095632.661E0168479@codespeak.net> Author: arigo Date: Sat Mar 7 10:56:28 2009 New Revision: 62685 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Add debugging code. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Mar 7 10:56:28 2009 @@ -347,6 +347,7 @@ self.nodes[box] = InstanceNode(box, escaped=False, startbox=True, const=isinstance(box, Const)) for op in self.loop.operations: + #print '| ' + op.repr() opnum = op.opnum if (opnum == rop.MERGE_POINT or opnum == rop.CATCH or Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Mar 7 10:56:28 2009 @@ -599,6 +599,7 @@ while True: pc = self.pc op = ord(self.bytecode[pc]) + #print self.metainterp.opcode_names[op] self.pc = pc + 1 stop = self.metainterp.opcode_implementations[op](self, pc) #self.metainterp.most_recent_mp = None @@ -676,6 +677,7 @@ # { greenkey: list-of-MergePoints } self.opcode_implementations = [] + self.opcode_names = [] self.opname_to_index = {} self.class_sizes = populate_type_cache(graphs, self.cpu) @@ -978,6 +980,7 @@ "too many implementations of opcodes!" name = "opimpl_" + opname self.opname_to_index[opname] = len(self.opcode_implementations) + self.opcode_names.append(opname) self.opcode_implementations.append(getattr(MIFrame, name).im_func) def find_opcode(self, name): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sat Mar 7 10:56:28 2009 @@ -29,16 +29,20 @@ self.descr = descr def __repr__(self): - if self.result is not None: - sres = repr(self.result) + ' = ' - else: - sres = '' - result = '%s%s(%s)' % (sres, self.getopname(), - ', '.join(map(repr, self.args))) + result = self.repr() if self.liveboxes is not None: result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) return result + def repr(self): + # RPython-friendly version + if self.result is not None: + sres = '%s = ' % (self.result,) + else: + sres = '' + return '%s%s(%s)' % (sres, self.getopname(), + ', '.join([str(a) for a in self.args])) + def clone(self): op = ResOperation(self.opnum, self.args, self.result, self.descr) op.specnodes = self.specnodes From arigo at codespeak.net Sat Mar 7 10:57:15 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 10:57:15 +0100 (CET) Subject: [pypy-svn] r62686 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090307095715.836EB16847F@codespeak.net> Author: arigo Date: Sat Mar 7 10:57:14 2009 New Revision: 62686 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Fix bug! Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Mar 7 10:57:14 2009 @@ -951,7 +951,7 @@ def rebuild_state_after_failure(self, key, newboxes): if not we_are_translated(): self._debug_history.append(['guard_failure', None, None]) - self.framestack = [] + self.framestack = [] nbindex = 0 for jitcode, pc, envlength, exception_target in key: f = self.newframe(jitcode) From fijal at codespeak.net Sat Mar 7 11:14:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 11:14:18 +0100 (CET) Subject: [pypy-svn] r62687 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090307101418.922CE1683FD@codespeak.net> Author: fijal Date: Sat Mar 7 11:14:17 2009 New Revision: 62687 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: make exception work (not yet translated). I'm not sure about the solution, but it seems we have to copy exception on side when we encounter it (since handling exception is just more rpython code) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sat Mar 7 11:14:17 2009 @@ -30,24 +30,23 @@ self.mc2 = None self.rtyper = cpu.rtyper self.malloc_func_addr = 0 - if translate_support_code: - self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) - self._exception_addr = 0 - # patched later, after exc transform - else: - self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, - zero=True, flavor='raw') - self._exception_addr = cpu.cast_ptr_to_int(self._exception_data) + self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) + self._exception_addr = 0 def make_sure_mc_exists(self): if self.mc is None: # we generate the loop body in 'mc' # 'mc2' is for guard recovery code - # XXX we should catch the real one, somehow self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, zero=True, flavor='raw') self._exception_addr = self.cpu.cast_ptr_to_int( self._exception_data) + # a backup, in case our exception can be somehow mangled, + # by a handling code + self._exception_bck = lltype.malloc(rffi.CArray(lltype.Signed), 2, + zero=True, flavor='raw') + self._exception_bck_addr = self.cpu.cast_ptr_to_int( + self._exception_bck) self.mc = codebuf.MachineCodeBlock(self.MC_SIZE) self.mc2 = codebuf.MachineCodeBlock(self.MC_SIZE) self.generic_return_addr = self.assemble_generic_return() @@ -221,10 +220,10 @@ self.mc2.MOV(stack_pos(stacklocs[i]), loc) ovf_error_vtable = self.cpu.cast_adr_to_int(self._ovf_error_vtable) self.mc2.MOV(eax, imm(ovf_error_vtable)) - self.mc2.MOV(addr_add(imm(self._exception_addr), imm(0)), eax) + self.mc2.MOV(addr_add(imm(self._exception_bck_addr), imm(0)), eax) ovf_error_instance = self.cpu.cast_adr_to_int(self._ovf_error_inst) self.mc2.MOV(eax, imm(ovf_error_instance)) - self.mc2.MOV(addr_add(imm(self._exception_addr), imm(WORD)), eax) + self.mc2.MOV(addr_add(imm(self._exception_bck_addr), imm(WORD)),eax) self.mc2.PUSH(esp) # frame address self.mc2.PUSH(imm(index)) # index of guard that failed self.mc2.CALL(rel32(self.cpu.get_failure_recovery_func_addr())) @@ -501,6 +500,16 @@ loc = locs[i] if isinstance(loc, REG): self.mc2.MOV(stack_pos(stacklocs[i]), loc) + if (guard_op.opnum == rop.GUARD_EXCEPTION or + guard_op.opnum == rop.GUARD_NO_EXCEPTION): + self.mc2.MOV(eax, heap(self._exception_addr)) + self.mc2.MOV(heap(self._exception_bck_addr), eax) + self.mc2.MOV(eax, addr_add(imm(self._exception_addr), imm(WORD))) + self.mc2.MOV(addr_add(imm(self._exception_bck_addr), imm(WORD)), + eax) + # clean up the original exception, we don't want + # to enter more rpython code with exc set + self.mc2.MOV(heap(self._exception_addr), imm(0)) self.mc2.PUSH(esp) # frame address self.mc2.PUSH(imm(index)) # index of guard that failed self.mc2.CALL(rel32(self.cpu.get_failure_recovery_func_addr())) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sat Mar 7 11:14:17 2009 @@ -136,12 +136,20 @@ self.metainterp = metainterp def get_exception(self): - res = self.assembler._exception_data[0] - self.assembler._exception_data[0] = 0 - return res + self.assembler.make_sure_mc_exists() + return self.assembler._exception_bck[0] def get_exc_value(self): - return self.cast_int_to_gcref(self.assembler._exception_data[1]) + return self.cast_int_to_gcref(self.assembler._exception_bck[1]) + + def clear_exception(self): + self.assembler._exception_bck[0] = 0 + + def set_overflow_error(self): + ovf_vtable = self.cast_adr_to_int(self.assembler._ovf_error_vtable) + ovf_inst = self.cast_adr_to_int(self.assembler._ovf_error_inst) + self.assembler._exception_bck[0] = ovf_vtable + self.assembler._exception_bck[1] = ovf_inst # def execute_operation(self, opnum, valueboxes, result_type): # xxx @@ -543,16 +551,10 @@ else: self.return_value_type = INT result = self.execute_operations_in_new_frame('call', mp, args) - if not we_are_translated(): - exc = self.get_exception() - if exc: - TP = lltype.Ptr(rclass.OBJECT_VTABLE) - TP_V = lltype.Ptr(rclass.OBJECT) - exc_t_a = self.cast_int_to_adr(exc) - exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP) - exc_v_a = self.get_exc_value() - exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a) - raise LLException(exc_type, exc_val) + # XXX I'm not sure if we're supposed to do that here, probably only + # in assembler + self.assembler._exception_bck[0] = self.assembler._exception_data[0] + self.assembler._exception_bck[1] = self.assembler._exception_data[1] return result # ------------------- helpers and descriptions -------------------- Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Sat Mar 7 11:14:17 2009 @@ -537,3 +537,6 @@ assert x.value == 142 s = execute(cpu, rop.NEWSTR, [BoxInt(8)]) assert len(s.getptr(lltype.Ptr(rstr.STR)).chars) == 8 + # XXX cannot work without rtyper + #s = execute(cpu, rop.INT_MUL_OVF, [BoxInt(sys.maxint/2), BoxInt(10)]) + #assert cpu.get_exception() From fijal at codespeak.net Sat Mar 7 11:27:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 11:27:14 +0100 (CET) Subject: [pypy-svn] r62688 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090307102714.A77EF168445@codespeak.net> Author: fijal Date: Sat Mar 7 11:27:14 2009 New Revision: 62688 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: I were right. We're not suppose to do such tricks here. Move it to assembler Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sat Mar 7 11:27:14 2009 @@ -432,6 +432,16 @@ if loc is not eax: self.mc.MOV(eax, loc) self.mc.ADD(esp, imm(FRAMESIZE)) + # copy exception to some safe place and clean the original + # one + self.mc.MOV(ecx, heap(self._exception_addr)) + self.mc.MOV(heap(self._exception_bck_addr), ecx) + self.mc.MOV(ecx, addr_add(imm(self._exception_addr), imm(WORD))) + self.mc.MOV(addr_add(imm(self._exception_bck_addr), imm(WORD)), + ecx) + # clean up the original exception, we don't want + # to enter more rpython code with exc set + self.mc.MOV(heap(self._exception_addr), imm(0)) self.mc.RET() def genop_jump(self, op, locs): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sat Mar 7 11:27:14 2009 @@ -551,10 +551,6 @@ else: self.return_value_type = INT result = self.execute_operations_in_new_frame('call', mp, args) - # XXX I'm not sure if we're supposed to do that here, probably only - # in assembler - self.assembler._exception_bck[0] = self.assembler._exception_data[0] - self.assembler._exception_bck[1] = self.assembler._exception_data[1] return result # ------------------- helpers and descriptions -------------------- From arigo at codespeak.net Sat Mar 7 11:28:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 11:28:00 +0100 (CET) Subject: [pypy-svn] r62689 - in pypy/branch/pyjitpl5/pypy: rpython/lltypesystem translator translator/test Message-ID: <20090307102800.DFAD4168445@codespeak.net> Author: arigo Date: Sat Mar 7 11:27:55 2009 New Revision: 62689 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py pypy/branch/pyjitpl5/pypy/translator/test/test_exceptiontransform.py Log: Add two operations to be used by the JIT: get_exception_addr and get_exc_value_addr, returning the address of where the exceptions are stored (i.e. inside the exc_data introduced by the exception transformer). Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py Sat Mar 7 11:27:55 2009 @@ -395,6 +395,8 @@ 'call_boehm_gc_alloc': LLOp(canraise=(MemoryError,)), 'jit_marker': LLOp(), 'promote_virtualizable':LLOp(canrun=True), + 'get_exception_addr': LLOp(), + 'get_exc_value_addr': LLOp(), # __________ GC operations __________ Modified: pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py Sat Mar 7 11:27:55 2009 @@ -133,6 +133,8 @@ rpyexc_restore_exception, [self.lltype_of_exception_value], lltype.Void) + self.build_extra_funcs() + self.mixlevelannotator.finish() self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping() @@ -192,13 +194,20 @@ # order of transformations is important - but the gctransformer will # put them in a new graph, so all transformations will run again. for i in range(len(block.operations)): - if block.operations[i].opname == 'gc_fetch_exception': + opname = block.operations[i].opname + if opname == 'gc_fetch_exception': block.operations[i].opname = "direct_call" block.operations[i].args = [self.rpyexc_fetch_exception_ptr] - if block.operations[i].opname == 'gc_restore_exception': + if opname == 'gc_restore_exception': block.operations[i].opname = "direct_call" block.operations[i].args.insert(0, self.rpyexc_restore_exception_ptr) + if opname == 'get_exception_addr': # only for lltype + block.operations[i].opname = "direct_call" + block.operations[i].args.insert(0, self.rpyexc_get_exception_addr_ptr) + if opname == 'get_exc_value_addr': # only for lltype + block.operations[i].opname = "direct_call" + block.operations[i].args.insert(0, self.rpyexc_get_exc_value_addr_ptr) def transform_block(self, graph, block): need_exc_matching = False @@ -380,6 +389,7 @@ self.gen_setfield('exc_type', self.c_null_etype, llops) normalafterblock.operations[:0] = llops + class LLTypeExceptionTransformer(BaseExceptionTransformer): def setup_excdata(self): @@ -433,6 +443,29 @@ return True return False + def build_extra_funcs(self): + EXCDATA = self.EXCDATA + exc_data = self.exc_data_ptr + + def rpyexc_get_exception_addr(): + return (llmemory.cast_ptr_to_adr(exc_data) + + llmemory.offsetof(EXCDATA, 'exc_type')) + + def rpyexc_get_exc_value_addr(): + return (llmemory.cast_ptr_to_adr(exc_data) + + llmemory.offsetof(EXCDATA, 'exc_value')) + + self.rpyexc_get_exception_addr_ptr = self.build_func( + "RPyGetExceptionAddr", + rpyexc_get_exception_addr, + [], llmemory.Address) + + self.rpyexc_get_exc_value_addr_ptr = self.build_func( + "RPyGetExcValueAddr", + rpyexc_get_exc_value_addr, + [], llmemory.Address) + + class OOTypeExceptionTransformer(BaseExceptionTransformer): def setup_excdata(self): Modified: pypy/branch/pyjitpl5/pypy/translator/test/test_exceptiontransform.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/test/test_exceptiontransform.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/test/test_exceptiontransform.py Sat Mar 7 11:27:55 2009 @@ -234,6 +234,21 @@ # checking assert summary(g) == {'int_gt': 1, 'int_add': 1, 'direct_call': 1} + def test_get_exception_addr(self): + from pypy.rpython.lltypesystem import lltype, llmemory + from pypy.rpython.lltypesystem.lloperation import llop + def foo(): + # a bit hard to test, really + a = llop.get_exception_addr(llmemory.Address) + assert lltype.typeOf(a) is llmemory.Address + a = llop.get_exc_value_addr(llmemory.Address) + assert lltype.typeOf(a) is llmemory.Address + return 42 + f = self.compile(foo, []) + res = f() + assert res == 42 + + class TestOOType(BaseTestExceptionTransform): type_system = 'ootype' From fijal at codespeak.net Sat Mar 7 11:39:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 11:39:29 +0100 (CET) Subject: [pypy-svn] r62690 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090307103929.D41E7168446@codespeak.net> Author: fijal Date: Sat Mar 7 11:39:29 2009 New Revision: 62690 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: good, now test_exception_from_outside passes. A bit hackish... I'll fix it I promise Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sat Mar 7 11:39:29 2009 @@ -2,8 +2,9 @@ import ctypes from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.history import Const, ConstInt, Box -from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr +from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory from pypy.rpython.lltypesystem.rclass import OBJECT +from pypy.rpython.lltypesystem.lloperation import llop from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, @@ -37,14 +38,18 @@ if self.mc is None: # we generate the loop body in 'mc' # 'mc2' is for guard recovery code - self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, - zero=True, flavor='raw') + if we_are_translated(): + addr = llop.get_exception_addr(llmemory.Address) + self._exception_data = llmemory.cast_adr_to_ptr(addr, rffi.CArrayPtr(lltype.Signed)) + else: + self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2, + zero=True, flavor='raw') self._exception_addr = self.cpu.cast_ptr_to_int( self._exception_data) # a backup, in case our exception can be somehow mangled, # by a handling code self._exception_bck = lltype.malloc(rffi.CArray(lltype.Signed), 2, - zero=True, flavor='raw') + zero=True, flavor='raw') self._exception_bck_addr = self.cpu.cast_ptr_to_int( self._exception_bck) self.mc = codebuf.MachineCodeBlock(self.MC_SIZE) From arigo at codespeak.net Sat Mar 7 11:57:52 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 11:57:52 +0100 (CET) Subject: [pypy-svn] r62691 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090307105752.55AFE16844C@codespeak.net> Author: arigo Date: Sat Mar 7 11:57:50 2009 New Revision: 62691 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Log: Easiest fix for test_zrpy_virtualizable: just kill all this code, it contains only half of what would be needed, but it's not used at all. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Sat Mar 7 11:57:50 2009 @@ -12,68 +12,3 @@ "NOT_RPYTHON" self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for name in TOPSTRUCT._hints['virtuals']] - initialize_virtualizable(cpu, TOPSTRUCT.access) - self.vable_base = cpu.fielddescrof(TOPSTRUCT, 'vable_base') - self.vable_rti = cpu.fielddescrof(TOPSTRUCT, 'vable_rti') - self.c_vable_base = history.ConstInt(self.vable_base) - self.c_vable_rti = history.ConstInt(self.vable_rti) - -def initialize_virtualizable(cpu, access): - if not hasattr(cpu, '_seen_virtualizables'): - cpu._seen_virtualizables = {} - if access in cpu._seen_virtualizables: - return - cpu._seen_virtualizables[access] = True - for fieldname in access.redirected_fields: - initialize_vable_field(cpu, access, fieldname) - for subaccess in access.subaccessors: - initialize_virtualizable(cpu, subaccess) - if access.parent is not None: - initialize_virtualizable(cpu, access.parent) - -def initialize_vable_field(cpu, access, fieldname): - FIELDTYPE = getattr(access.STRUCT, fieldname) - if FIELDTYPE is lltype.Void: - return - type = history.getkind_num(cpu, FIELDTYPE) - ofs = cpu.fielddescrof(access.STRUCT, fieldname) - getset = access.getsets[fieldname] - - def getter(instanceptr): - rti = instanceptr.vable_rti - if we_are_translated(): - rti = cast_base_ptr_to_instance(VirtualizableRTI, rti) - instanceptr = lltype.cast_opaque_ptr(llmemory.GCREF, instanceptr) - box = rti.get_field(instanceptr, ofs, type) - if type == 'ptr': - return box.getptr(RESTYPE) - else: - return lltype.cast_primitive(RESTYPE, box.getint()) - - def setter(instanceptr, value): - rti = instanceptr.vable_rti - if we_are_translated(): - rti = cast_base_ptr_to_instance(VirtualizableRTI, rti) - instanceadr = lltype.cast_opaque_ptr(llmemory.GCREF, instanceptr) - if type == 'ptr': - valuebox = BoxPtr(llmemory.cast_ptr_to_adr(value)) - else: - valuebox = BoxInt(lltype.cast_primitive(lltype.Signed, value)) - rti.set_field(instanceadr, ofs, type, valuebox) - - GETSET = lltype.typeOf(getset).TO - RESTYPE = GETSET.get.TO.RESULT - if cpu.translate_support_code: - mixlevelann = cpu.mixlevelann - getset.get = mixlevelann.delayedfunction(getter, - [lltype_to_annotation(t) for t in GETSET.get.TO.ARGS], - lltype_to_annotation(GETSET.get.TO.RESULT), - needtype=True) - getset.set = mixlevelann.delayedfunction(setter, - [lltype_to_annotation(t) for t in GETSET.set.TO.ARGS], - lltype_to_annotation(GETSET.set.TO.RESULT), - needtype=True) - else: - # for testing: when the cpu and the metainterp are not translated - getset.get = llhelper(GETSET.get, getter) - getset.set = llhelper(GETSET.set, setter) From fijal at codespeak.net Sat Mar 7 12:11:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 12:11:20 +0100 (CET) Subject: [pypy-svn] r62692 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090307111120.30971168444@codespeak.net> Author: fijal Date: Sat Mar 7 12:11:19 2009 New Revision: 62692 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py Log: skip checking loops Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py Sat Mar 7 12:11:19 2009 @@ -8,6 +8,9 @@ def meta_interp(fn, args, **kwds): return c_meta_interp(fn, args, **kwds) + def check_loops(self, *args, **kwds): + pass + class TestSList(Jit386Mixin, ListTests): # for the individual tests see # ====> ../../test/test_slist.py From fijal at codespeak.net Sat Mar 7 12:12:07 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 12:12:07 +0100 (CET) Subject: [pypy-svn] r62693 - pypy/branch/pyjitpl5/pypy/translator/c Message-ID: <20090307111207.419E716844B@codespeak.net> Author: fijal Date: Sat Mar 7 12:12:06 2009 New Revision: 62693 Modified: pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py Log: (empty for now) promote_virtualizable op Modified: pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py Sat Mar 7 12:12:06 2009 @@ -775,5 +775,8 @@ def OP_JIT_MARKER(self, op): return '/* JIT_MARKER %s */' % op + def OP_PROMOTE_VIRTUALIZABLE(self, op): + return '/* PROMOTE_VIRTUALIZABLE %s */' % op + assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) From cami at codespeak.net Sat Mar 7 12:50:45 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 7 Mar 2009 12:50:45 +0100 (CET) Subject: [pypy-svn] r62694 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090307115045.741D616844B@codespeak.net> Author: cami Date: Sat Mar 7 12:50:44 2009 New Revision: 62694 Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/sound.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: cleaning the sound Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Sat Mar 7 12:50:44 2009 @@ -38,8 +38,8 @@ self.timer = Timer(self.interrupt) self.joypad = Joypad(self.joypad_driver, self.interrupt) self.video = Video(self.video_driver, self.interrupt, self) - #self.sound = Sound(self.sound_driver) - self.sound = BogusSound() + self.sound = Sound(self.sound_driver) + #self.sound = BogusSound() def get_cartridge_manager(self): return self.cartridge_manager Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Sat Mar 7 12:50:44 2009 @@ -13,10 +13,10 @@ import time use_rsdl = True -show_metadata = True # Extends the window with windows visualizing meta-data +show_metadata = False # Extends the window with windows visualizing meta-data if use_rsdl: - from pypy.rlib.rsdl import RSDL, RSDL_helper + from pypy.rlib.rsdl import RSDL, RSDL_helper, RMix from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.objectmodel import specialize import time @@ -241,14 +241,20 @@ """ def __init__(self): SoundDriver.__init__(self) + self.enabled = False + self.sampleRate = 44100 + self.chunksize = 1024 + self.channelCount = 2 + self.bitsPerSample = 4 self.create_sound_driver() - self.enabled = True - self.sampleRate = 44100 - self.channelCount = 2 - self.bitsPerSample = 8 def create_sound_driver(self): - pass + if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, + self.channelCount, self.chunksize) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) + else: + self.enabled = True def start(self): pass @@ -257,6 +263,7 @@ pass def write(self, buffer, length): + if not self.enabled: return pass Modified: pypy/trunk/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/sound.py (original) +++ pypy/trunk/pypy/lang/gameboy/sound.py Sat Mar 7 12:50:44 2009 @@ -2,6 +2,60 @@ PyGirl Emulator Audio Processor Unit (Sharp LR35902 APU) + +There are two sound channels connected to the output +terminals SO1 and SO2. There is also a input terminal Vin +connected to the cartridge. It can be routed to either of +both output terminals. GameBoy circuitry allows producing +sound in four different ways: + + Quadrangular wave patterns with sweep and envelope functions. + Quadrangular wave patterns with envelope functions. + Voluntary wave patterns from wave RAM. + White noise with an envelope function. + +These four sounds can be controlled independantly and +then mixed separately for each of the output terminals. + + Sound registers may be set at all times while producing +sound. + +When setting the initial value of the envelope and +restarting the length counter, set the initial flag to 1 +and initialize the data. + + Under the following situations the Sound ON flag is +reset and the sound output stops: + + 1. When the sound output is stopped by the length counter. + 2. When overflow occurs at the addition mode while sweep + is operating at sound 1. + +When the Sound OFF flag for sound 3 (bit 7 of NR30) is +set at 0, the cancellation of the OFF mode must be done +by setting the sound OFF flag to 1. By initializing +sound 3, it starts it's function. + +When the All Sound OFF flag (bit 7 of NR52) is set to 0, +the mode registers for sounds 1,2,3, and 4 are reset and +the sound output stops. (NOTE: The setting of each sounds +mode register must be done after the All Sound OFF mode +is cancelled. During the All Sound OFF mode, each sound +mode register cannot be set.) + +NOTE: DURING THE ALL SOUND OFF MODE, GB POWER CONSUMPTION +DROPS BY 16% OR MORE! WHILE YOUR PROGRAMS AREN'T USING +SOUND THEN SET THE ALL SOUND OFF FLAG TO 0. IT DEFAULTS +TO 1 ON RESET. + + These tend to be the two most important equations in +converting between Hertz and GB frequency registers: +(Sounds will have a 2.4% higher frequency on Super GB.) + + gb = 2048 - (131072 / Hz) + + Hz = 131072 / (2048 - gb) + """ from pypy.lang.gameboy.constants import * @@ -20,11 +74,6 @@ self.envelope = 0 self.frequency = 0 self.playback = 0 - self.nr0 = 0 - self.nr1 = 0 - self.nr2 = 0 - self.nr4 = 0 - self.nr3 = 0 self.index = 0 self.length = 0 self.frequency = 0 @@ -68,6 +117,9 @@ def set_playback(self, playback): self.playback = playback + def mix_audio(self, buffer, length, output_terminal): + pass + # ------------------------------------------------------------------------------ @@ -78,12 +130,15 @@ def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) self.sample_sweep = 0 + self.raw_sample_sweep = 0 self.index = 0 self.length = 0 + self.raw_length = 0 self.volume = 0 self.envelope_length = 0 self.sample_sweep_length = 0 self.frequency = 0 + self.raw_frequency = 0 def reset(self): Channel.reset(self) @@ -95,17 +150,18 @@ # Audio Channel 1 def get_sweep(self): - return self.sample_sweep + return self.raw_sample_sweep def set_sweep(self, data): - self.sample_sweep = data + self.raw_sample_sweep = data self.sample_sweep_length = (SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) - + def get_length(self): + return self.raw_length + def set_length(self, data): - self.length = data - self.length = (SOUND_CLOCK / 256) * \ - (64 - (self.length & 0x3F)) + self.raw_length = data + self.length = (SOUND_CLOCK / 256) * (64 - (self.raw_length & 0x3F)) def set_envelope(self, data): self.envelope = data @@ -113,23 +169,21 @@ return if (self.envelope >> 4) == 0: self.volume = 0 - elif self.envelope_length == 0 and \ - (self.envelope & 0x07) == 0: + elif self.envelope_length == 0 and (self.envelope & 0x07) == 0: self.volume = (self.volume + 1) & 0x0F else: self.volume = (self.volume + 2) & 0x0F def set_frequency(self, data): - # TODO make sure get and set frequency will work - self.frequency = data - index = self.frequency + ((self.playback & 0x07) << 8) + self.raw_frequency = data + index = self.raw_frequency + ((self.playback & 0x07) << 8) self.frequency = self.frequency_table[index] def set_playback(self, data): self.playback = data - index = self.frequency + ((self.playback & 0x07) << 8) + index = self.raw_frequency + ((self.playback & 0x07) << 8) self.frequency = self.frequency_table[index] if (self.playback & 0x80) != 0: self.enabled = True @@ -137,10 +191,9 @@ self.length = (SOUND_CLOCK / 256) * \ (64 - (self.length & 0x3F)) self.sample_sweep_length = (SOUND_CLOCK / 128) * \ - ((self.sample_sweep >> 4) & 0x07) + ((self.raw_sample_sweep >> 4) & 0x07) self.volume = self.envelope >> 4 - self.envelope_length = (SOUND_CLOCK / 64) * \ - (self.envelope & 0x07) + self.envelope_length = (SOUND_CLOCK / 64) * (self.envelope & 0x07) def update_enable(self): if (self.playback & 0x40) != 0 and self.length > 0: @@ -165,21 +218,21 @@ self.sample_sweep_length-=1 if self.sample_sweep_length > 0: return - sweep_steps = (self.sample_sweep & 0x07) + sweep_steps = (self.raw_sample_sweep & 0x07) if sweep_steps != 0: self.update_frequency(sweep_steps) self.sample_sweep_length += (SOUND_CLOCK / 128) * \ - ((self.sample_sweep >> 4) & 0x07) + ((self.raw_sample_sweep >> 4) & 0x07) def update_frequency(self, sweep_steps): frequency = ((self.playback & 0x07) << 8) + self.frequency - if (self.sample_sweep & 0x08) != 0: + if (self.raw_sample_sweep & 0x08) != 0: frequency -= frequency >> sweep_steps else: frequency += frequency >> sweep_steps if frequency < 2048: self.frequency = self.frequency_table[frequency] - self.frequency = frequency & 0xFF + self.raw_frequency = frequency & 0xFF self.playback = (self.playback & 0xF8) + \ ((frequency >> 8) & 0x07) else: @@ -205,11 +258,11 @@ def get_current_wave_pattern(self): wave_pattern = 0x18 - if (self.length & 0xC0) == 0x00: + if (self.raw_length & 0xC0) == 0x00: wave_pattern = 0x04 - elif (self.length & 0xC0) == 0x40: + elif (self.raw_length & 0xC0) == 0x40: wave_pattern = 0x08 - elif (self.length & 0xC0) == 0x80: + elif (self.raw_length & 0xC0) == 0x80: wave_pattern = 0x10 return wave_pattern << 22 @@ -224,7 +277,9 @@ self.level = 0 self.index = 0 self.length = 0 + self.raw_length = 0 self.frequency = 0 + self.raw_frequency = 0 self.wave_pattern = [0]*16 def reset(self): @@ -234,45 +289,44 @@ self.set_level(0x9F) self.set_frequency(0xFF) self.set_playback(0xBF) - - + def get_enable(self): return self.enable - def get_level(self): - return self.level - - #FIXME strange number here - def get_frequency(self): - return self.frequency - def set_enable(self, data): self.enable = data & 0x80 if (self.enable & 0x80) == 0: self.enabled = False - - def set_length(self, data): - self.length = data - self.length = (SOUND_CLOCK / 256) * \ - (256 - self.length) - + + def get_level(self): + return self.level + def set_level(self, data): self.level = data + + def get_length(self): + return self.raw_length + + def set_length(self, data): + self.raw_length = data + self.length = (SOUND_CLOCK / 256) * (256 - self.raw_length) + + def get_frequency(self): + return self.raw_frequency def set_frequency(self, data): - self.frequency = data - index = ((self.playback & 0x07) << 8) + self.frequency + self.raw_frequency = data + index = ((self.playback & 0x07) << 8) + self.raw_frequency self.frequency = self.frequency_table[index] >> 1 def set_playback(self, data): self.playback = data - index = ((self.playback & 0x07) << 8) + self.frequency + index = ((self.playback & 0x07) << 8) + self.raw_frequency self.frequency = self.frequency_table[index] >> 1 if (self.playback & 0x80) != 0 and (self.enable & 0x80) != 0: self.enabled = True if (self.playback & 0x40) != 0 and self.length == 0: - self.length = (SOUND_CLOCK / 256) *\ - (256 - self.length) + self.length = (SOUND_CLOCK / 256) * (256 - self.raw_length) def set_wave_pattern(self, address, data): self.wave_pattern[address & 0x0F] = data @@ -305,11 +359,11 @@ wave_pattern = 2 if (self.level & 0x60) == 0x00: wave_pattern = 8 - elif (self.level & 0x60) == 0x40: + elif (self.level & 0x60) == 0x20: wave_pattern = 0 - elif (self.level & 0x60) == 0x80: + elif (self.level & 0x60) == 0x40: wave_pattern = 1 - return wave_pattern + return wave_pattern << 22 # --------------------------------------------------------------------------- @@ -318,11 +372,12 @@ def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) # Audio Channel 4 int - self.length = 0 - self.polynomial = 0 + self.length = 0 + self.polynomial = 0 self.index = 0 self.length = 0 - self.volume = 0 + self.raw_length = 0 + self.volume = 0 self.envelope_length = 0 self.frequency = 0 self.generate_noise_frequency_ratio_table() @@ -342,12 +397,11 @@ # 1 / 2^3 * 1 / 5 4194304 Hz * 1 / 2^3 * 1 / 6 4194304 Hz * 1 / 2^3 * 1 / 7 self.noiseFreqRatioTable = [0] * 8 sampleFactor = ((1 << 16) / self.sample_rate) - for ratio in range(0, 8): - divider = 1 - if ratio != 0: - divider = 2 * ratio - self.noiseFreqRatioTable[ratio] = (GAMEBOY_CLOCK / \ - divider) *sampleFactor + self.noiseFreqRatioTable[0] = GAMEBOY_CLOCK * sampleFactor + for ratio in range(1, 8): + divider = 2 * ratio + self.noiseFreqRatioTable[ratio] = (GAMEBOY_CLOCK / divider) * \ + sampleFactor def generate_noise_tables(self): self.create_7_step_noise_table() @@ -361,10 +415,10 @@ for index in range(0, 0x7F): polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | \ (polynomial >> 1) - if (index & 31) == 0: + if (index & 0x1F) == 0: self.noise_step_7_table[index >> 5] = 0 - self.noise_step_7_table[index >> 5] |= (polynomial & 1) << \ - (index & 31) + self.noise_step_7_table[index >> 5] |= (polynomial & 0x01) << \ + (index & 0x1F) def create_15_step_noise_table(self): # 15 steps& @@ -373,25 +427,17 @@ for index in range(0, 0x7FFF): polynomial = (((polynomial << 14) ^ (polynomial << 13)) & \ 0x4000) | (polynomial >> 1) - if (index & 31) == 0: + if (index & 0x1F) == 0: self.noise_step_15_table[index >> 5] = 0 - self.noise_step_15_table[index >> 5] |= (polynomial & 1) << \ - (index & 31) + self.noise_step_15_table[index >> 5] |= (polynomial & 0x01) << \ + (index & 0x1F) - # Audio Channel 4 def get_length(self): - return self.length - - def get_polynomial(self): - return self.polynomial - - def get_playback(self): - return self.playback + return self.raw_length def set_length(self, data): - self.length = data - self.length = (SOUND_CLOCK / 256) * \ - (64 - (self.length & 0x3F)) + self.raw_length = data + self.length = (SOUND_CLOCK / 256) * (64 - (self.length & 0x3F)) def set_envelope(self, data): self.envelope = data @@ -399,12 +445,14 @@ return if (self.envelope >> 4) == 0: self.volume = 0 - elif self.envelope_length == 0 and \ - (self.envelope & 0x07) == 0: + elif self.envelope_length == 0 and (self.envelope & 0x07) == 0: self.volume = (self.volume + 1) & 0x0F else: self.volume = (self.volume + 2) & 0x0F + def get_polynomial(self): + return self.polynomial + def set_polynomial(self, data): self.polynomial = data if (self.polynomial >> 4) <= 12: @@ -413,17 +461,18 @@ else: self.frequency = 0 + def get_playback(self): + return self.playback + def set_playback(self, data): self.playback = data if (self.playback & 0x80) == 0: return self.enabled = True if (self.playback & 0x40) != 0 and self.length == 0: - self.length = (SOUND_CLOCK / 256) * \ - (64 - (self.length & 0x3F)) + self.length = (SOUND_CLOCK / 256) * (64 - (self.length & 0x3F)) self.volume = self.envelope >> 4 - self.envelope_length = (SOUND_CLOCK / 64) * \ - (self.envelope & 0x07) + self.envelope_length = (SOUND_CLOCK / 64) * (self.envelope & 0x07) self.index = 0 def update_enabled(self): @@ -435,16 +484,15 @@ def update_envelope_and_volume(self): if self.envelope_length <= 0: return - self.envelope_length-=1 + self.envelope_length -= 1 if self.envelope_length > 0: return if (self.envelope & 0x08) != 0: if self.volume < 15: - self.volume+=1 + self.volume += 1 elif self.volume > 0: - self.volume-=1 - self.envelope_length += (SOUND_CLOCK / 64) *\ - (self.envelope & 0x07) + self.volume -= 1 + self.envelope_length += (SOUND_CLOCK / 64) * (self.envelope & 0x07) def mix_audio(self, buffer, length, output_terminal): for index in range(0, length, 2): @@ -454,12 +502,12 @@ # 7 steps self.index &= 0x7FFFFF polynomial = self.noise_step_7_table[self.index >> 21] >>\ - ((self.index >> 16) & 31) + ((self.index >> 16) & 0x1F) else: # 15 steps self.index &= 0x7FFFFFFF polynomial = self.noise_step_15_table[self.index >> 21] >> \ - ((self.index >> 16) & 31) + ((self.index >> 16) & 0x1F) if (polynomial & 1) != 0: if (output_terminal & 0x80) != 0: buffer[index + 0] -= self.volume @@ -604,8 +652,7 @@ elif address==NR52: return self.get_output_enable() - elif address >= AUD3WAVERAM and \ - address <= AUD3WAVERAM + 0x3F: + elif address >= AUD3WAVERAM and address <= AUD3WAVERAM + 0x3F: return self.channel3.get_wave_pattern(address) return 0xFF @@ -658,23 +705,20 @@ elif address == NR52: self.set_output_enable(data) - elif address >= AUD3WAVERAM and \ - address <= AUD3WAVERAM + 0x3F: + elif address >= AUD3WAVERAM and address <= AUD3WAVERAM + 0x3F: self.channel3.set_wave_pattern(address, data) def update_audio(self): - if (self.output_enable & 0x80) == 0: - return - for channel in self.channels: - if channel.enabled: - channel.update_audio() + if (self.output_enable & 0x80) != 0: + for channel in self.channels: + if channel.enabled: + channel.update_audio() def mix_audio(self, buffer, length): - if (self.output_enable & 0x80) == 0: - return - for channel in self.channels: - if channel.enabled: - channel.mix_audio(buffer, length, self.output_terminal) + if (self.output_enable & 0x80) != 0: + for channel in self.channels: + if channel.enabled: + channel.mix_audio(buffer, length, self.output_terminal) # Output Control def get_output_level(self): Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Mar 7 12:50:44 2009 @@ -278,6 +278,8 @@ def draw_clean_line(self, line): raise Exception("Not implemented") +# ----------------------------------------------------------------------------- + class Window(Drawable): def reset(self): From arigo at codespeak.net Sat Mar 7 13:01:18 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 13:01:18 +0100 (CET) Subject: [pypy-svn] r62695 - in pypy/branch/pyjitpl5/pypy: . config jit/backend jit/metainterp jit/tl translator translator/goal translator/test Message-ID: <20090307120118.3BB6E168443@codespeak.net> Author: arigo Date: Sat Mar 7 13:01:14 2009 New Revision: 62695 Added: pypy/branch/pyjitpl5/pypy/jit/backend/detect_cpu.py - copied, changed from r62149, pypy/branch/oo-jit/pypy/jit/codegen/detect_cpu.py Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py pypy/branch/pyjitpl5/pypy/jit/tl/targettlc.py pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py pypy/branch/pyjitpl5/pypy/testrunner_cfg.py pypy/branch/pyjitpl5/pypy/translator/driver.py pypy/branch/pyjitpl5/pypy/translator/goal/translate.py pypy/branch/pyjitpl5/pypy/translator/test/test_driver.py Log: Port the driver to the new JIT. Adapt targettlc (although it still crashes). Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/config/translationoption.py (original) +++ pypy/branch/pyjitpl5/pypy/config/translationoption.py Sat Mar 7 13:01:14 2009 @@ -108,6 +108,11 @@ BoolOption("rweakref", "The backend supports RPython-level weakrefs", default=True), + # JIT generation + BoolOption("jit", "generate a JIT", + default=False, cmdline="--jit", + requires=[("translation.gc", "boehm")]), + # misc BoolOption("verbose", "Print extra information", default=False), BoolOption("debug", "Record extra annotation information", @@ -126,7 +131,7 @@ ChoiceOption("fork_before", "(UNIX) Create restartable checkpoint before step", ["annotate", "rtype", "backendopt", "database", "source", - "hintannotate", "timeshift"], + "pyjitpl"], default=None, cmdline="--fork-before"), ArbitraryOption("instrumentctl", "internal", Copied: pypy/branch/pyjitpl5/pypy/jit/backend/detect_cpu.py (from r62149, pypy/branch/oo-jit/pypy/jit/codegen/detect_cpu.py) ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/detect_cpu.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/detect_cpu.py Sat Mar 7 13:01:14 2009 @@ -39,3 +39,11 @@ }[mach] except KeyError: raise ProcessorAutodetectError, "unsupported processor '%s'" % mach + +def getcpuclass(): + cpu = autodetect() + if cpu == 'i386': + from pypy.jit.backend.x86.runner import CPU + else: + raise Exception('Unsuported cpu %r' % cpu) + return CPU Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sat Mar 7 13:01:14 2009 @@ -19,6 +19,13 @@ # ____________________________________________________________ # Bootstrapping +def apply_jit(translator, **kwds): + from pypy.jit.backend.detect_cpu import getcpuclass + warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=getcpuclass(), + translate_support_code=True, + **kwds) + warmrunnerdesc.finish() + def ll_meta_interp(function, args, backendopt=False, **kwds): interp, graph = get_interpreter(function, args, backendopt=backendopt, inline_threshold=0) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/targettlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/targettlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/targettlc.py Sat Mar 7 13:01:14 2009 @@ -1,8 +1,9 @@ import time import py py.magic.autopath() -from pypy.jit.tl.tlc import interp, interp_eval, interp_nonjit, ConstantPool -from pypy.jit.codegen.hlinfo import highleveljitinfo +from pypy.jit.tl.tlc import interp, interp_nonjit, ConstantPool +from pypy.jit.metainterp.policy import JitPolicy +from pypy.jit.backend.hlinfo import highleveljitinfo def entry_point(args): @@ -57,18 +58,9 @@ # ____________________________________________________________ -from pypy.jit.hintannotator.policy import HintAnnotatorPolicy - -class MyHintAnnotatorPolicy(HintAnnotatorPolicy): - novirtualcontainer = True - oopspec = True - -def portal(driver): - """Return the 'portal' function, and the hint-annotator policy. - The portal is the function that gets patched with a call to the JIT - compiler. - """ - return interp_eval, MyHintAnnotatorPolicy() +def jitpolicy(driver): + """Returns the JIT policy to use when translating.""" + return JitPolicy() if __name__ == '__main__': import sys Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Sat Mar 7 13:01:14 2009 @@ -251,8 +251,9 @@ pc = frame.pc while pc < len(code): - myjitdriver.jit_merge_point(frame=frame, framestack=framestack, - code=code, pc=pc, pool=pool) + if jitted: + myjitdriver.jit_merge_point(frame=frame, framestack=framestack, + code=code, pc=pc, pool=pool) opcode = ord(code[pc]) pc += 1 stack = frame.stack @@ -352,7 +353,7 @@ old_pc = pc pc += char2int(code[pc]) pc += 1 - if old_pc > pc: + if jitted and old_pc > pc: myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, framestack=framestack, pool=pool) @@ -362,7 +363,7 @@ if cond.t(): old_pc = pc pc += char2int(code[pc]) + 1 - if old_pc > pc: + if jitted and old_pc > pc: myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, framestack=framestack, pool=pool) @@ -374,7 +375,7 @@ if stack.pop().t(): old_pc = pc pc += offset - if old_pc > pc: + if jitted and old_pc > pc: myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, framestack=framestack, pool=pool) Modified: pypy/branch/pyjitpl5/pypy/testrunner_cfg.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/testrunner_cfg.py (original) +++ pypy/branch/pyjitpl5/pypy/testrunner_cfg.py Sat Mar 7 13:01:14 2009 @@ -1,9 +1,7 @@ # nightly test configuration for the paraller runner def collect_one_testdir(testdirs, reldir, tests): - if (reldir.startswith('jit/codegen/i386/') or - reldir.startswith('jit/timeshifter/') or - reldir.startswith('translator/c/') or + if (reldir.startswith('translator/c/') or reldir.startswith('rlib/test') or reldir.startswith('rpython/memory/')): testdirs.extend(tests) Modified: pypy/branch/pyjitpl5/pypy/translator/driver.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/driver.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/driver.py Sat Mar 7 13:01:14 2009 @@ -121,8 +121,7 @@ else: task, postfix = parts if task in ('rtype', 'backendopt', 'llinterpret', - 'prehannotatebackendopt', 'hintannotate', - 'timeshift'): + 'prejitbackendopt', 'pyjitpl'): if ts: if ts == postfix: expose_task(task, explicit_task) @@ -356,7 +355,7 @@ task_rtype_ootype = taskdef(task_rtype_ootype, ['annotate'], "ootyping") OOTYPE = 'rtype_ootype' - def task_prehannotatebackendopt_lltype(self): + def task_prejitbackendopt_lltype(self): from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(self.translator, inline_threshold=0, @@ -365,73 +364,30 @@ raisingop2direct_call=False, remove_asserts=True) # - task_prehannotatebackendopt_lltype = taskdef( - task_prehannotatebackendopt_lltype, + task_prejitbackendopt_lltype = taskdef( + task_prejitbackendopt_lltype, [RTYPE], - "Backendopt before Hint-annotate") + "Backendopt before jitting") - def task_hintannotate_lltype(self): - raise NotImplementedError("JIT is not implemented on trunk, look at oo-jit branch instead") - from pypy.jit.hintannotator.annotator import HintAnnotator - from pypy.jit.hintannotator.model import OriginFlags - from pypy.jit.hintannotator.model import SomeLLAbstractConstant - - get_portal = self.extra['portal'] - PORTAL, POLICY = get_portal(self) - t = self.translator - self.portal_graph = graphof(t, PORTAL) - - hannotator = HintAnnotator(base_translator=t, policy=POLICY) - self.hint_translator = hannotator.translator - hs = hannotator.build_types(self.portal_graph, - [SomeLLAbstractConstant(v.concretetype, - {OriginFlags(): True}) - for v in self.portal_graph.getargs()]) - count = hannotator.bookkeeper.nonstuboriggraphcount - stubcount = hannotator.bookkeeper.stuboriggraphcount - self.log.info("The hint-annotator saw %d graphs" - " (and made stubs for %d graphs)." % (count, stubcount)) - n = len(list(hannotator.translator.graphs[0].iterblocks())) - self.log.info("portal has %d blocks" % n) - self.hannotator = hannotator - # - task_hintannotate_lltype = taskdef(task_hintannotate_lltype, - ['prehannotatebackendopt_lltype'], - "Hint-annotate") - - def task_timeshift_lltype(self): - raise NotImplementedError("JIT is not implemented on trunk, look at oo-jit branch instead") - - from pypy.jit.timeshifter.hrtyper import HintRTyper - 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 - elif cpu == 'ppc': - from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp - RGenOp.MC_SIZE = 32 * 1024 * 1024 - else: - raise Exception('Unsuported cpu %r'%cpu) - - del self.hint_translator - ha = self.hannotator - t = self.translator - # make the timeshifted graphs - hrtyper = HintRTyper(ha, t.rtyper, RGenOp) - hrtyper.specialize(origportalgraph=self.portal_graph, view=False) - # - task_timeshift_lltype = taskdef(task_timeshift_lltype, - ["hintannotate_lltype"], - "Timeshift") + def task_pyjitpl_lltype(self): + get_policy = self.extra['jitpolicy'] + self.jitpolicy = get_policy(self) + # + from pypy.jit.metainterp.warmspot import apply_jit + apply_jit(self.translator) + # + self.log.info("the JIT compiler was generated") + # + task_pyjitpl_lltype = taskdef(task_pyjitpl_lltype, + [RTYPE, '?prejitbackendopt_lltype'], + "JIT compiler generation") def task_backendopt_lltype(self): from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(self.translator) # task_backendopt_lltype = taskdef(task_backendopt_lltype, - [RTYPE, - '??timeshift_lltype'], + [RTYPE, '??pyjitpl_lltype'], "lltype back-end optimisations") BACKENDOPT = 'backendopt_lltype' Modified: pypy/branch/pyjitpl5/pypy/translator/goal/translate.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/goal/translate.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/goal/translate.py Sat Mar 7 13:01:14 2009 @@ -20,14 +20,12 @@ GOALS= [ ("annotate", "do type inference", "-a --annotate", ""), ("rtype", "do rtyping", "-t --rtype", ""), - ("prehannotatebackendopt", "backend optimize before hint-annotating", - "--prehannotatebackendopt", ""), - ("hintannotate", "hint-annotate", "--hintannotate", ""), - ("timeshift", "timeshift (jit generation)", "--timeshift", ""), + ("prejitbackendopt", "backend optimize before jitting", + "--prejitbackendopt", ""), + ("pyjitpl", "JIT generation step", "--pyjitpl", ""), ("backendopt", "do backend optimizations", "--backendopt", ""), ("source", "create source", "-s --source", ""), ("compile", "compile", "-c --compile", " (default goal)"), - ("?jit", "generate JIT", "--jit", ""), ("run", "run the resulting binary", "--run", ""), ("llinterpret", "interpret the rtyped flow graphs", "--llinterpret", ""), ] @@ -258,10 +256,10 @@ disable=translateconfig.skipped_goals, default_goal='compile') log_config(translateconfig, "translate.py configuration") - if translateconfig.goal_options.jit: - if 'portal' not in targetspec_dic: - raise Exception('target has no portal defined.') - drv.set_extra_goals(['timeshift']) + if config.translation.jit: + if 'jitpolicy' not in targetspec_dic: + raise Exception('target has no jitpolicy defined.') + drv.set_extra_goals(['pyjitpl']) log_config(config.translation, "translation configuration") pdb_plus_show.expose({'drv': drv, 'prof': prof}) Modified: pypy/branch/pyjitpl5/pypy/translator/test/test_driver.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/test/test_driver.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/test/test_driver.py Sat Mar 7 13:01:14 2009 @@ -6,8 +6,7 @@ def test_ctr(): td = TranslationDriver() expected = ['annotate', 'backendopt', 'llinterpret', 'rtype', 'source', - 'compile', 'run', 'prehannotatebackendopt', 'hintannotate', - 'timeshift'] + 'compile', 'run', 'prejitbackendopt', 'pyjitpl'] assert set(td.exposed) == set(expected) assert td.backend_select_goals(['compile_c']) == ['compile_c'] @@ -37,8 +36,7 @@ 'compile_llvm', 'compile_js', 'run_llvm', 'run_c', 'run_js', 'run_cli', 'compile_jvm', 'source_jvm', 'run_jvm', - 'prehannotatebackendopt_lltype', 'hintannotate_lltype', - 'timeshift_lltype'] + 'prejitbackendopt_lltype', 'pyjitpl_lltype'] assert set(td.exposed) == set(expected) td = TranslationDriver({'backend': None, 'type_system': 'lltype'}) @@ -53,6 +51,6 @@ expected = ['annotate', 'backendopt', 'llinterpret', 'rtype', 'source_c', 'source_llvm', 'compile_c', 'compile_llvm', 'run_llvm', - 'run_c', 'prehannotatebackendopt', 'hintannotate', 'timeshift'] + 'run_c', 'prejitbackendopt', 'pyjitpl'] assert set(td.exposed) == set(expected) From santagada at codespeak.net Sat Mar 7 13:34:08 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sat, 7 Mar 2009 13:34:08 +0100 (CET) Subject: [pypy-svn] r62696 - in pypy/trunk/pypy/rlib/rsdl: . test Message-ID: <20090307123408.D848616804E@codespeak.net> Author: santagada Date: Sat Mar 7 13:34:08 2009 New Revision: 62696 Added: pypy/trunk/pypy/rlib/rsdl/test/applause.wav (contents, props changed) Modified: pypy/trunk/pypy/rlib/rsdl/RMix.py pypy/trunk/pypy/rlib/rsdl/test/test_sdl_mixer.py Log: exposing 3 more functions of sdl_mixer, and a new test (is it okay to time.sleep during a test?) Modified: pypy/trunk/pypy/rlib/rsdl/RMix.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RMix.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RMix.py Sat Mar 7 13:34:08 2009 @@ -8,7 +8,7 @@ eci = ExternalCompilationInfo( includes = ['SDL_mixer.h'], frameworks = ['SDL_mixer'], - include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Versions/A/Headers'] + include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] ) else: eci = ExternalCompilationInfo( @@ -38,11 +38,16 @@ CloseAudio = external('Mix_CloseAudio', [], lltype.Void) -_LoadWAV = external('Mix_LoadWAV_RW', +LoadWAV_RW = external('Mix_LoadWAV_RW', [RSDL.RWopsPtr, rffi.INT], ChunkPtr) def LoadWAV(filename_ccharp): - _LoadWAV(RSDL.RWFromFile(filename_ccharp, rffi.str2charp('rb')), 1) + return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, rffi.str2charp('rb')), 1) +PlayChannelTimed = external('Mix_PlayChannelTimed', + [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], + rffi.INT) +def PlayChannel(channel,chunk,loops): + return PlayChannelTimed(channel, chunk, loops, -1) Added: pypy/trunk/pypy/rlib/rsdl/test/applause.wav ============================================================================== Binary file. No diff available. Modified: pypy/trunk/pypy/rlib/rsdl/test/test_sdl_mixer.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/test/test_sdl_mixer.py (original) +++ pypy/trunk/pypy/rlib/rsdl/test/test_sdl_mixer.py Sat Mar 7 13:34:08 2009 @@ -1,4 +1,6 @@ -import py, os +import py +import os +import time import autopath from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi @@ -13,7 +15,19 @@ if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: error = rffi.charp2str(RSDL.GetError()) raise Exception(error) - filename = rffi.str2charp('test.wav') + filename = rffi.str2charp('applause.wav') RMix.LoadWAV(filename) rffi.free_charp(filename) RMix.CloseAudio() + +def test_play_wav(): + if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) + filename = rffi.str2charp('applause.wav') + applause = RMix.LoadWAV(filename) + rffi.free_charp(filename) + RMix.PlayChannel(-1, applause, -1) + time.sleep(1) + RMix.CloseAudio() + From arigo at codespeak.net Sat Mar 7 14:29:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 14:29:56 +0100 (CET) Subject: [pypy-svn] r62697 - pypy/trunk/pypy/module/pypyjit Message-ID: <20090307132956.76AA3168441@codespeak.net> Author: arigo Date: Sat Mar 7 14:29:53 2009 New Revision: 62697 Removed: pypy/trunk/pypy/module/pypyjit/ Log: Remove this directory. From arigo at codespeak.net Sat Mar 7 14:35:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 14:35:17 +0100 (CET) Subject: [pypy-svn] r62698 - pypy/trunk/pypy/interpreter Message-ID: <20090307133517.94CFF168442@codespeak.net> Author: arigo Date: Sat Mar 7 14:35:17 2009 New Revision: 62698 Added: pypy/trunk/pypy/interpreter/pyopcode.py.merge.tmp - copied, changed from r62697, pypy/trunk/pypy/interpreter/pyopcode.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py revisions 61705 to 62697: ------------------------------------------------------------------------ r62179 | arigo | 2009-02-26 13:56:10 +0100 (Thu, 26 Feb 2009) | 2 lines Remove most hints in the Python interpreter. They are not useful any more. ------------------------------------------------------------------------ r61713 | fijal | 2009-02-11 12:33:01 +0100 (Wed, 11 Feb 2009) | 4 lines (arigo, fijal) Create a new branch for importing pyjitpl5 into trunk (and pieces from pypy-oo-jit) ------------------------------------------------------------------------ Copied: pypy/trunk/pypy/interpreter/pyopcode.py.merge.tmp (from r62697, pypy/trunk/pypy/interpreter/pyopcode.py) ============================================================================== --- pypy/trunk/pypy/interpreter/pyopcode.py (original) +++ pypy/trunk/pypy/interpreter/pyopcode.py.merge.tmp Sat Mar 7 14:35:17 2009 @@ -183,8 +183,6 @@ oparg = (hi << 8) | lo else: oparg = 0 - hint(opcode, concrete=True) - hint(oparg, concrete=True) while opcode == opcodedesc.EXTENDED_ARG.index: opcode = ord(co_code[next_instr]) @@ -194,8 +192,6 @@ hi = ord(co_code[next_instr+2]) next_instr += 3 oparg = (oparg << 16) | (hi << 8) | lo - hint(opcode, concrete=True) - hint(oparg, concrete=True) if opcode == opcodedesc.RETURN_VALUE.index: w_returnvalue = self.popvalue() @@ -265,7 +261,6 @@ while n > 0: block = self.blockstack.pop() n -= 1 - hint(n, concrete=True) if (block.handling_mask & unroller_kind) != 0: return block block.cleanupstack(self) @@ -1142,7 +1137,7 @@ def handle(self, frame, unroller): next_instr = self.really_handle(frame, unroller) # JIT hack - return hint(next_instr, promote=True) + return next_instr def really_handle(self, frame, unroller): """ Purely abstract method From arigo at codespeak.net Sat Mar 7 14:35:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 14:35:22 +0100 (CET) Subject: [pypy-svn] r62699 - pypy/trunk/pypy/objspace/std Message-ID: <20090307133522.9568F16844A@codespeak.net> Author: arigo Date: Sat Mar 7 14:35:22 2009 New Revision: 62699 Added: pypy/trunk/pypy/objspace/std/intobject.py.merge.tmp - copied, changed from r62697, pypy/trunk/pypy/objspace/std/intobject.py Log: merging of svn+ssh://codespeak.net/svn/pypy/branch/pyjitpl5/pypy/objspace/std/intobject.py revisions 61705 to 62697: ------------------------------------------------------------------------ r62545 | fijal | 2009-03-04 20:01:49 +0100 (Wed, 04 Mar 2009) | 3 lines reintroduce _immutable_ hint on Int and Bool. I think it was gone because previous JIT was unable to cope with it ------------------------------------------------------------------------ r61713 | fijal | 2009-02-11 12:33:01 +0100 (Wed, 11 Feb 2009) | 4 lines (arigo, fijal) Create a new branch for importing pyjitpl5 into trunk (and pieces from pypy-oo-jit) ------------------------------------------------------------------------ Copied: pypy/trunk/pypy/objspace/std/intobject.py.merge.tmp (from r62697, pypy/trunk/pypy/objspace/std/intobject.py) ============================================================================== --- pypy/trunk/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/pypy/objspace/std/intobject.py.merge.tmp Sat Mar 7 14:35:22 2009 @@ -13,6 +13,9 @@ class W_IntObject(W_Object): __slots__ = 'intval' + + _immutable_ = True + from pypy.objspace.std.inttype import int_typedef as typedef def __init__(w_self, intval): From arigo at codespeak.net Sat Mar 7 14:36:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 14:36:30 +0100 (CET) Subject: [pypy-svn] r62700 - in pypy/trunk/pypy: . annotation config doc/jit interpreter jit module/_pickle_support module/pypyjit objspace/std rlib rpython rpython/lltypesystem rpython/lltypesystem/test translator translator/backendopt translator/c translator/c/test translator/goal translator/test Message-ID: <20090307133630.C5E26168441@codespeak.net> Author: arigo Date: Sat Mar 7 14:36:30 2009 New Revision: 62700 Added: pypy/trunk/pypy/annotation/listdef.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/annotation/listdef.py pypy/trunk/pypy/config/translationoption.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/config/translationoption.py pypy/trunk/pypy/doc/jit/ - copied from r62699, pypy/branch/pyjitpl5/pypy/doc/jit/ pypy/trunk/pypy/interpreter/baseobjspace.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/interpreter/baseobjspace.py pypy/trunk/pypy/interpreter/eval.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/interpreter/eval.py pypy/trunk/pypy/interpreter/gateway.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/interpreter/gateway.py pypy/trunk/pypy/interpreter/pycode.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/interpreter/pycode.py pypy/trunk/pypy/interpreter/pyframe.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py pypy/trunk/pypy/interpreter/pyopcode.py - copied unchanged from r62699, pypy/trunk/pypy/interpreter/pyopcode.py.merge.tmp pypy/trunk/pypy/jit/ - copied from r62699, pypy/branch/pyjitpl5/pypy/jit/ pypy/trunk/pypy/module/_pickle_support/ - copied from r62699, pypy/branch/pyjitpl5/pypy/module/_pickle_support/ pypy/trunk/pypy/module/pypyjit/ - copied from r62699, pypy/branch/pyjitpl5/pypy/module/pypyjit/ pypy/trunk/pypy/objspace/std/boolobject.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/objspace/std/boolobject.py pypy/trunk/pypy/objspace/std/intobject.py - copied unchanged from r62699, pypy/trunk/pypy/objspace/std/intobject.py.merge.tmp pypy/trunk/pypy/objspace/std/marshal_impl.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/objspace/std/marshal_impl.py pypy/trunk/pypy/rlib/debug.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rlib/debug.py pypy/trunk/pypy/rlib/jit.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rlib/jit.py pypy/trunk/pypy/rpython/llinterp.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/trunk/pypy/rpython/lltypesystem/ll_str.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py pypy/trunk/pypy/rpython/lltypesystem/lloperation.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/trunk/pypy/rpython/lltypesystem/lltype.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py pypy/trunk/pypy/rpython/lltypesystem/opimpl.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/opimpl.py pypy/trunk/pypy/rpython/lltypesystem/rclass.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py pypy/trunk/pypy/rpython/lltypesystem/rlist.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py pypy/trunk/pypy/rpython/lltypesystem/rvirtualizable2.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/trunk/pypy/rpython/rlist.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/rlist.py pypy/trunk/pypy/rpython/rtyper.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/rpython/rtyper.py pypy/trunk/pypy/testrunner_cfg.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/testrunner_cfg.py pypy/trunk/pypy/translator/backendopt/ - copied from r62699, pypy/branch/pyjitpl5/pypy/translator/backendopt/ pypy/trunk/pypy/translator/c/database.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/c/database.py pypy/trunk/pypy/translator/c/funcgen.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py pypy/trunk/pypy/translator/c/primitive.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/c/primitive.py pypy/trunk/pypy/translator/c/test/ - copied from r62699, pypy/branch/pyjitpl5/pypy/translator/c/test/ pypy/trunk/pypy/translator/driver.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/driver.py pypy/trunk/pypy/translator/exceptiontransform.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py pypy/trunk/pypy/translator/goal/ann_override.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/goal/ann_override.py pypy/trunk/pypy/translator/goal/translate.py - copied unchanged from r62699, pypy/branch/pyjitpl5/pypy/translator/goal/translate.py pypy/trunk/pypy/translator/test/ - copied from r62699, pypy/branch/pyjitpl5/pypy/translator/test/ Removed: pypy/trunk/pypy/interpreter/pyopcode.py.merge.tmp pypy/trunk/pypy/objspace/std/intobject.py.merge.tmp Log: Merge the pyjitpl5 branch to trunk. From arigo at codespeak.net Sat Mar 7 14:36:52 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 14:36:52 +0100 (CET) Subject: [pypy-svn] r62701 - pypy/branch/pyjitpl5 Message-ID: <20090307133652.9B227168448@codespeak.net> Author: arigo Date: Sat Mar 7 14:36:51 2009 New Revision: 62701 Removed: pypy/branch/pyjitpl5/ Log: Removed merged branch. From arigo at codespeak.net Sat Mar 7 14:45:53 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 14:45:53 +0100 (CET) Subject: [pypy-svn] r62702 - pypy/trunk/pypy/jit/old-metainterp Message-ID: <20090307134553.ABCB7168445@codespeak.net> Author: arigo Date: Sat Mar 7 14:45:53 2009 New Revision: 62702 Removed: pypy/trunk/pypy/jit/old-metainterp/ Log: Kill old directory. From fijal at codespeak.net Sat Mar 7 14:59:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 14:59:22 +0100 (CET) Subject: [pypy-svn] r62703 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090307135922.7A83B168445@codespeak.net> Author: fijal Date: Sat Mar 7 14:59:19 2009 New Revision: 62703 Modified: pypy/trunk/pypy/module/_locale/ (props changed) pypy/trunk/pypy/module/_locale/__init__.py (props changed) pypy/trunk/pypy/module/_locale/app_locale.py (props changed) pypy/trunk/pypy/module/_locale/interp_locale.py (props changed) pypy/trunk/pypy/module/_locale/test/ (props changed) pypy/trunk/pypy/module/_locale/test/test_locale.py (props changed) Log: fixeol From fijal at codespeak.net Sat Mar 7 15:01:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 15:01:01 +0100 (CET) Subject: [pypy-svn] r62704 - pypy/trunk/pypy/interpreter/test Message-ID: <20090307140101.66F0A168445@codespeak.net> Author: fijal Date: Sat Mar 7 15:00:59 2009 New Revision: 62704 Modified: pypy/trunk/pypy/interpreter/test/test_generator.py Log: some non-essential changes, lying around in my wc Modified: pypy/trunk/pypy/interpreter/test/test_generator.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_generator.py (original) +++ pypy/trunk/pypy/interpreter/test/test_generator.py Sat Mar 7 15:00:59 2009 @@ -166,20 +166,21 @@ def test_close_on_collect(self): ## we need to exec it, else it won't run on python2.4 + d = {} exec """ def f(): try: yield finally: f.x = 42 - """.strip() in locals(), locals() + """.strip() in d - g = f() + g = d['f']() g.next() del g import gc gc.collect() - assert f.x == 42 + assert d['f'].x == 42 def test_generator_raises_typeerror(self): def f(): From fijal at codespeak.net Sat Mar 7 15:01:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 15:01:53 +0100 (CET) Subject: [pypy-svn] r62705 - pypy/trunk/pypy/jit/tl Message-ID: <20090307140153.68652168447@codespeak.net> Author: fijal Date: Sat Mar 7 15:01:52 2009 New Revision: 62705 Modified: pypy/trunk/pypy/jit/tl/targettlr.py Log: update the target Modified: pypy/trunk/pypy/jit/tl/targettlr.py ============================================================================== --- pypy/trunk/pypy/jit/tl/targettlr.py (original) +++ pypy/trunk/pypy/jit/tl/targettlr.py Sat Mar 7 15:01:52 2009 @@ -1,7 +1,7 @@ import py py.magic.autopath() from pypy.jit.tl.tlr import interpret -from pypy.jit.codegen.hlinfo import highleveljitinfo +from pypy.jit.backend.hlinfo import highleveljitinfo def entry_point(args): @@ -33,18 +33,10 @@ # ____________________________________________________________ -from pypy.jit.hintannotator.policy import HintAnnotatorPolicy +from pypy.jit.metainterp.policy import JitPolicy -class MyHintAnnotatorPolicy(HintAnnotatorPolicy): - novirtualcontainer = True - oopspec = True - -def portal(driver): - """Return the 'portal' function, and the hint-annotator policy. - The portal is the function that gets patched with a call to the JIT - compiler. - """ - return interpret, MyHintAnnotatorPolicy() +def jitpolicy(driver): + return JitPolicy() if __name__ == '__main__': import sys From fijal at codespeak.net Sat Mar 7 15:02:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 15:02:15 +0100 (CET) Subject: [pypy-svn] r62706 - pypy/trunk/pypy/jit/tl Message-ID: <20090307140215.3F3B616844F@codespeak.net> Author: fijal Date: Sat Mar 7 15:02:13 2009 New Revision: 62706 Modified: pypy/trunk/pypy/jit/tl/pypyjit.py Log: it's far too useful to be temporary Modified: pypy/trunk/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/trunk/pypy/jit/tl/pypyjit.py (original) +++ pypy/trunk/pypy/jit/tl/pypyjit.py Sat Mar 7 15:02:13 2009 @@ -1,5 +1,5 @@ """ -A temporary file that invokes translation of PyPy with the JIT enabled. +A file that invokes translation of PyPy with the JIT enabled. """ import py, os From santagada at codespeak.net Sat Mar 7 15:27:11 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sat, 7 Mar 2009 15:27:11 +0100 (CET) Subject: [pypy-svn] r62707 - in pypy/trunk/pypy/translator: platform tool tool/test Message-ID: <20090307142711.C0A78168455@codespeak.net> Author: santagada Date: Sat Mar 7 15:27:11 2009 New Revision: 62707 Modified: pypy/trunk/pypy/translator/platform/__init__.py pypy/trunk/pypy/translator/platform/posix.py pypy/trunk/pypy/translator/platform/windows.py pypy/trunk/pypy/translator/tool/cbuild.py pypy/trunk/pypy/translator/tool/test/test_cbuild.py Log: Added a new link_files parameter that is passed directly to the linker. Updated a test for it, but would really like to have advice on how to test it better. Modified: pypy/trunk/pypy/translator/platform/__init__.py ============================================================================== --- pypy/trunk/pypy/translator/platform/__init__.py (original) +++ pypy/trunk/pypy/translator/platform/__init__.py Sat Mar 7 15:27:11 2009 @@ -120,8 +120,9 @@ def _link_args_from_eci(self, eci): library_dirs = self._libdirs(eci.library_dirs) libraries = self._libs(eci.libraries) + link_files = self._linkfiles(eci.link_files) return (library_dirs + libraries + self.link_flags + - list(eci.link_extra)) + link_files + list(eci.link_extra)) def _finish_linking(self, ofiles, eci, outputfilename, standalone): if outputfilename is None: Modified: pypy/trunk/pypy/translator/platform/posix.py ============================================================================== --- pypy/trunk/pypy/translator/platform/posix.py (original) +++ pypy/trunk/pypy/translator/platform/posix.py Sat Mar 7 15:27:11 2009 @@ -23,6 +23,9 @@ def _includedirs(self, include_dirs): return ['-I%s' % (idir,) for idir in include_dirs] + def _linkfiles(self, link_files): + return list(link_files) + def _compile_c_file(self, cc, cfile, compile_args): oname = cfile.new(ext='o') args = ['-c'] + compile_args + [str(cfile), '-o', str(oname)] Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Sat Mar 7 15:27:11 2009 @@ -126,6 +126,9 @@ ) return ['/LIBPATH:%s' % (ldir,) for ldir in library_dirs] + def _linkfiles(self, link_files): + return list(link_files) + def _args_for_shared(self, args): return ['/dll'] + args Modified: pypy/trunk/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/cbuild.py Sat Mar 7 15:27:11 2009 @@ -18,7 +18,7 @@ 'post_include_bits', 'libraries', 'library_dirs', 'separate_module_sources', 'separate_module_files', 'export_symbols', 'compile_extra', 'link_extra', - 'frameworks'] + 'frameworks', 'link_files'] _DUPLICATES_OK = ['compile_extra', 'link_extra'] def __init__(self, @@ -34,6 +34,7 @@ compile_extra = [], link_extra = [], frameworks = [], + link_files = [], platform = None): """ pre_include_bits: list of pieces of text that should be put at the top @@ -76,6 +77,9 @@ link to a framework bundle. Not suitable for unix-like .dylib installations. + link_files: list of file names which will be directly passed to the + linker + platform: an object that can identify the platform """ for name in self._ATTRIBUTES: Modified: pypy/trunk/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/test/test_cbuild.py Sat Mar 7 15:27:11 2009 @@ -41,16 +41,20 @@ def test_merge2(self): e1 = ExternalCompilationInfo( pre_include_bits = ['1'], + link_files = ['1.c'] ) e2 = ExternalCompilationInfo( pre_include_bits = ['2'], + link_files = ['1.c', '2.c'] ) e3 = ExternalCompilationInfo( pre_include_bits = ['3'], + link_files = ['1.c', '2.c', '3.c'] ) e = e1.merge(e2) e = e.merge(e3, e3) assert e.pre_include_bits == ('1', '2', '3') + assert e.link_files == ('1.c', '2.c', '3.c') def test_convert_sources_to_c_files(self): eci = ExternalCompilationInfo( From santagada at codespeak.net Sat Mar 7 15:28:54 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sat, 7 Mar 2009 15:28:54 +0100 (CET) Subject: [pypy-svn] r62708 - in pypy/trunk/pypy/rlib/rsdl: . test Message-ID: <20090307142854.BF139168459@codespeak.net> Author: santagada Date: Sat Mar 7 15:28:54 2009 New Revision: 62708 Modified: pypy/trunk/pypy/rlib/rsdl/RIMG.py pypy/trunk/pypy/rlib/rsdl/RMix.py pypy/trunk/pypy/rlib/rsdl/eci.py pypy/trunk/pypy/rlib/rsdl/test/conftest.py Log: Updated the eci for rsdl, their conftest and made RIMG work properly on osx Modified: pypy/trunk/pypy/rlib/rsdl/RIMG.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RIMG.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RIMG.py Sat Mar 7 15:28:54 2009 @@ -1,12 +1,22 @@ +import sys from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rsdl import RSDL -eci = ExternalCompilationInfo( - includes=['SDL_image.h'], - libraries=['SDL_image'], + +if sys.platform == 'darwin': + eci = ExternalCompilationInfo( + includes = ['SDL_image.h'], + frameworks = ['SDL_image'], + include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] + ) +else: + eci = ExternalCompilationInfo( + includes=['SDL_image.h'], + libraries=['SDL_image'], ) + eci = eci.merge(RSDL.eci) def external(name, args, result): Modified: pypy/trunk/pypy/rlib/rsdl/RMix.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RMix.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RMix.py Sat Mar 7 15:28:54 2009 @@ -1,8 +1,9 @@ +import sys from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rsdl import RSDL -import sys + if sys.platform == 'darwin': eci = ExternalCompilationInfo( Modified: pypy/trunk/pypy/rlib/rsdl/eci.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/eci.py (original) +++ pypy/trunk/pypy/rlib/rsdl/eci.py Sat Mar 7 15:28:54 2009 @@ -8,7 +8,7 @@ eci = ExternalCompilationInfo( includes = ['SDL.h'], include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], - link_extra = [ + link_files = [ str(py.magic.autopath().dirpath().join('macosx-sdl-main/SDLMain.m')), ], frameworks = ['SDL', 'Cocoa'] Modified: pypy/trunk/pypy/rlib/rsdl/test/conftest.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/test/conftest.py (original) +++ pypy/trunk/pypy/rlib/rsdl/test/conftest.py Sat Mar 7 15:28:54 2009 @@ -2,9 +2,10 @@ import py class Directory(py.test.collect.Directory): - def run(self): + def collect(self): try: check_sdl_installation() except SDLNotInstalled, e: + raise py.test.skip("SDL not installed(?): %s" % (e,)) - return py.test.collect.Directory.run(self) + return py.test.collect.Directory.collect(self) From arigo at codespeak.net Sat Mar 7 15:42:21 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 15:42:21 +0100 (CET) Subject: [pypy-svn] r62709 - in pypy/trunk/pypy: rpython/lltypesystem translator/test Message-ID: <20090307144221.B8AE716845E@codespeak.net> Author: arigo Date: Sat Mar 7 15:42:21 2009 New Revision: 62709 Modified: pypy/trunk/pypy/rpython/lltypesystem/rlist.py pypy/trunk/pypy/translator/test/test_simplify.py Log: Test and fix for list comprehension operations. Modified: pypy/trunk/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rlist.py Sat Mar 7 15:42:21 2009 @@ -136,10 +136,10 @@ hints = hop.args_s[-1].const if 'maxlength' in hints: if optimized: + v_iterable = hop.args_v[1] s_iterable = hop.args_s[1] r_iterable = hop.args_r[1] v_list = hop.inputarg(self, arg=0) - v_iterable = hop.inputarg(r_iterable, arg=1) hop2 = hop.copy() while hop2.nb_args > 0: hop2.r_s_popfirstarg() Modified: pypy/trunk/pypy/translator/test/test_simplify.py ============================================================================== --- pypy/trunk/pypy/translator/test/test_simplify.py (original) +++ pypy/trunk/pypy/translator/test/test_simplify.py Sat Mar 7 15:42:21 2009 @@ -337,6 +337,15 @@ res = interp.eval_graph(graph, [4, 4]) assert res == 1 + 4 * 17 + 4 * 17 + def test_iterate_over_constant(self): + CONST = range(10) + def main(n): + lst = [x*17 for x in CONST] + return lst[5] + interp, graph = self.specialize(main, [int]) + res = interp.eval_graph(graph, [10]) + assert res == 5 * 17 + ## TODO: maxlength and fence hints are not supported by ootype ## see doc/discussion/list_comprehension_ootype.txt ##class TestOOSpecializeListComprehension(TestLLSpecializeListComprehension): From tverwaes at codespeak.net Sat Mar 7 15:43:32 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 7 Mar 2009 15:43:32 +0100 (CET) Subject: [pypy-svn] r62710 - pypy/trunk/pypy/translator/goal Message-ID: <20090307144332.E7AA3168467@codespeak.net> Author: tverwaes Date: Sat Mar 7 15:43:32 2009 New Revision: 62710 Modified: pypy/trunk/pypy/translator/goal/targetgbimplementation.py Log: update Modified: pypy/trunk/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/trunk/pypy/translator/goal/targetgbimplementation.py Sat Mar 7 15:43:32 2009 @@ -7,8 +7,6 @@ print ROM_PATH -use_rsdl = False - def entry_point(argv=None): if argv is not None and len(argv) > 1: filename = argv[1] @@ -22,8 +20,10 @@ except: print "Corrupt Cartridge" gameBoy.load_cartridge_file(str(filename), verify=False) + + gameBoy.open_window() gameBoy.mainLoop() - #pdb.runcall(gameBoy.mainLoop) + return 0 @@ -39,6 +39,7 @@ # STARTPOINT =================================================================== if __name__ == '__main__': + use_rsdl = False if use_rsdl and sys.platform == 'darwin': from AppKit import NSApplication NSApplication.sharedApplication() From tverwaes at codespeak.net Sat Mar 7 15:44:07 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 7 Mar 2009 15:44:07 +0100 (CET) Subject: [pypy-svn] r62711 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090307144407.3F0BC16845E@codespeak.net> Author: tverwaes Date: Sat Mar 7 15:44:06 2009 New Revision: 62711 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: adding an open_window, so that we can translate with a game built in. changing penalty system to fade penalties out Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Sat Mar 7 15:44:06 2009 @@ -30,8 +30,11 @@ self.is_running = False self.penalty = 0.0 self.sync_time = time.time() + + def open_window(self): if use_rsdl: self.init_sdl() + self.video_driver.create_screen() def init_sdl(self): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 @@ -62,16 +65,14 @@ self.handle_events() # Come back to this cycle every 1/X seconds self.emulate(constants.GAMEBOY_CLOCK / X) - # if use_rsdl: - # RSDL.Delay(100) spent = time.time() - self.sync_time left = (1.0/X) + self.penalty - spent if left > 0: time.sleep(left) self.penalty = 0.0 else: - self.penalty = left - # print "WARNING: Going too slow: ", spent, " ", left + # Fade out penalties over time. + self.penalty = left - self.penalty / 2 self.sync_time = time.time() @@ -116,7 +117,6 @@ if show_metadata: self.create_meta_windows(gameboy) - self.create_screen() def create_screen(self): if use_rsdl: From arigo at codespeak.net Sat Mar 7 15:47:59 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 15:47:59 +0100 (CET) Subject: [pypy-svn] r62712 - pypy/trunk/pypy/translator/goal Message-ID: <20090307144759.3A898168459@codespeak.net> Author: arigo Date: Sat Mar 7 15:47:58 2009 New Revision: 62712 Modified: pypy/trunk/pypy/translator/goal/targetpypystandalone.py Log: Oups, this was messed up. Modified: pypy/trunk/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/trunk/pypy/translator/goal/targetpypystandalone.py Sat Mar 7 15:47:58 2009 @@ -172,10 +172,10 @@ if not config.translation.rweakref: config.objspace.usemodules._weakref = False - if self.translateconfig.goal_options.jit: + if config.translation.jit: config.objspace.usemodules.pypyjit = True elif config.objspace.usemodules.pypyjit: - self.translateconfig.goal_options.jit = True + config.translation.jit = True if config.translation.backend == "cli": config.objspace.usemodules.clr = True From santagada at codespeak.net Sat Mar 7 16:10:16 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sat, 7 Mar 2009 16:10:16 +0100 (CET) Subject: [pypy-svn] r62713 - in pypy/trunk/pypy/rlib/rsdl: . test Message-ID: <20090307151016.DC926168459@codespeak.net> Author: santagada Date: Sat Mar 7 16:10:14 2009 New Revision: 62713 Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py pypy/trunk/pypy/rlib/rsdl/test/test_basic.py Log: new GetTicks. Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RSDL.py Sat Mar 7 16:10:14 2009 @@ -204,6 +204,10 @@ [rffi.INT], rffi.INT) +GetTicks = external('SDL_GetTicks', + [], + Uint32) + Delay = external('SDL_Delay', [Uint32], lltype.Void) Modified: pypy/trunk/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/test/test_basic.py (original) +++ pypy/trunk/pypy/rlib/rsdl/test/test_basic.py Sat Mar 7 16:10:14 2009 @@ -28,3 +28,10 @@ assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' +def test_delay_getticks(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + RSDL.Delay(10) + i = RSDL.GetTicks() + assert i >= 10 + RSDL.Quit() + \ No newline at end of file From arigo at codespeak.net Sat Mar 7 16:25:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 16:25:46 +0100 (CET) Subject: [pypy-svn] r62714 - in pypy/trunk/pypy/translator/backendopt: . test Message-ID: <20090307152546.1A41D168458@codespeak.net> Author: arigo Date: Sat Mar 7 16:25:45 2009 New Revision: 62714 Modified: pypy/trunk/pypy/translator/backendopt/constfold.py pypy/trunk/pypy/translator/backendopt/test/test_constfold.py Log: Test and fix. Modified: pypy/trunk/pypy/translator/backendopt/constfold.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/constfold.py (original) +++ pypy/trunk/pypy/translator/backendopt/constfold.py Sat Mar 7 16:25:45 2009 @@ -241,7 +241,7 @@ vexit = block.exitswitch if isinstance(vexit, Variable): for link in block.exits: - if vexit in link.args: + if vexit in link.args and link.exitcase != 'default': remap = {vexit: Constant(link.llexitcase, vexit.concretetype)} link.args = [remap.get(v, v) for v in link.args] Modified: pypy/trunk/pypy/translator/backendopt/test/test_constfold.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/test/test_constfold.py (original) +++ pypy/trunk/pypy/translator/backendopt/test/test_constfold.py Sat Mar 7 16:25:45 2009 @@ -317,3 +317,21 @@ check_graph(graph, [2], 0, t) check_graph(graph, [10], 100, t) check_graph(graph, [42], 0, t) + +def test_merge_if_blocks_bug(): + def fn(n): + if n == 1: return 5 + elif n == 2: return 6 + elif n == 3: return 8 + elif n == 4: return -123 + elif n == 5: return 12973 + else: return n + + graph, t = get_graph(fn, [int]) + from pypy.translator.backendopt.removenoops import remove_same_as + from pypy.translator.backendopt import merge_if_blocks + remove_same_as(graph) + merge_if_blocks.merge_if_blocks_once(graph) + constant_fold_graph(graph) + check_graph(graph, [4], -123, t) + check_graph(graph, [9], 9, t) From fijal at codespeak.net Sat Mar 7 16:46:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 16:46:43 +0100 (CET) Subject: [pypy-svn] r62715 - pypy/trunk/pypy/jit/backend/x86 Message-ID: <20090307154643.5DBA0168458@codespeak.net> Author: fijal Date: Sat Mar 7 16:46:42 2009 New Revision: 62715 Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py Log: bah. implement call_pure and a debug info that helps to find it Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/assembler.py (original) +++ pypy/trunk/pypy/jit/backend/x86/assembler.py Sat Mar 7 16:46:42 2009 @@ -559,6 +559,20 @@ elif size == 2: self.mc.AND(eax, imm(0xffff)) + genop_call_pure = genop_call + + def not_implemented_op_discard(self, op, arglocs): + print "not implemented operation: %s" % op.getopname() + raise NotImplementedError + + def not_implemented_op(self, op, arglocs, resloc): + print "not implemented operation with res: %s" % op.getopname() + raise NotImplementedError + + def not_implemented_op_guard(self, op, arglocs, resloc, descr): + print "not implemented operation (guard): %s" % op.getopname() + raise NotImplementedError + #def genop_call__1(self, op, arglocs, resloc): # self.gen_call(op, arglocs, resloc) # self.mc.MOVZX(eax, al) @@ -568,9 +582,9 @@ # self.gen_call(op, arglocs, resloc) # self.mc.MOVZX(eax, eax) -genop_discard_list = [None] * (RETURN + 1) -genop_list = [None] * rop._LAST -genop_guard_list = [None] * rop._LAST +genop_discard_list = [Assembler386.not_implemented_op_discard] * (RETURN + 1) +genop_list = [Assembler386.not_implemented_op] * rop._LAST +genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST for name, value in Assembler386.__dict__.iteritems(): if name.startswith('genop_'): From arigo at codespeak.net Sat Mar 7 17:01:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 17:01:13 +0100 (CET) Subject: [pypy-svn] r62716 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090307160113.9EB7516844A@codespeak.net> Author: arigo Date: Sat Mar 7 17:01:11 2009 New Revision: 62716 Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py Log: Revert a part of a checkin that accidentally undid a bug fix. Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rclass.py Sat Mar 7 17:01:11 2009 @@ -415,17 +415,16 @@ else: return self.rbase.get_ll_hash_function() - def initialize_prebuilt_instance(self, value, classdef, result): + def initialize_prebuilt_data(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance - self.rbase.initialize_prebuilt_instance(value, classdef, - result.super) + self.rbase.initialize_prebuilt_data(value, classdef, result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): if r.lowleveltype is Void: llattrvalue = None elif name == '_hash_cache_': # hash() support - llattrvalue = hash(value) + continue # already done by initialize_prebuilt_hash() else: try: attrvalue = getattr(value, name) @@ -445,6 +444,14 @@ rclass = getclassrepr(self.rtyper, classdef) result.typeptr = rclass.getvtable() + def initialize_prebuilt_hash(self, value, result): + if self.classdef is not None: + self.rbase.initialize_prebuilt_hash(value, result.super) + if '_hash_cache_' in self.fields: + mangled_name, r = self.fields['_hash_cache_'] + llattrvalue = hash(value) + setattr(result, mangled_name, llattrvalue) + def getfieldrepr(self, attr): """Return the repr used for the given attribute.""" if attr in self.fields: From fijal at codespeak.net Sat Mar 7 17:57:32 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 17:57:32 +0100 (CET) Subject: [pypy-svn] r62717 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090307165732.86E56168442@codespeak.net> Author: fijal Date: Sat Mar 7 17:57:29 2009 New Revision: 62717 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Log: it's probably very wrong, but ll2ctypes is used when translating as well for getting sizes. It requires some refactoring to avoid that, for now let's say a weakref is a pointer Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Sat Mar 7 17:57:29 2009 @@ -48,6 +48,7 @@ lltype.Bool: ctypes.c_long, # XXX llmemory.Address: ctypes.c_void_p, llmemory.GCREF: ctypes.c_void_p, + llmemory.WeakRef: ctypes.c_void_p, # XXX }) # for unicode strings, do not use ctypes.c_wchar because ctypes From fijal at codespeak.net Sat Mar 7 17:58:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 17:58:00 +0100 (CET) Subject: [pypy-svn] r62718 - pypy/trunk/pypy/translator/goal Message-ID: <20090307165800.810AA168447@codespeak.net> Author: fijal Date: Sat Mar 7 17:58:00 2009 New Revision: 62718 Modified: pypy/trunk/pypy/translator/goal/targetpypystandalone.py Log: update pypy target Modified: pypy/trunk/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/trunk/pypy/translator/goal/targetpypystandalone.py Sat Mar 7 17:58:00 2009 @@ -198,9 +198,9 @@ return self.get_entry_point(config) - def portal(self, driver): - from pypy.module.pypyjit.portal import get_portal - return get_portal(driver) + def jitpolicy(self, driver): + from pypy.module.pypyjit.portal import PyPyJitPolicy + return PyPyJitPolicy(driver.translator) def get_entry_point(self, config): space = make_objspace(config) @@ -215,7 +215,7 @@ def interface(self, ns): for name in ['take_options', 'handle_config', 'print_help', 'target', - 'portal', + 'jitpolicy', 'get_additional_config_options']: ns[name] = getattr(self, name) From arigo at codespeak.net Sat Mar 7 18:04:33 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 18:04:33 +0100 (CET) Subject: [pypy-svn] r62719 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090307170433.404FA16841E@codespeak.net> Author: arigo Date: Sat Mar 7 18:04:32 2009 New Revision: 62719 Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: Performance enhancement: when interpreting with a BlackHole, do all calls as residual calls instead of regular calls. Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/codewriter.py (original) +++ pypy/trunk/pypy/jit/metainterp/codewriter.py Sat Mar 7 18:04:32 2009 @@ -17,8 +17,9 @@ class JitCode(history.AbstractValue): - def __init__(self, name): + def __init__(self, name, cfnptr): self.name = name + self.cfnptr = cfnptr def setup(self, code, constants): self.code = code @@ -87,8 +88,6 @@ graph = self.unfinished_graphs.pop() self.make_one_bytecode(graph, False) log.info("there are %d JitCode instances." % len(self.all_graphs)) - # xxx annotation hack: make sure there is at least one ConstAddr around - jitcode.constants.append(history.ConstAddr(llmemory.NULL, self.cpu)) return jitcode def make_one_bytecode(self, graph, portal): @@ -100,7 +99,9 @@ def get_jitcode(self, graph): if graph in self.all_graphs: return self.all_graphs[graph] - bytecode = JitCode(graph.name) # 'graph.name' is for dump() + fnptr = self.rtyper.getcallable(graph) + cfnptr = history.ConstAddr(llmemory.cast_ptr_to_adr(fnptr), self.cpu) + bytecode = JitCode(graph.name, cfnptr) # 'graph.name' is for dump() self.all_graphs[graph] = bytecode self.unfinished_graphs.append(graph) return bytecode @@ -660,7 +661,12 @@ self.minimize_variables() [targetgraph] = self.codewriter.policy.graphs_from(op) jitbox = self.codewriter.get_jitcode(targetgraph) + args = [x for x in op.args[1:] if x.concretetype is not lltype.Void] + argtypes = [v.concretetype for v in args] + resulttype = op.result.concretetype + calldescr = self.cpu.calldescrof(argtypes, resulttype) self.emit('call') + self.emit(calldescr) self.emit(self.get_position(jitbox)) self.emit_varargs([x for x in op.args[1:] if x.concretetype is not lltype.Void]) @@ -669,9 +675,9 @@ def handle_residual_call(self, op): self.minimize_variables() args = [x for x in op.args if x.concretetype is not lltype.Void] - argtypes = [v.concretetype for v in args] + argtypes = [v.concretetype for v in args[1:]] resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes[1:], resulttype) + calldescr = self.cpu.calldescrof(argtypes, resulttype) self.emit('residual_call') self.emit(calldescr) self.emit_varargs(args) Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Sat Mar 7 18:04:32 2009 @@ -391,11 +391,18 @@ def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc) - @arguments("bytecode", "varargs") - def opimpl_call(self, callee, varargs): - f = self.metainterp.newframe(callee) - f.setup_call(varargs) - return True + @arguments("int", "bytecode", "varargs") + def opimpl_call(self, calldescr, callee, varargs): + if not isinstance(self.metainterp.history, history.BlackHole): + # when tracing, this bytecode causes the subfunction to be entered + f = self.metainterp.newframe(callee) + f.setup_call(varargs) + return True + else: + # when producing only a BlackHole, we can implement this by + # calling the subfunction directly instead of interpreting it + varargs = [callee.cfnptr] + varargs + return self.execute_with_exc(rop.CALL, varargs, descr=calldescr) @arguments("int", "varargs") def opimpl_residual_call(self, calldescr, varargs): From arigo at codespeak.net Sat Mar 7 18:25:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 18:25:46 +0100 (CET) Subject: [pypy-svn] r62720 - in pypy/trunk/pypy/jit: . metainterp/test Message-ID: <20090307172546.1647E16844C@codespeak.net> Author: arigo Date: Sat Mar 7 18:25:45 2009 New Revision: 62720 Added: pypy/trunk/pypy/jit/conftest.py (contents, props changed) Modified: pypy/trunk/pypy/jit/metainterp/test/test_zrpy_basic.py Log: Add a py.test option, "--slow", to run all the test_zrpy_*. By default only one test is run, which should be enough to catch most cases. Added: pypy/trunk/pypy/jit/conftest.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/jit/conftest.py Sat Mar 7 18:25:45 2009 @@ -0,0 +1,13 @@ +import py + + +option = py.test.config.option + +class JitTestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("JIT options") + group.addoption('--slow', action="store_true", + default=False, dest="run_slow_tests", + help="run all the compiled tests (instead of just a few)") + +ConftestPlugin = JitTestPlugin Modified: pypy/trunk/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_zrpy_basic.py Sat Mar 7 18:25:45 2009 @@ -2,10 +2,14 @@ from pypy.jit.metainterp.warmspot import rpython_ll_meta_interp, ll_meta_interp from pypy.jit.metainterp.test import test_basic from pypy.rlib.jit import JitDriver +from pypy.jit.conftest import option + class TestBasic: def test_loop_1(self): + if not option.run_slow_tests: + py.test.skip("use --slow to execute this long-running test") jitdriver = JitDriver(greens = [], reds = ['i', 'total']) def f(i): total = 0 @@ -21,6 +25,7 @@ assert res == 490 def test_loop_2(self): + # this test runs even without the --slow option, to see at least one jitdriver = JitDriver(greens = [], reds = ['i', 'total']) def f(i): total = 0 @@ -39,9 +44,13 @@ class LLInterpJitMixin: type_system = 'lltype' - meta_interp = staticmethod(rpython_ll_meta_interp) basic = False + def meta_interp(self, *args, **kwds): + if not option.run_slow_tests: + py.test.skip("use --slow to execute this long-running test") + return rpython_ll_meta_interp(*args, **kwds) + def check_history(self, expected=None, **check): pass def check_loops(self, expected=None, **check): From arigo at codespeak.net Sat Mar 7 18:28:36 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 18:28:36 +0100 (CET) Subject: [pypy-svn] r62721 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090307172836.0308416844C@codespeak.net> Author: arigo Date: Sat Mar 7 18:28:36 2009 New Revision: 62721 Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py Log: Reintroduce this hack. Needed in case there is no CALL bytecode. Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/codewriter.py (original) +++ pypy/trunk/pypy/jit/metainterp/codewriter.py Sat Mar 7 18:28:36 2009 @@ -88,6 +88,8 @@ graph = self.unfinished_graphs.pop() self.make_one_bytecode(graph, False) log.info("there are %d JitCode instances." % len(self.all_graphs)) + # xxx annotation hack: make sure there is at least one ConstAddr around + jitcode.constants.append(history.ConstAddr(llmemory.NULL, self.cpu)) return jitcode def make_one_bytecode(self, graph, portal): From fijal at codespeak.net Sat Mar 7 18:44:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 18:44:38 +0100 (CET) Subject: [pypy-svn] r62722 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090307174438.341D6168455@codespeak.net> Author: fijal Date: Sat Mar 7 18:44:37 2009 New Revision: 62722 Modified: pypy/trunk/pypy/jit/metainterp/executor.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py pypy/trunk/pypy/jit/metainterp/resoperation.py Log: a bunch of missing ops Modified: pypy/trunk/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/executor.py (original) +++ pypy/trunk/pypy/jit/metainterp/executor.py Sat Mar 7 18:44:37 2009 @@ -46,6 +46,8 @@ do_uint_add = do_int_add do_uint_sub = do_int_sub do_uint_mul = do_int_mul +do_uint_lshift = do_int_lshift +do_uint_rshift = do_int_rshift # ---------- @@ -87,6 +89,8 @@ def do_int_is_true(cpu, args, descr=0): return ConstInt(bool(args[0].getint())) +do_uint_is_true = do_int_is_true + def do_int_neg(cpu, args, descr=0): return ConstInt(-args[0].getint()) Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Sat Mar 7 18:44:37 2009 @@ -225,10 +225,10 @@ 'int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', 'int_and', 'int_or', 'int_xor', - 'int_rshift', 'int_lshift', + 'int_rshift', 'int_lshift', 'uint_lshift', 'uint_rshift', 'uint_add', 'uint_sub', 'uint_mul', 'uint_lt', 'uint_le', 'uint_eq', - 'uint_ne', 'uint_gt', 'int_ge', + 'uint_ne', 'uint_gt', 'int_ge', 'uint_and', ]: exec py.code.Source(''' @arguments("box", "box") @@ -245,6 +245,7 @@ ''' % (_opimpl, _opimpl.upper())).compile() for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', + 'uint_is_true', ]: exec py.code.Source(''' @arguments("box") Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resoperation.py (original) +++ pypy/trunk/pypy/jit/metainterp/resoperation.py Sat Mar 7 18:44:37 2009 @@ -109,26 +109,29 @@ UINT_ADD = 40 UINT_SUB = 41 UINT_MUL = 42 + UINT_LSHIFT = 43 + UINT_RSHIFT = 44 # - _COMPARISON_FIRST = 44 - INT_LT = 44 - INT_LE = 45 - INT_EQ = 46 - INT_NE = 47 - INT_GT = 48 - INT_GE = 49 - UINT_LT = 50 - UINT_LE = 51 - UINT_EQ = 52 - UINT_NE = 53 - UINT_GT = 54 - UINT_GE = 55 + _COMPARISON_FIRST = 45 + INT_LT = 45 + INT_LE = 46 + INT_EQ = 47 + INT_NE = 48 + INT_GT = 49 + INT_GE = 50 + UINT_LT = 51 + UINT_LE = 52 + UINT_EQ = 53 + UINT_NE = 54 + UINT_GT = 55 + UINT_GE = 56 _COMPARISON_LAST = 55 # INT_IS_TRUE = 60 INT_NEG = 61 INT_INVERT = 62 BOOL_NOT = 63 + UINT_IS_TRUE = 64 # OONONNULL = 70 OOISNULL = 71 From fijal at codespeak.net Sat Mar 7 18:46:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 18:46:20 +0100 (CET) Subject: [pypy-svn] r62723 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090307174620.0CD97168458@codespeak.net> Author: fijal Date: Sat Mar 7 18:46:20 2009 New Revision: 62723 Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py Log: oops Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/resoperation.py (original) +++ pypy/trunk/pypy/jit/metainterp/resoperation.py Sat Mar 7 18:46:20 2009 @@ -125,7 +125,7 @@ UINT_NE = 54 UINT_GT = 55 UINT_GE = 56 - _COMPARISON_LAST = 55 + _COMPARISON_LAST = 56 # INT_IS_TRUE = 60 INT_NEG = 61 From arigo at codespeak.net Sat Mar 7 18:51:50 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 18:51:50 +0100 (CET) Subject: [pypy-svn] r62724 - in pypy/trunk/pypy/objspace/std: . test Message-ID: <20090307175150.11388168445@codespeak.net> Author: arigo Date: Sat Mar 7 18:51:49 2009 New Revision: 62724 Modified: pypy/trunk/pypy/objspace/std/builtinshortcut.py pypy/trunk/pypy/objspace/std/model.py pypy/trunk/pypy/objspace/std/objspace.py pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py Log: issue426 testing Improve builtinshortcut to work also for inplace operations that fallback to normal operations, like x += 5. Modified: pypy/trunk/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/trunk/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/trunk/pypy/objspace/std/builtinshortcut.py Sat Mar 7 18:51:49 2009 @@ -50,7 +50,7 @@ % (_name,)) -def install(space, mm): +def install(space, mm, fallback_mm=None): """Install a function () on the space instance which invokes a shortcut for built-in types. Returns the shortcutting multimethod object or None. @@ -79,6 +79,8 @@ # (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() + if fallback_mm: + mm = mm.merge_with(fallback_mm) shortcut_method = mm.install_not_sliced(expanded_order) def operate(*args_w): @@ -95,31 +97,21 @@ def install_is_true(space, mm_nonzero, mm_len): - nonzero_shortcut = install(space, mm_nonzero) - len_shortcut = install(space, mm_len) + shortcut = install(space, mm_nonzero, fallback_mm = 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) + w_res = 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 + # always directly return a Bool; however, the __len__ method + # of built-in objects typically returns an unwrappable integer + if isinstance(w_res, W_BoolObject): + return w_res.boolval try: return space.int_w(w_res) != 0 except OperationError: Modified: pypy/trunk/pypy/objspace/std/model.py ============================================================================== --- pypy/trunk/pypy/objspace/std/model.py (original) +++ pypy/trunk/pypy/objspace/std/model.py Sat Mar 7 18:51:49 2009 @@ -329,3 +329,29 @@ return self.install(prefix = '__mm_' + self.name, list_of_typeorders = [typeorder]*self.arity, baked_perform_call=baked_perform_call) + + def merge_with(self, other): + # Make a new 'merged' multimethod including the union of the two + # tables. In case of conflict, pick the entry from 'self'. + if self.arity != other.arity: + return self # XXX that's the case of '**' + operatorsymbol = '%s_merge_%s' % (self.name, other.name) + assert self.extras == other.extras + mm = StdObjSpaceMultiMethod(operatorsymbol, self.arity, **self.extras) + # + def merge(node1, node2): + assert type(node1) is type(node2) + if isinstance(node1, dict): + d = node1.copy() + d.update(node2) + for key in node1: + if key in node2: + d[key] = merge(node1[key], node2[key]) + return d + else: + assert isinstance(node1, list) + assert node1 + return node1 # pick the entry from 'self' + # + mm.dispatch_tree = merge(self.dispatch_tree, other.dispatch_tree) + return mm Modified: pypy/trunk/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/pypy/objspace/std/objspace.py Sat Mar 7 18:51:49 2009 @@ -286,7 +286,14 @@ setattr(self, name, boundmethod) # store into 'space' instance elif self.config.objspace.std.builtinshortcut: from pypy.objspace.std import builtinshortcut - builtinshortcut.install(self, mm) + if name.startswith('inplace_'): + fallback_name = name[len('inplace_'):] + if fallback_name in ('or', 'and'): + fallback_name += '_' + fallback_mm = self.MM.__dict__[fallback_name] + else: + fallback_mm = None + builtinshortcut.install(self, mm, fallback_mm) if self.config.objspace.std.builtinshortcut: from pypy.objspace.std import builtinshortcut Modified: pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py Sat Mar 7 18:51:49 2009 @@ -34,6 +34,34 @@ s.discard(F("abc")) assert not s + def test_inplace_methods(self): + assert '__iadd__' not in int.__dict__ + assert '__iadd__' not in float.__dict__ + x = 5 + x += 6.5 + assert x == 11.5 + + def test_inplace_user_subclasses(self): + class I(int): pass + class F(float): pass + x = I(5) + x += F(6.5) + assert x == 11.5 + assert type(x) is float + + def test_inplace_override(self): + class I(int): + def __iadd__(self, other): + return 'foo' + x = I(5) + x += 6 + assert x == 'foo' + x = I(5) + x += 6.5 + assert x == 'foo' + assert 5 + 6.5 == 11.5 + + class AppTestSet(test_set.AppTestAppSetTest): # this tests tons of funny comparison combinations that can easily go wrong def setup_class(cls): From fijal at codespeak.net Sat Mar 7 19:18:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Mar 2009 19:18:49 +0100 (CET) Subject: [pypy-svn] r62725 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090307181849.C1EBC168455@codespeak.net> Author: fijal Date: Sat Mar 7 19:18:48 2009 New Revision: 62725 Modified: pypy/trunk/pypy/jit/metainterp/executor.py Log: implement those correctly Modified: pypy/trunk/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/executor.py (original) +++ pypy/trunk/pypy/jit/metainterp/executor.py Sat Mar 7 19:18:48 2009 @@ -2,7 +2,7 @@ """ import py -from pypy.rlib.rarithmetic import ovfcheck, r_uint +from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask from pypy.jit.metainterp.history import BoxInt, ConstInt from pypy.jit.metainterp.resoperation import rop @@ -46,8 +46,14 @@ do_uint_add = do_int_add do_uint_sub = do_int_sub do_uint_mul = do_int_mul -do_uint_lshift = do_int_lshift -do_uint_rshift = do_int_rshift + +def do_uint_lshift(cpu, args, descr=0): + v = r_uint(args[0].getint()) << r_uint(args[1].getint()) + return ConstInt(intmask(v)) + +def do_uint_rshift(cpu, args, descr=0): + v = r_uint(args[0].getint()) >> r_uint(args[1].getint()) + return ConstInt(intmask(v)) # ---------- From arigo at codespeak.net Sat Mar 7 19:23:12 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Mar 2009 19:23:12 +0100 (CET) Subject: [pypy-svn] r62726 - pypy/trunk/pypy/module/pypyjit Message-ID: <20090307182312.7294E168457@codespeak.net> Author: arigo Date: Sat Mar 7 19:23:12 2009 New Revision: 62726 Modified: pypy/trunk/pypy/module/pypyjit/portal.py Log: Kill old code. Modified: pypy/trunk/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/trunk/pypy/module/pypyjit/portal.py (original) +++ pypy/trunk/pypy/module/pypyjit/portal.py Sat Mar 7 19:23:12 2009 @@ -131,10 +131,3 @@ 'pypy.interpreter.function': True, 'pypy.interpreter.pytraceback': True, } - - -def get_portal(drv): - t = drv.translator - policy = PyPyHintAnnotatorPolicy() - policy.seetranslator(t) - return None, policy From santagada at codespeak.net Sun Mar 8 01:11:50 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sun, 8 Mar 2009 01:11:50 +0100 (CET) Subject: [pypy-svn] r62728 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090308001150.596A0168436@codespeak.net> Author: santagada Date: Sun Mar 8 01:11:48 2009 New Revision: 62728 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: Scaling on the video driver (with a very naive algo), using sdl_delay and quitting when you close the window. Scaling is set to 2x, but 3x runs fast enough also. Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Sun Mar 8 01:11:48 2009 @@ -1,7 +1,9 @@ #___________________________________________________________________________ # GAMEBOY #___________________________________________________________________________ - + +USE_RSDL = True + # Gameboy Clock Speed (1048576 Hz) GAMEBOY_CLOCK = 1 << 20 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Sun Mar 8 01:11:48 2009 @@ -12,14 +12,19 @@ from pypy.lang.gameboy import constants import time -use_rsdl = True show_metadata = False # Extends the window with windows visualizing meta-data -if use_rsdl: +if constants.USE_RSDL: from pypy.rlib.rsdl import RSDL, RSDL_helper, RMix from pypy.rpython.lltypesystem import lltype, rffi + delay = RSDL.Delay + get_ticks = RSDL.GetTicks +else: + delay = time.sleep + + from pypy.rlib.objectmodel import specialize -import time + # GAMEBOY ---------------------------------------------------------------------- @@ -28,11 +33,11 @@ def __init__(self): GameBoy.__init__(self) self.is_running = False - self.penalty = 0.0 - self.sync_time = time.time() + self.penalty = 0 + self.sync_time = int(time.time()) def open_window(self): - if use_rsdl: + if constants.USE_RSDL: self.init_sdl() self.video_driver.create_screen() @@ -65,24 +70,24 @@ self.handle_events() # Come back to this cycle every 1/X seconds self.emulate(constants.GAMEBOY_CLOCK / X) - spent = time.time() - self.sync_time - left = (1.0/X) + self.penalty - spent + spent = int(time.time()) - self.sync_time + left = int(1000.0/X) + self.penalty - spent if left > 0: - time.sleep(left) - self.penalty = 0.0 + delay(left) + self.penalty = 0 else: - # Fade out penalties over time. + # Fade out penalties over time. self.penalty = left - self.penalty / 2 - self.sync_time = time.time() + self.sync_time = int(time.time()) def handle_execution_error(self, error): - if use_rsdl: + if constants.USE_RSDL: lltype.free(self.event, flavor='raw') RSDL.Quit() def handle_events(self): - if use_rsdl: + if constants.USE_RSDL: self.poll_event() if self.check_for_escape(): self.is_running = False @@ -90,19 +95,21 @@ def poll_event(self): - if use_rsdl: + if constants.USE_RSDL: ok = rffi.cast(lltype.Signed, RSDL.PollEvent(self.event)) return ok > 0 else: return True def check_for_escape(self): - if not use_rsdl: return False + if not constants.USE_RSDL: return False c_type = rffi.getintfield(self.event, 'c_type') if c_type == RSDL.KEYDOWN: p = rffi.cast(RSDL.KeyboardEventPtr, self.event) if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: return True + elif c_type == RSDL.QUIT: + return True return False @@ -114,13 +121,14 @@ def __init__(self, gameboy): VideoDriver.__init__(self) + self.scale = 2 if show_metadata: self.create_meta_windows(gameboy) def create_screen(self): - if use_rsdl: - self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) + if constants.USE_RSDL: + self.screen = RSDL.SetVideoMode(self.width*self.scale, self.height*self.scale, 32, 0) def create_meta_windows(self, gameboy): upper_meta_windows = [SpritesWindow(gameboy), @@ -148,7 +156,7 @@ def update_display(self): - if use_rsdl: + if constants.USE_RSDL: RSDL.LockSurface(self.screen) if show_metadata: for meta_window in self.meta_windows: @@ -161,9 +169,18 @@ self.draw_ascii_pixels() def draw_pixel(self, x, y, color): - color = VideoDriverImplementation.COLOR_MAP[color] - RSDL_helper.set_pixel(self.screen, x, y, color) - + color = self.COLOR_MAP[color] + start_x = x * self.scale + start_y = y * self.scale + + if self.scale > 1: + for x in range(self.scale): + for y in range(self.scale): + RSDL_helper.set_pixel(self.screen, start_x + x, + start_y + y, color) + else: + RSDL_helper.set_pixel(self.screen, start_x, start_y, color) + def draw_pixels(self): for y in range(constants.GAMEBOY_SCREEN_HEIGHT): for x in range(constants.GAMEBOY_SCREEN_WIDTH): @@ -187,7 +204,7 @@ self.last_key = 0 def update(self, event): - if not use_rsdl: return + if not constants.USE_RSDL: return # fetch the event from sdl type = rffi.getintfield(event, 'c_type') if type == RSDL.KEYDOWN: @@ -198,7 +215,7 @@ self.on_key_up() def create_called_key(self, event): - if use_rsdl: + if constants.USE_RSDL: p = rffi.cast(RSDL.KeyboardEventPtr, event) self.last_key = rffi.getintfield(p.c_keysym, 'c_sym') @@ -213,7 +230,7 @@ pressButtonFunction(self, enabled) def get_button_handler(self, key): - if not use_rsdl: return None + if not constants.USE_RSDL: return None if key == RSDL.K_UP: return JoypadDriver.button_up elif key == RSDL.K_RIGHT: From santagada at codespeak.net Sun Mar 8 01:30:03 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sun, 8 Mar 2009 01:30:03 +0100 (CET) Subject: [pypy-svn] r62729 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090308003003.43E64168436@codespeak.net> Author: santagada Date: Sun Mar 8 01:30:02 2009 New Revision: 62729 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: second button is now "s" on the keyboard, remember that when playing Metroid :) Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Sun Mar 8 01:30:02 2009 @@ -245,7 +245,7 @@ return JoypadDriver.button_select elif key == RSDL.K_a: return JoypadDriver.button_a - elif key == RSDL.K_b: + elif key == RSDL.K_s: return JoypadDriver.button_b return None From santagada at codespeak.net Sun Mar 8 01:49:19 2009 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sun, 8 Mar 2009 01:49:19 +0100 (CET) Subject: [pypy-svn] r62730 - pypy/trunk/pypy/rlib/rsdl Message-ID: <20090308004919.8F1AE16843A@codespeak.net> Author: santagada Date: Sun Mar 8 01:49:18 2009 New Revision: 62730 Modified: pypy/trunk/pypy/rlib/rsdl/RMix.py pypy/trunk/pypy/rlib/rsdl/RSDL.py Log: Some more missing parts of libsdl. Modified: pypy/trunk/pypy/rlib/rsdl/RMix.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RMix.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RMix.py Sun Mar 8 01:49:18 2009 @@ -24,7 +24,10 @@ class CConfig: _compilation_info_ = eci - Chunk = platform.Struct('Mix_Chunk', []) + Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), + ('abuf', RSDL.Uint8P), + ('alen', RSDL.Uint32), + ('volume', RSDL.Uint8)]) globals().update(platform.configure(CConfig)) Modified: pypy/trunk/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/trunk/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/trunk/pypy/rlib/rsdl/RSDL.py Sun Mar 8 01:49:18 2009 @@ -85,6 +85,9 @@ ('xrel', rffi.INT), ('yrel', rffi.INT)]) + QuitEvent = platform.Struct('SDL_QuitEvent', + [('type', rffi.INT)]) + RWops = platform.Struct('SDL_RWops', []) # ------------------------------------------------------------------------------ From fijal at codespeak.net Sun Mar 8 14:37:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 14:37:48 +0100 (CET) Subject: [pypy-svn] r62732 - pypy/trunk/pypy/translator Message-ID: <20090308133748.01D9516846B@codespeak.net> Author: fijal Date: Sun Mar 8 14:37:46 2009 New Revision: 62732 Modified: pypy/trunk/pypy/translator/driver.py Log: actually *use* generated policy Modified: pypy/trunk/pypy/translator/driver.py ============================================================================== --- pypy/trunk/pypy/translator/driver.py (original) +++ pypy/trunk/pypy/translator/driver.py Sun Mar 8 14:37:46 2009 @@ -374,7 +374,7 @@ self.jitpolicy = get_policy(self) # from pypy.jit.metainterp.warmspot import apply_jit - apply_jit(self.translator) + apply_jit(self.translator, policy=self.jitpolicy) # self.log.info("the JIT compiler was generated") # From fijal at codespeak.net Sun Mar 8 15:31:25 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 15:31:25 +0100 (CET) Subject: [pypy-svn] r62733 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090308143125.73021168495@codespeak.net> Author: fijal Date: Sun Mar 8 15:31:23 2009 New Revision: 62733 Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: fix specialcasing Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Sun Mar 8 15:31:23 2009 @@ -16,6 +16,7 @@ populate_type_cache) from pypy.jit.metainterp import codewriter, optimize, executor from pypy.rlib.rarithmetic import intmask +from pypy.rlib.objectmodel import specialize # ____________________________________________________________ @@ -652,12 +653,13 @@ cls = llmemory.cast_ptr_to_adr(obj.typeptr) return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) + @specialize.arg(1) def execute(self, opnum, argboxes, descr=0): resbox = self.metainterp.execute_and_record(opnum, argboxes, descr) if resbox is not None: self.make_result_box(resbox) - execute._annspecialcase_ = 'specialize:arg(1)' + @specialize.arg(1) def execute_with_exc(self, opnum, argboxes, descr=0): cpu = self.metainterp.cpu resbox = executor.execute(cpu, opnum, argboxes, descr) From fijal at codespeak.net Sun Mar 8 18:32:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 18:32:22 +0100 (CET) Subject: [pypy-svn] r62734 - in pypy/trunk/pypy/jit: backend/llgraph backend/x86 metainterp Message-ID: <20090308173222.6B7791684A8@codespeak.net> Author: fijal Date: Sun Mar 8 18:32:19 2009 New Revision: 62734 Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py pypy/trunk/pypy/jit/backend/x86/runner.py pypy/trunk/pypy/jit/metainterp/codewriter.py Log: Actually check for the correct number of args. I think it's fine by now.... Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/runner.py Sun Mar 8 18:32:19 2009 @@ -216,7 +216,7 @@ return size*2 + bit @staticmethod - def calldescrof(ARGS, RESULT): + def calldescrof(ARGS, RESULT, ignored=None): if RESULT is lltype.Void: return sys.maxint token = history.getkind(RESULT) Modified: pypy/trunk/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/runner.py (original) +++ pypy/trunk/pypy/jit/backend/x86/runner.py Sun Mar 8 18:32:19 2009 @@ -16,6 +16,7 @@ from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.x86.executor import execute from pypy.jit.backend.x86.support import gc_malloc_fnaddr +from pypy.objspace.flow.model import Constant GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) @@ -590,7 +591,13 @@ return size_of_field, ofs @staticmethod - def calldescrof(argtypes, resulttype): + def calldescrof(argtypes, resulttype, funcobj=None): + if isinstance(funcobj, Constant): + ARGS = lltype.typeOf(funcobj.value).TO.ARGS + lgt = len([arg for arg in ARGS if arg is not lltype.Void]) + assert lgt == len(argtypes) + else: + assert funcobj is None if resulttype is lltype.Void: size = 0 else: Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/codewriter.py (original) +++ pypy/trunk/pypy/jit/metainterp/codewriter.py Sun Mar 8 18:32:19 2009 @@ -666,7 +666,7 @@ args = [x for x in op.args[1:] if x.concretetype is not lltype.Void] argtypes = [v.concretetype for v in args] resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes, resulttype) + calldescr = self.cpu.calldescrof(argtypes, resulttype, op.args[0]) self.emit('call') self.emit(calldescr) self.emit(self.get_position(jitbox)) @@ -679,7 +679,7 @@ args = [x for x in op.args if x.concretetype is not lltype.Void] argtypes = [v.concretetype for v in args[1:]] resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes, resulttype) + calldescr = self.cpu.calldescrof(argtypes, resulttype, op.args[0]) self.emit('residual_call') self.emit(calldescr) self.emit_varargs(args) @@ -725,7 +725,7 @@ opname = 'residual_call_pure' # XXX not for possibly-raising calls else: opname = 'residual_call' - calldescr = self.cpu.calldescrof(argtypes, resulttype) + calldescr = self.cpu.calldescrof(argtypes, resulttype, None) self.emit(opname) self.emit(calldescr) self.emit_varargs([c_func] + args) From fijal at codespeak.net Sun Mar 8 18:57:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 18:57:49 +0100 (CET) Subject: [pypy-svn] r62735 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090308175749.37D811684BB@codespeak.net> Author: fijal Date: Sun Mar 8 18:57:46 2009 New Revision: 62735 Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: Revert 62719. It broke a bit translation and I have no clue why and commit message sais it's a performance improvement. Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/codewriter.py (original) +++ pypy/trunk/pypy/jit/metainterp/codewriter.py Sun Mar 8 18:57:46 2009 @@ -17,9 +17,8 @@ class JitCode(history.AbstractValue): - def __init__(self, name, cfnptr): + def __init__(self, name): self.name = name - self.cfnptr = cfnptr def setup(self, code, constants): self.code = code @@ -101,9 +100,7 @@ def get_jitcode(self, graph): if graph in self.all_graphs: return self.all_graphs[graph] - fnptr = self.rtyper.getcallable(graph) - cfnptr = history.ConstAddr(llmemory.cast_ptr_to_adr(fnptr), self.cpu) - bytecode = JitCode(graph.name, cfnptr) # 'graph.name' is for dump() + bytecode = JitCode(graph.name) # 'graph.name' is for dump() self.all_graphs[graph] = bytecode self.unfinished_graphs.append(graph) return bytecode @@ -663,12 +660,7 @@ self.minimize_variables() [targetgraph] = self.codewriter.policy.graphs_from(op) jitbox = self.codewriter.get_jitcode(targetgraph) - args = [x for x in op.args[1:] if x.concretetype is not lltype.Void] - argtypes = [v.concretetype for v in args] - resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes, resulttype, op.args[0]) self.emit('call') - self.emit(calldescr) self.emit(self.get_position(jitbox)) self.emit_varargs([x for x in op.args[1:] if x.concretetype is not lltype.Void]) @@ -677,9 +669,9 @@ def handle_residual_call(self, op): self.minimize_variables() args = [x for x in op.args if x.concretetype is not lltype.Void] - argtypes = [v.concretetype for v in args[1:]] + argtypes = [v.concretetype for v in args] resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes, resulttype, op.args[0]) + calldescr = self.cpu.calldescrof(argtypes[1:], resulttype, op.args[0]) self.emit('residual_call') self.emit(calldescr) self.emit_varargs(args) Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Sun Mar 8 18:57:46 2009 @@ -395,16 +395,9 @@ @arguments("int", "bytecode", "varargs") def opimpl_call(self, calldescr, callee, varargs): - if not isinstance(self.metainterp.history, history.BlackHole): - # when tracing, this bytecode causes the subfunction to be entered - f = self.metainterp.newframe(callee) - f.setup_call(varargs) - return True - else: - # when producing only a BlackHole, we can implement this by - # calling the subfunction directly instead of interpreting it - varargs = [callee.cfnptr] + varargs - return self.execute_with_exc(rop.CALL, varargs, descr=calldescr) + f = self.metainterp.newframe(callee) + f.setup_call(varargs) + return True @arguments("int", "varargs") def opimpl_residual_call(self, calldescr, varargs): From fijal at codespeak.net Sun Mar 8 19:06:12 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 19:06:12 +0100 (CET) Subject: [pypy-svn] r62736 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090308180612.CF4D21684BF@codespeak.net> Author: fijal Date: Sun Mar 8 19:06:12 2009 New Revision: 62736 Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: oops, actually revert it properly Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Sun Mar 8 19:06:12 2009 @@ -393,8 +393,8 @@ def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc) - @arguments("int", "bytecode", "varargs") - def opimpl_call(self, calldescr, callee, varargs): + @arguments("bytecode", "varargs") + def opimpl_call(self, callee, varargs): f = self.metainterp.newframe(callee) f.setup_call(varargs) return True From fijal at codespeak.net Sun Mar 8 21:19:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 21:19:04 +0100 (CET) Subject: [pypy-svn] r62737 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090308201904.E8FE01684CC@codespeak.net> Author: fijal Date: Sun Mar 8 21:19:02 2009 New Revision: 62737 Modified: pypy/trunk/pypy/rpython/lltypesystem/llmemory.py Log: provide a hash for llmemory.Address. This is needed when having a prebuilt dict of Address keys, the creation of rdict takes forever Modified: pypy/trunk/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/llmemory.py Sun Mar 8 21:19:02 2009 @@ -411,6 +411,11 @@ def __nonzero__(self): return self.ptr is not None + def __hash__(self): + if not self._fixup().ptr: + return 0 + return hash(self._fixup().ptr._obj) + def __eq__(self, other): if isinstance(other, fakeaddress): obj1 = self._fixup().ptr From fijal at codespeak.net Sun Mar 8 23:25:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 8 Mar 2009 23:25:40 +0100 (CET) Subject: [pypy-svn] r62739 - in pypy/trunk/pypy: jit/metainterp jit/metainterp/test rpython rpython/lltypesystem translator Message-ID: <20090308222540.04CCC1684D4@codespeak.net> Author: fijal Date: Sun Mar 8 23:25:39 2009 New Revision: 62739 Modified: pypy/trunk/pypy/jit/metainterp/support.py pypy/trunk/pypy/jit/metainterp/test/test_exception.py pypy/trunk/pypy/jit/metainterp/test/test_zrpy_exception.py pypy/trunk/pypy/jit/metainterp/warmspot.py pypy/trunk/pypy/rpython/llinterp.py pypy/trunk/pypy/rpython/lltypesystem/lloperation.py pypy/trunk/pypy/translator/exceptiontransform.py Log: try to do the right thing with ExitFrameWithExc. It almost works, except for the fact that it hits wrong exc block when run on top of x86 backend. IN-PROGRESS Modified: pypy/trunk/pypy/jit/metainterp/support.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/support.py (original) +++ pypy/trunk/pypy/jit/metainterp/support.py Sun Mar 8 23:25:39 2009 @@ -1,4 +1,4 @@ -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, rclass from pypy.rpython.ootypesystem import ootype from pypy.rpython import rlist from pypy.rpython.lltypesystem import rdict, rstr @@ -12,6 +12,7 @@ from pypy.annotation.policy import AnnotatorPolicy from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import MixLevelHelperAnnotator +from pypy.rpython.extregistry import ExtRegistryEntry def getargtypes(annotator, values): if values is None: # for backend tests producing stand-alone exe's @@ -221,3 +222,20 @@ rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT + +def raise_exc_value(tp, value): + from pypy.rpython.llinterp import LLException + raise LLException(tp, value) + +class Entry(ExtRegistryEntry): + _about_ = raise_exc_value + + def compute_result_annotation(self, s_tp, s_value): + return annmodel.s_ImpossibleValue + + def specialize_call(self, hop): + v_list = [hop.inputarg(hop.args_r[0], arg=0), + hop.inputarg(hop.args_r[1], arg=1)] + hop.has_implicit_exception(Exception) + hop.exception_is_here() + return hop.genop('raise_exc_value', v_list) Modified: pypy/trunk/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_exception.py Sun Mar 8 23:25:39 2009 @@ -321,6 +321,31 @@ res = self.interp_operations(f, [1, 2]) assert res == 1 + + def test_reraise_through_portal(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + + class SomeException(Exception): + pass + + def portal(n): + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + if n == 10: + raise SomeException + n -= 1 + + def f(n): + try: + portal(n) + except SomeException, e: + return 3 + return 2 + + res = self.meta_interp(f, [100]) + assert res == 3 + class MyError(Exception): def __init__(self, n): self.n = n Modified: pypy/trunk/pypy/jit/metainterp/test/test_zrpy_exception.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_zrpy_exception.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_zrpy_exception.py Sun Mar 8 23:25:39 2009 @@ -1,7 +1,7 @@ import py from pypy.jit.metainterp.test import test_exception from pypy.jit.metainterp.test.test_zrpy_basic import LLInterpJitMixin - +from pypy.rlib.jit import JitDriver class TestLLExceptions(test_exception.ExceptionTests, LLInterpJitMixin): def interp_operations(self, *args, **kwds): @@ -14,6 +14,5 @@ def test_raise_through_wrong_exc(self): skip1() def test_raise_through_wrong_exc_2(self): skip1() - def skip1(): py.test.skip("the portal always raises, causing blocked blocks") Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmspot.py Sun Mar 8 23:25:39 2009 @@ -10,6 +10,7 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.jit import PARAMETERS from pypy.rlib.rarithmetic import r_uint +from pypy.rpython.lltypesystem.lloperation import llop from pypy.jit.metainterp import support, history, pyjitpl from pypy.jit.metainterp.pyjitpl import OOMetaInterp, Options @@ -304,13 +305,9 @@ return unwrap(RESULT, e.resultbox) except ExitFrameWithException, e: value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) - if we_are_translated(): - # re-raise the exception as it is - raise Exception, value - else: - type = e.typebox.getaddr(self.metainterp.cpu) - type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) - raise LLException(type, value) + type = e.typebox.getaddr(self.metainterp.cpu) + type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) + support.raise_exc_value(type, value) portal_runner_ptr = self.helper_func(lltype.Ptr(PORTALFUNC), ll_portal_runner) Modified: pypy/trunk/pypy/rpython/llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/llinterp.py (original) +++ pypy/trunk/pypy/rpython/llinterp.py Sun Mar 8 23:25:39 2009 @@ -1181,6 +1181,9 @@ def op_oohash(self, s): return ootype.oohash(s) + def op_raise_exc_value(self, etype, evalue): + raise LLException(etype, evalue) + class Tracer(object): Counter = 0 file = None Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lloperation.py Sun Mar 8 23:25:39 2009 @@ -397,6 +397,7 @@ 'promote_virtualizable':LLOp(canrun=True), 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), + 'raise_exc_value' : LLOp(canraise=(Exception,)), # __________ GC operations __________ Modified: pypy/trunk/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/trunk/pypy/translator/exceptiontransform.py (original) +++ pypy/trunk/pypy/translator/exceptiontransform.py Sun Mar 8 23:25:39 2009 @@ -199,15 +199,18 @@ block.operations[i].opname = "direct_call" block.operations[i].args = [self.rpyexc_fetch_exception_ptr] - if opname == 'gc_restore_exception': + elif opname == 'gc_restore_exception': block.operations[i].opname = "direct_call" block.operations[i].args.insert(0, self.rpyexc_restore_exception_ptr) - if opname == 'get_exception_addr': # only for lltype + elif opname == 'get_exception_addr': # only for lltype block.operations[i].opname = "direct_call" block.operations[i].args.insert(0, self.rpyexc_get_exception_addr_ptr) - if opname == 'get_exc_value_addr': # only for lltype + elif opname == 'get_exc_value_addr': # only for lltype block.operations[i].opname = "direct_call" block.operations[i].args.insert(0, self.rpyexc_get_exc_value_addr_ptr) + elif opname == 'raise_exc_value': + block.operations[i].opname = 'direct_call' + block.operations[i].args.insert(0, self.rpyexc_raise_ptr) def transform_block(self, graph, block): need_exc_matching = False From fijal at codespeak.net Mon Mar 9 00:03:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 00:03:06 +0100 (CET) Subject: [pypy-svn] r62741 - pypy/trunk/pypy/translator Message-ID: <20090308230306.00CDA1684E3@codespeak.net> Author: fijal Date: Mon Mar 9 00:03:06 2009 New Revision: 62741 Modified: pypy/trunk/pypy/translator/exceptiontransform.py Log: A fix. A bit awkward if you ask me, but makes the test pass Modified: pypy/trunk/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/trunk/pypy/translator/exceptiontransform.py (original) +++ pypy/trunk/pypy/translator/exceptiontransform.py Mon Mar 9 00:03:06 2009 @@ -170,7 +170,7 @@ n_gen_exc_checks = 0 for block in list(graph.iterblocks()): self.replace_stack_unwind(block) - self.replace_fetch_restore_operations(block) + self.replace_fetch_restore_operations(graph, block) need_exc_matching, gen_exc_checks = self.transform_block(graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks @@ -189,7 +189,7 @@ block.operations[i].opname = "direct_call" block.operations[i].args = [self.rpyexc_raise_runtime_error_ptr] - def replace_fetch_restore_operations(self, block): + def replace_fetch_restore_operations(self, graph, block): # the gctransformer will create these operations. It looks as if the # order of transformations is important - but the gctransformer will # put them in a new graph, so all transformations will run again. @@ -211,6 +211,9 @@ elif opname == 'raise_exc_value': block.operations[i].opname = 'direct_call' block.operations[i].args.insert(0, self.rpyexc_raise_ptr) + del block.operations[i + 1:] + l = Link([error_constant(graph.returnblock.inputargs[0].concretetype)], graph.returnblock) + block.recloseblock(l) def transform_block(self, graph, block): need_exc_matching = False From hpk at codespeak.net Mon Mar 9 11:53:52 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 9 Mar 2009 11:53:52 +0100 (CET) Subject: [pypy-svn] r62748 - pypy/extradoc/talk/openbossa2009/pypy-mobile Message-ID: <20090309105352.A212816856C@codespeak.net> Author: hpk Date: Mon Mar 9 11:53:52 2009 New Revision: 62748 Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/ pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex (contents, props changed) - copied, changed from r62662, pypy/extradoc/talk/pycon-uk-2008/status/author.latex pypy/extradoc/talk/openbossa2009/pypy-mobile/makepdf (contents, props changed) - copied, changed from r62662, pypy/extradoc/talk/pycon-uk-2008/status/makepdf pypy/extradoc/talk/openbossa2009/pypy-mobile/merlinux-logo.jpg (props changed) - copied unchanged from r62662, pypy/extradoc/talk/pycon-uk-2008/status/merlinux-logo.jpg pypy/extradoc/talk/openbossa2009/pypy-mobile/sandboxed.png (props changed) - copied unchanged from r62662, pypy/extradoc/talk/pycon-uk-2008/status/sandboxed.png pypy/extradoc/talk/openbossa2009/pypy-mobile/stylesheet.latex (props changed) - copied unchanged from r62662, pypy/extradoc/talk/pycon-uk-2008/status/stylesheet.latex pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/title.latex (props changed) - copied unchanged from r62662, pypy/extradoc/talk/pycon-uk-2008/status/title.latex Log: draft slides Copied: pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex (from r62662, pypy/extradoc/talk/pycon-uk-2008/status/author.latex) ============================================================================== --- pypy/extradoc/talk/pycon-uk-2008/status/author.latex (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex Mon Mar 9 11:53:52 2009 @@ -1,8 +1,7 @@ \definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} -\title[PyPy status talk]{PyPy status talk} -\author[H. Krekel, M. Fijalkowski]{Holger Krekel \and Maciej Fijalkowski\\ -Merlinux GmbH} +\title[PyPy status / mobile perspectives]{PyPy status / mobile perspectives} +\author[H. Krekel]{Holger Krekel \\ Merlinux GmbH} -\institute[PyCon UK 2008]{PyCon UK 2008 - Birmingham} -\date{September 13 2008} +\institute[OpenBossa 2009, Recife, Brazil]{OpenBossa 2009, Brazil} +\date{March 11, 2009} Copied: pypy/extradoc/talk/openbossa2009/pypy-mobile/makepdf (from r62662, pypy/extradoc/talk/pycon-uk-2008/status/makepdf) ============================================================================== --- pypy/extradoc/talk/pycon-uk-2008/status/makepdf (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/makepdf Mon Mar 9 11:53:52 2009 @@ -6,9 +6,9 @@ # WARNING: to work, it needs this patch for docutils # https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414 -BASE=status +BASE=talk rst2beamer.py --stylesheet=stylesheet.latex --documentoptions=14pt $BASE.txt $BASE.latex || exit -sed 's/\\date{}/\\input{author.latex}/' -i $BASE.latex || exit -sed 's/\\maketitle/\\input{title.latex}/' -i $BASE.latex || exit +sed 's/\\date{}/\\input{author.latex}/' $BASE.latex >tmpfile || exit +sed 's/\\maketitle/\\input{title.latex}/' tmpfile >$BASE.latex || exit pdflatex $BASE.latex || exit Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Mon Mar 9 11:53:52 2009 @@ -0,0 +1,326 @@ +===================================== +PyPy: status and mobile perspectives +===================================== + +What this talk is about +======================= + +* Status of PyPy / 1.1 release + +* resource usage / startup time + +* some ideas for improvements + + +PyPy? +======== + +In this talk mostly: + + PyPy = PyPy Python Interpreter + +PyPy - developer motivation +================================= + +* Separate language specification from low-level details + +* layer GCs, JIT, Stackless atop the spec + +* generate interpreters for C, .NET, JVM, embedded platforms, ... + +PyPy - user motivation +======================= + +* use Python rather than C for performance + +* have a more resource efficient interpreter + +* support more programming paradigms + +* Just-in-time compiler should make number-crunching + and static-enough code fast enough + + +Getting Production ready +========================== + +* we worked a lot on running + existing applications on top of PyPy + +* PyPy today very (most?) compatible to Python 2.5 + +* main blocker for running apps will be **missing external modules** + + +Sqlite +====== + +* part of cpython stdlib since 2.5 + +* we use Gerhard Haering's CTypes version + +* works reasonably well after some fixes + +Django +====== + +* we run unmodified Django 1.0 + +* only with sqlite DB backend for now + +http://www.djangoproject.com + +http://code.djangoproject.com/wiki/DjangoAndPyPy + + +Pylons +====== + +* worked almost out of the box once eggs + were working (1 day) + +* no SQLAlchemy yet, obscure problems + ahead + +* unmodified passes all tests + +* http://pylonshq.com/ + +Twisted & Nevow +=============== + +* twisted works (60/4500 tests failing) + +* nevow works + +* we don't support PyCrypto nor PyOpenSSL and we + won't anytime soon (if nobody contributes CTypes or rpython + versions) + +* http://twistedmatrix.com/ + + +Other software +============== + +* pure python should just work + +* setup.py / distutils works + +* BitTorrent + +* PyPy translation toolchain + +* py lib + +* sympy + +CTypes +====== + +* official way to have bindings to + external (C) libraries for PyPy + +* can handle i.e. pysqlite-ctypes, pyglet, pymunk or Sole Scion, + almost whatever.... + +* contribution to original ctypes + (better errno handling, bugfixes, tests...) + +* part of google sponsoring + +* XXX 32bit and a bit slow + +CTypes configure +================ + +* our own small addition to general + CTypes usefulness + +* invokes C compiler for small details + +* can handle #defines, types, structure layout + etc. + +Memory - comparison with CPython +=================================== + +* PyPy has pluggable Garbage Collection + +* gcbench - 0.8 (because of our faster GCs) + +* better handling of unusual patterns + +* care needed with communication with C + +* GCs are semi-decent + + +Speed of executing bytecode +=============================== + +* we're something between 0.8-4x slower than + CPython on executing bytecode + +* our JIT is to be the huge leap beyond CPython + + +Threading / Stackless +=================================== + +* currently using GIL, quite robust + +* free threading? requires research + some work + +* pypy-c has software threading / stackless + +* added during translation + +Other backends +============== + +* PyPy-jvm runs! + +* more integration between pypy-cli and .NET + +* general speed improvements + +* both backends are progressing - very slowly though + +* contributors wanted! + +Sandboxing +========== + +* fully sandboxed python interpreter + +* all external calls to C goes via another + python process + +* special library for making custom + policies + +.. image:: sandboxed.png + :scale: 30 + :align: center + +pypy-c measurements on Maemo +=============================== + +- cross-compiled to Maemo +- measurements done on N810 device +- done with http://codespeak.net/svn/pypy/build/benchmem/pypy/ +- python object sizes, application benchmarks, startup time +- base interpreter size, GC pauses, interpretation speed + +Python object sizes +======================= + +- PyPy has smaller "per-object" RAM usage +- class instances usually at 50% of CPython size or less +- a lot of room for further optimizations + +see table at http://codespeak.net/~hpk/openbossa09/table-objsizes.html + +startup time +======================= + + +--------------+--------+-------------+---------------+ + |startup |python |pypy-Omem-opt|python-launcher| + +--------------+--------+-------------+---------------+ + |site |**0.24**|**0.16**/0.13|**0.11**/0.00 | + +--------------+--------+-------------+---------------+ + |nosite |**0.21**|**0.04**/0.03|**0.11**/0.00 | + +--------------+--------+-------------+---------------+ + |importos |**0.21**|**0.04**/0.03|**0.11**/0.00 | + +--------------+--------+-------------+---------------+ + |importdecimal |**0.47**|**0.42**/0.39|**0.34**/0.00 | + +--------------+--------+-------------+---------------+ + |importoptparse|**0.54**|**0.04**/0.01|**0.11**/0.00 | + +--------------+--------+-------------+---------------+ + +where pypy is currently worse +=================================== + +- interpreter size: larger than cpython, but mostly shareable +- gc collection pauses can be larger: needs work +- bytecode execution speed: 1-4 times slower than CPython + +(FYI also our parser and compiler implementation is bad) + +Where pypy is already better +============================= + +- more efficient RAM usage +- faster startup +- more secure + +Extension modules +=================== + +- for binding to C-libs: ctypes +- for speed: JIT or if need be: rpython +- binding to C++? + +Idea: C++ Extension modules +============================= + +- idea: use CERN's Reflex mechanism +- generate shared "introspect" library for each C++ lib +- write generic small extension module in Python + +Idea: perfect PYC files +============================ + +- PYC file gets MMAPed into process memory +- interpreter directly works with memory data structures +- executes bytecode to construct __dict__ + +-> total sharing of bytecode and constants +-> no allocation of redundant objects during import + +Idea: next-generation GC work +=============================== + +- currently: naive Mark&Compact (500 lines of code) +- port/implement researched techniques +- malloc-directed inlining +- maximize shared interpreter state +- minimize collection pauses / incremental collection + +a word about doing GCs +=================================== + +- program your GC in Python +- test your GC in Python +- get tracebacks on memory faults +- once ready, translate with Python Interpreter + +Outlook / +========= + +- PyPy 1.1 release in 1-2 months +- get the JIT to surpass CPython speed +- perfect/commoditize Python sandboxing +- help/do compatibility work, ext modules +- C++? +- bring PyPy to symbian and more mobiles? + +Contact / Q&A +========================== + +holger krekel +at http://merlinux.eu + +PyPy: http://codespeak.net/pypy + +My Blog: http://tetamap.wordpress.com +PyPy Blog: http://morepypy.blogspot.com + +.. raw:: latex + + \begin{figure} + \includegraphics[width=64px,height=64px]{merlinux-logo.jpg} + \qquad + \includegraphics[width=80px]{../../img/py-web.png} + \end{figure} From fijal at codespeak.net Mon Mar 9 12:57:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 12:57:31 +0100 (CET) Subject: [pypy-svn] r62750 - pypy/trunk/pypy/jit/backend/x86 Message-ID: <20090309115731.7D836169E10@codespeak.net> Author: fijal Date: Mon Mar 9 12:57:31 2009 New Revision: 62750 Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py Log: be more explicit about missing opts Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/trunk/pypy/jit/backend/x86/regalloc.py Mon Mar 9 12:57:31 2009 @@ -952,7 +952,11 @@ self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] -oplist = [None] * (RETURN + 1) + def not_implemented_op(self, op, ignored): + print "[regalloc] Not implemented operation: %s" % op.getopname() + raise NotImplementedError + +oplist = [RegAlloc.not_implemented_op] * (RETURN + 1) for name, value in RegAlloc.__dict__.iteritems(): if name.startswith('consider_'): From fijal at codespeak.net Mon Mar 9 12:58:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 12:58:04 +0100 (CET) Subject: [pypy-svn] r62751 - pypy/trunk/pypy/jit/backend/x86/test Message-ID: <20090309115804.37B2A169E13@codespeak.net> Author: fijal Date: Mon Mar 9 12:58:03 2009 New Revision: 62751 Added: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_virtualizable.py (contents, props changed) Log: port test_zrpy_virtualizable to x86 backend Added: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_virtualizable.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_virtualizable.py Mon Mar 9 12:58:03 2009 @@ -0,0 +1,9 @@ + +import py +from pypy.jit.metainterp.test import test_virtualizable +from pypy.jit.backend.x86.test.test_zrpy_slist import Jit386Mixin + + +class TestLLImplicitVirtualizable(Jit386Mixin, + test_virtualizable.ImplicitVirtualizableTests): + pass From fijal at codespeak.net Mon Mar 9 13:02:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 13:02:01 +0100 (CET) Subject: [pypy-svn] r62752 - pypy/trunk/pypy/jit/metainterp/test Message-ID: <20090309120201.5687C169E19@codespeak.net> Author: fijal Date: Mon Mar 9 13:02:00 2009 New Revision: 62752 Modified: pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py Log: one more test + update external_read Modified: pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_virtualizable.py Mon Mar 9 13:02:00 2009 @@ -342,8 +342,41 @@ res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == 0 + def test_external_pass(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 'z'], + virtualizables = ['frame']) + + class BaseFrame(object): + _virtualizable2_ = True + + def __init__(self, x): + self.x = x + + class Frame(BaseFrame): + pass + + def g(x): + return x[1] == 1 + + def f(n): + frame = Frame([1,2,3]) + z = 0 + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n, z=z) + jitdriver.jit_merge_point(frame=frame, n=n, z=z) + z += g(frame.x) + n -= 1 + return z + + res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) + assert res == f(10) + + def test_external_read(self): py.test.skip("Fails") + jitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + class Frame(object): _virtualizable2_ = True class SomewhereElse: @@ -361,12 +394,13 @@ frame.y = 10 somewhere_else.top_frame = frame while frame.x > 0: + jitdriver.can_enter_jit(frame=frame) + jitdriver.jit_merge_point(frame=frame) frame.x -= g() frame.y += 1 return frame.x - res = self.meta_interp(f, [123], exceptions=False, - policy=StopAtXPolicy(g)) + res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) assert res == f(123) self.check_loops(getfield_gc=0, setfield_gc=0) From fijal at codespeak.net Mon Mar 9 14:10:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:10:47 +0100 (CET) Subject: [pypy-svn] r62756 - pypy/trunk/pypy/rpython/test Message-ID: <20090309131047.43265168078@codespeak.net> Author: fijal Date: Mon Mar 9 14:10:45 2009 New Revision: 62756 Modified: pypy/trunk/pypy/rpython/test/test_rdict.py Log: A test for __hash__ of address Modified: pypy/trunk/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rdict.py (original) +++ pypy/trunk/pypy/rpython/test/test_rdict.py Mon Mar 9 14:10:45 2009 @@ -750,6 +750,35 @@ res = self.interpret(func, []) assert 5 + 6 + 7 <= res <= 5 + 6 + 7 + (5^16) + (6^16) + (7^16) + def test_prebuilt_list_of_addresses(self): + from pypy.rpython.lltypesystem import llmemory + + TP = lltype.Struct('x', ('y', lltype.Signed)) + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + c = lltype.malloc(TP, flavor='raw', immortal=True) + a_a = llmemory.cast_ptr_to_adr(a) + a0 = llmemory.cast_ptr_to_adr(a) + assert a_a is not a0 + assert a_a == a0 + a_b = llmemory.cast_ptr_to_adr(b) + a_c = llmemory.cast_ptr_to_adr(c) + + d = {a_a: 3, a_b: 4, a_c: 5} + d[a0] = 8 + + def func(i): + if i == 0: + ptr = a + else: + ptr = b + return d[llmemory.cast_ptr_to_adr(ptr)] + + res = self.interpret(func, [0]) + assert res == 8 + res = self.interpret(func, [1]) + assert res == 4 + # ____________________________________________________________ From fijal at codespeak.net Mon Mar 9 14:12:55 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:12:55 +0100 (CET) Subject: [pypy-svn] r62757 - pypy/trunk/pypy/translator/c/test Message-ID: <20090309131255.B5929169E3C@codespeak.net> Author: fijal Date: Mon Mar 9 14:12:52 2009 New Revision: 62757 Modified: pypy/trunk/pypy/translator/c/test/test_lladdresses.py Log: the same test for C (exploding!) Modified: pypy/trunk/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/trunk/pypy/translator/c/test/test_lladdresses.py Mon Mar 9 14:12:52 2009 @@ -173,3 +173,29 @@ fn = compile(f, [int], gcpolicy='boehm') assert fn(3) == 123 assert fn(-3) == -42 + +def test_prebuilt_list_of_addresses(): + TP = lltype.Struct('x', ('y', lltype.Signed)) + a = lltype.malloc(TP, flavor='raw', immortal=True) + b = lltype.malloc(TP, flavor='raw', immortal=True) + c = lltype.malloc(TP, flavor='raw', immortal=True) + a_a = cast_ptr_to_adr(a) + a0 = cast_ptr_to_adr(a) + assert a_a is not a0 + assert a_a == a0 + a_b = cast_ptr_to_adr(b) + a_c = cast_ptr_to_adr(c) + + d = {a_a: 3, a_b: 4, a_c: 5} + d[a0] = 8 + + def func(i): + if i == 0: + ptr = a + else: + ptr = b + return d[cast_ptr_to_adr(ptr)] + + fn = compile(func, [int], gcpolicy='boehm') + assert fn(0) == 8 + assert fn(1) == 4 From fijal at codespeak.net Mon Mar 9 14:24:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:24:58 +0100 (CET) Subject: [pypy-svn] r62758 - pypy/trunk/pypy/translator/c/test Message-ID: <20090309132458.D4C06169E49@codespeak.net> Author: fijal Date: Mon Mar 9 14:24:58 2009 New Revision: 62758 Modified: pypy/trunk/pypy/translator/c/test/test_lladdresses.py Log: remove this test Modified: pypy/trunk/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/trunk/pypy/translator/c/test/test_lladdresses.py Mon Mar 9 14:24:58 2009 @@ -1,3 +1,4 @@ +import py from pypy.rpython.lltypesystem.llmemory import * from pypy.annotation.model import SomeAddress, SomeChar from pypy.translator.c.test.test_genc import compile @@ -173,29 +174,3 @@ fn = compile(f, [int], gcpolicy='boehm') assert fn(3) == 123 assert fn(-3) == -42 - -def test_prebuilt_list_of_addresses(): - TP = lltype.Struct('x', ('y', lltype.Signed)) - a = lltype.malloc(TP, flavor='raw', immortal=True) - b = lltype.malloc(TP, flavor='raw', immortal=True) - c = lltype.malloc(TP, flavor='raw', immortal=True) - a_a = cast_ptr_to_adr(a) - a0 = cast_ptr_to_adr(a) - assert a_a is not a0 - assert a_a == a0 - a_b = cast_ptr_to_adr(b) - a_c = cast_ptr_to_adr(c) - - d = {a_a: 3, a_b: 4, a_c: 5} - d[a0] = 8 - - def func(i): - if i == 0: - ptr = a - else: - ptr = b - return d[cast_ptr_to_adr(ptr)] - - fn = compile(func, [int], gcpolicy='boehm') - assert fn(0) == 8 - assert fn(1) == 4 From fijal at codespeak.net Mon Mar 9 14:25:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:25:33 +0100 (CET) Subject: [pypy-svn] r62759 - in pypy/trunk/pypy/rpython: lltypesystem test Message-ID: <20090309132533.AA53A169E4D@codespeak.net> Author: fijal Date: Mon Mar 9 14:25:33 2009 New Revision: 62759 Modified: pypy/trunk/pypy/rpython/lltypesystem/rdict.py pypy/trunk/pypy/rpython/test/test_rdict.py Log: now that I know why not, let's explode when we have a prebuilt dictionary with addresses as keys Modified: pypy/trunk/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rdict.py Mon Mar 9 14:25:33 2009 @@ -197,6 +197,7 @@ def convert_const(self, dictobj): + from pypy.rpython.lltypesystem import llmemory # get object from bound dict methods #dictobj = getattr(dictobj, '__self__', dictobj) if dictobj is None: @@ -211,6 +212,8 @@ l_dict = ll_newdict_size(self.DICT, len(dictobj)) self.dict_cache[key] = l_dict r_key = self.key_repr + if r_key.lowleveltype == llmemory.Address: + raise TypeError("No prebuilt dicts of address keys") r_value = self.value_repr if isinstance(dictobj, objectmodel.r_dict): if self.r_rdict_eqfn.lowleveltype != lltype.Void: Modified: pypy/trunk/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rdict.py (original) +++ pypy/trunk/pypy/rpython/test/test_rdict.py Mon Mar 9 14:25:33 2009 @@ -774,10 +774,7 @@ ptr = b return d[llmemory.cast_ptr_to_adr(ptr)] - res = self.interpret(func, [0]) - assert res == 8 - res = self.interpret(func, [1]) - assert res == 4 + py.test.raises(TypeError, self.interpret, func, [0]) # ____________________________________________________________ From fijal at codespeak.net Mon Mar 9 14:26:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:26:08 +0100 (CET) Subject: [pypy-svn] r62760 - pypy/trunk/pypy/translator Message-ID: <20090309132608.5F606169E4C@codespeak.net> Author: fijal Date: Mon Mar 9 14:26:07 2009 New Revision: 62760 Modified: pypy/trunk/pypy/translator/driver.py Log: asserts are useful for debugging, leave it alone Modified: pypy/trunk/pypy/translator/driver.py ============================================================================== --- pypy/trunk/pypy/translator/driver.py (original) +++ pypy/trunk/pypy/translator/driver.py Mon Mar 9 14:26:07 2009 @@ -362,7 +362,7 @@ merge_if_blocks=True, constfold=True, raisingop2direct_call=False, - remove_asserts=True) + remove_asserts=False) # task_prejitbackendopt_lltype = taskdef( task_prejitbackendopt_lltype, From fijal at codespeak.net Mon Mar 9 14:53:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:53:42 +0100 (CET) Subject: [pypy-svn] r62761 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309135342.A5BD7169E6F@codespeak.net> Author: fijal Date: Mon Mar 9 14:53:42 2009 New Revision: 62761 Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: some low level debug facilities Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Mon Mar 9 14:53:42 2009 @@ -24,6 +24,7 @@ for arg in args: assert isinstance(arg, (Box, Const)) +LLDEBUG = False class arguments(object): def __init__(self, *argtypes, **kwargs): @@ -603,6 +604,8 @@ op = ord(self.bytecode[pc]) #print self.metainterp.opcode_names[op] self.pc = pc + 1 + if LLDEBUG: + print "EXECUTE %d %d" % (pc, op) stop = self.metainterp.opcode_implementations[op](self, pc) #self.metainterp.most_recent_mp = None if stop: @@ -659,6 +662,8 @@ if not we_are_translated(): self.metainterp._debug_history.append(['call', argboxes[0], argboxes[1:]]) + elif LLDEBUG: + print "CALL %d" % argboxes[0].getint() # record the operation in the history self.metainterp.history.record(opnum, argboxes, resbox, descr) if resbox is not None: @@ -670,6 +675,7 @@ class OOMetaInterp(object): num_green_args = 0 + class_sizes = None def __init__(self, portal_graph, graphs, cpu, stats, options): self.portal_graph = portal_graph @@ -682,11 +688,19 @@ self.opcode_implementations = [] self.opcode_names = [] self.opname_to_index = {} - self.class_sizes = populate_type_cache(graphs, self.cpu) - + self._class_sizes = populate_type_cache(graphs, self.cpu) + if not cpu.translate_support_code: + self.class_sizes = self._class_sizes self._virtualizabledescs = {} self._debug_history = [] + def _recompute_class_sizes(self): + if self.class_sizes is None: + cs = {} + for key, value in self._class_sizes: + cs[key] = value + self.class_sizes = cs + def generate_bytecode(self, policy): self._codewriter = codewriter.CodeWriter(self, policy) self.portal_code = self._codewriter.make_portal_bytecode( @@ -698,8 +712,11 @@ return not we_are_translated() def newframe(self, jitcode): + self._recompute_class_sizes() if not we_are_translated(): self._debug_history.append(['enter', jitcode, None]) + elif LLDEBUG: + print "ENTER %s" % jitcode.name f = MIFrame(self, jitcode) self.framestack.append(f) return f @@ -708,6 +725,9 @@ frame = self.framestack.pop() if not we_are_translated(): self._debug_history.append(['leave', frame.jitcode, None]) + else: + if LLDEBUG: + print "LEAVE %s" % frame.jitcode.name if self.framestack: if resultbox is not None: self.framestack[-1].make_result_box(resultbox) @@ -726,6 +746,8 @@ return True if not we_are_translated(): self._debug_history.append(['leave_exc', frame.jitcode, None]) + elif LLDEBUG: + print "LEAVE_EXC %s" % frame.jitcode.name self.framestack.pop() raise self.ExitFrameWithException(exceptionbox, excvaluebox) @@ -954,6 +976,8 @@ def rebuild_state_after_failure(self, key, newboxes): if not we_are_translated(): self._debug_history.append(['guard_failure', None, None]) + elif LLDEBUG: + print "GUARD_FAILURE" self.framestack = [] nbindex = 0 for jitcode, pc, envlength, exception_target in key: From fijal at codespeak.net Mon Mar 9 14:56:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:56:33 +0100 (CET) Subject: [pypy-svn] r62762 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309135633.41146169E74@codespeak.net> Author: fijal Date: Mon Mar 9 14:56:32 2009 New Revision: 62762 Modified: pypy/trunk/pypy/jit/metainterp/heaptracker.py Log: oops, a missing commit Modified: pypy/trunk/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/trunk/pypy/jit/metainterp/heaptracker.py Mon Mar 9 14:56:32 2009 @@ -64,7 +64,10 @@ testing_gcstruct2vtable[GCSTRUCT] = vtable def populate_type_cache(graphs, cpu): - cache = {} + if not cpu.translate_support_code: + cache = {} + else: + cache = [] for graph in graphs: for block in graph.iterblocks(): for op in block.operations: @@ -79,7 +82,7 @@ cache[vt] = cpu.sizeof(STRUCT) else: vt = llmemory.cast_ptr_to_adr(vtable) - cache[vt] = cpu.sizeof(STRUCT) + cache.append((vt, cpu.sizeof(STRUCT))) return cache testing_gcstruct2vtable = {} From fijal at codespeak.net Mon Mar 9 14:56:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 14:56:48 +0100 (CET) Subject: [pypy-svn] r62763 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309135648.35FF0169E77@codespeak.net> Author: fijal Date: Mon Mar 9 14:56:47 2009 New Revision: 62763 Modified: pypy/trunk/pypy/jit/metainterp/optimize.py Log: this one also Modified: pypy/trunk/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/optimize.py (original) +++ pypy/trunk/pypy/jit/metainterp/optimize.py Mon Mar 9 14:56:47 2009 @@ -1024,7 +1024,11 @@ for vtable in storage.allocations: if metainterp.cpu.translate_support_code: vtable_addr = metainterp.cpu.cast_int_to_adr(vtable) - size = metainterp.class_sizes[vtable_addr] + try: + size = metainterp.class_sizes[vtable_addr] + except KeyError: + print vtable_addr, vtable, "CRAAAAAAAASH" + raise else: size = metainterp.class_sizes[vtable] vtablebox = ConstInt(vtable) From cfbolz at codespeak.net Mon Mar 9 17:35:59 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 9 Mar 2009 17:35:59 +0100 (CET) Subject: [pypy-svn] r62764 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090309163559.0B015169E94@codespeak.net> Author: cfbolz Date: Mon Mar 9 17:35:57 2009 New Revision: 62764 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: it seems veeeery likely that I will come. Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Mon Mar 9 17:35:57 2009 @@ -1,5 +1,5 @@ -People coming to the Leysin sprint Winter 2008 +People coming to the Leysin sprint Winter 2009 ================================================== People who have a ``?`` in their arrive/depart or accomodation @@ -11,6 +11,7 @@ Name Arrive/Depart Accomodation ==================== ============== ======================= Armin Rigo -- private +Carl Friedrich Bolz 14th-21st Ermina ==================== ============== ======================= People on the following list were present at previous sprints: @@ -18,7 +19,6 @@ ==================== ============== ===================== Name Arrive/Depart Accomodation ==================== ============== ===================== -Carl Friedrich Bolz ? ? Antonio Cuni ? ? Maciej Fijalkowski ? ? Toby Watson ? ? From cfbolz at codespeak.net Mon Mar 9 17:53:28 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 9 Mar 2009 17:53:28 +0100 (CET) Subject: [pypy-svn] r62765 - pypy/branch/speedup-globals Message-ID: <20090309165328.67C27169EA0@codespeak.net> Author: cfbolz Date: Mon Mar 9 17:53:28 2009 New Revision: 62765 Added: pypy/branch/speedup-globals/ - copied from r62764, pypy/trunk/ Log: A branch to try Armin's and mine newest idea about how to speed up global lookups. From arigo at codespeak.net Mon Mar 9 17:59:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Mar 2009 17:59:34 +0100 (CET) Subject: [pypy-svn] r62766 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309165934.B8683169EA1@codespeak.net> Author: arigo Date: Mon Mar 9 17:59:34 2009 New Revision: 62766 Modified: pypy/trunk/pypy/jit/metainterp/executor.py Log: uint_lshift is the same as int_lshift. Modified: pypy/trunk/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/executor.py (original) +++ pypy/trunk/pypy/jit/metainterp/executor.py Mon Mar 9 17:59:34 2009 @@ -46,10 +46,7 @@ do_uint_add = do_int_add do_uint_sub = do_int_sub do_uint_mul = do_int_mul - -def do_uint_lshift(cpu, args, descr=0): - v = r_uint(args[0].getint()) << r_uint(args[1].getint()) - return ConstInt(intmask(v)) +do_uint_lshift = do_int_lshift def do_uint_rshift(cpu, args, descr=0): v = r_uint(args[0].getint()) >> r_uint(args[1].getint()) From fijal at codespeak.net Mon Mar 9 18:01:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 18:01:19 +0100 (CET) Subject: [pypy-svn] r62767 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309170119.C6637169EA5@codespeak.net> Author: fijal Date: Mon Mar 9 18:01:17 2009 New Revision: 62767 Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py Log: revert a bit of my changes Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmspot.py Mon Mar 9 18:01:17 2009 @@ -1,6 +1,7 @@ import sys from pypy.rpython.lltypesystem import lltype, llmemory, rclass -from pypy.rpython.annlowlevel import llhelper, MixLevelHelperAnnotator +from pypy.rpython.annlowlevel import llhelper, MixLevelHelperAnnotator,\ + cast_base_ptr_to_instance from pypy.annotation import model as annmodel from pypy.rpython.llinterp import LLException from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache @@ -305,9 +306,13 @@ return unwrap(RESULT, e.resultbox) except ExitFrameWithException, e: value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) - type = e.typebox.getaddr(self.metainterp.cpu) - type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) - support.raise_exc_value(type, value) + if we_are_translated(): + type = e.typebox.getaddr(self.metainterp.cpu) + type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) + raise LLException(type, value) + else: + value = cast_base_ptr_to_instance(Exception, value) + raise Exception, value portal_runner_ptr = self.helper_func(lltype.Ptr(PORTALFUNC), ll_portal_runner) From arigo at codespeak.net Mon Mar 9 18:09:08 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Mar 2009 18:09:08 +0100 (CET) Subject: [pypy-svn] r62768 - pypy/trunk/pypy/doc/config Message-ID: <20090309170908.D3906169E91@codespeak.net> Author: arigo Date: Mon Mar 9 18:09:04 2009 New Revision: 62768 Added: pypy/trunk/pypy/doc/config/translation.jit.txt (contents, props changed) Log: Add missing file. Added: pypy/trunk/pypy/doc/config/translation.jit.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/config/translation.jit.txt Mon Mar 9 18:09:04 2009 @@ -0,0 +1,2 @@ +Enable the JIT generator, for targets that have JIT support. +Experimental so far. From arigo at codespeak.net Mon Mar 9 18:22:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Mar 2009 18:22:02 +0100 (CET) Subject: [pypy-svn] r62769 - pypy/trunk/pypy/jit/backend Message-ID: <20090309172202.E0359169EA3@codespeak.net> Author: arigo Date: Mon Mar 9 18:22:01 2009 New Revision: 62769 Modified: pypy/trunk/pypy/jit/backend/detect_cpu.py Log: Typo. Modified: pypy/trunk/pypy/jit/backend/detect_cpu.py ============================================================================== --- pypy/trunk/pypy/jit/backend/detect_cpu.py (original) +++ pypy/trunk/pypy/jit/backend/detect_cpu.py Mon Mar 9 18:22:01 2009 @@ -45,5 +45,5 @@ if cpu == 'i386': from pypy.jit.backend.x86.runner import CPU else: - raise Exception('Unsuported cpu %r' % cpu) + raise ProcessorAutodetectError, "unsupported cpu '%s'" % cpu return CPU From arigo at codespeak.net Mon Mar 9 18:22:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Mar 2009 18:22:32 +0100 (CET) Subject: [pypy-svn] r62770 - pypy/trunk/pypy/config Message-ID: <20090309172232.1D87F169E9F@codespeak.net> Author: arigo Date: Mon Mar 9 18:22:31 2009 New Revision: 62770 Modified: pypy/trunk/pypy/config/translationoption.py Log: Require list comprehension for now (to ensure that more lists are fixed-size). Modified: pypy/trunk/pypy/config/translationoption.py ============================================================================== --- pypy/trunk/pypy/config/translationoption.py (original) +++ pypy/trunk/pypy/config/translationoption.py Mon Mar 9 18:22:31 2009 @@ -111,7 +111,8 @@ # JIT generation BoolOption("jit", "generate a JIT", default=False, cmdline="--jit", - requires=[("translation.gc", "boehm")]), + requires=[("translation.gc", "boehm"), + ("translation.list_comprehension_operations", True)]), # misc BoolOption("verbose", "Print extra information", default=False), From afa at codespeak.net Mon Mar 9 18:40:19 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Mar 2009 18:40:19 +0100 (CET) Subject: [pypy-svn] r62771 - in pypy/trunk/pypy/rpython/lltypesystem: . test Message-ID: <20090309174019.B6EA8169EB2@codespeak.net> Author: afa Date: Mon Mar 9 18:40:18 2009 New Revision: 62771 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Fix one case where a recursive structure cannot be built if we start with the one that is inlined in the other. Seen when translating with the --jit option. Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Mon Mar 9 18:40:18 2009 @@ -69,7 +69,10 @@ if max_n is not None and fieldname == S._arrayfld: cls = get_ctypes_array_of_size(FIELDTYPE, max_n) else: - cls = get_ctypes_type(FIELDTYPE) + if isinstance(FIELDTYPE, lltype.Ptr): + cls = get_ctypes_type(FIELDTYPE, delayed_builders) + else: + cls = get_ctypes_type(FIELDTYPE) fields.append((fieldname, cls)) CStruct._fields_ = fields Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Mon Mar 9 18:40:18 2009 @@ -929,7 +929,8 @@ } """) - eci = ExternalCompilationInfo(separate_module_sources=[c_source]) + eci = ExternalCompilationInfo(separate_module_sources=[c_source], + export_symbols=['eating_callback']) args = [T, rffi.CCallback([T], rffi.INT)] eating_callback = rffi.llexternal('eating_callback', args, rffi.INT, @@ -953,6 +954,20 @@ assert pc2.contents.value == 42 assert pc2.contents.next.contents.value == 42 + def test_indirect_recursive_struct_more(self): + NODE = lltype.ForwardReference() + NODE2 = lltype.Struct('NODE2', ('ping', lltype.Ptr(NODE))) + NODE.become(lltype.Struct('NODE', ('pong', NODE2))) + + # Building NODE2 first used to fail. + get_ctypes_type(NODE2) + + CNODEPTR = get_ctypes_type(NODE) + pc = CNODEPTR() + pc.pong.ping = ctypes.pointer(pc) + p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc)) + assert p.pong.ping == p + def test_cast_adr_to_int(self): class someaddr(object): def _cast_to_int(self): From arigo at codespeak.net Mon Mar 9 18:48:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Mar 2009 18:48:35 +0100 (CET) Subject: [pypy-svn] r62772 - in pypy/trunk/pypy/jit: backend/llgraph backend/x86 metainterp Message-ID: <20090309174835.19761169EBE@codespeak.net> Author: arigo Date: Mon Mar 9 18:48:34 2009 New Revision: 62772 Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py pypy/trunk/pypy/jit/backend/x86/runner.py pypy/trunk/pypy/jit/metainterp/codewriter.py Log: Clean-up: don't push the sanity-checking during codewriter.py to the backend. Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/trunk/pypy/jit/backend/llgraph/runner.py Mon Mar 9 18:48:34 2009 @@ -216,7 +216,7 @@ return size*2 + bit @staticmethod - def calldescrof(ARGS, RESULT, ignored=None): + def calldescrof(ARGS, RESULT): if RESULT is lltype.Void: return sys.maxint token = history.getkind(RESULT) Modified: pypy/trunk/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/runner.py (original) +++ pypy/trunk/pypy/jit/backend/x86/runner.py Mon Mar 9 18:48:34 2009 @@ -16,7 +16,6 @@ from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.x86.executor import execute from pypy.jit.backend.x86.support import gc_malloc_fnaddr -from pypy.objspace.flow.model import Constant GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) @@ -591,13 +590,7 @@ return size_of_field, ofs @staticmethod - def calldescrof(argtypes, resulttype, funcobj=None): - if isinstance(funcobj, Constant): - ARGS = lltype.typeOf(funcobj.value).TO.ARGS - lgt = len([arg for arg in ARGS if arg is not lltype.Void]) - assert lgt == len(argtypes) - else: - assert funcobj is None + def calldescrof(argtypes, resulttype): if resulttype is lltype.Void: size = 0 else: Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/codewriter.py (original) +++ pypy/trunk/pypy/jit/metainterp/codewriter.py Mon Mar 9 18:48:34 2009 @@ -114,6 +114,18 @@ IndirectCallset(self, graphs) return result + def getcalldescr(self, v_func, args, result): + non_void_args = [x for x in args if x.concretetype is not lltype.Void] + NON_VOID_ARGS = [x.concretetype for x in non_void_args] + RESULT = result.concretetype + # check the number and type of arguments + ARGS = v_func.concretetype.TO.ARGS + assert NON_VOID_ARGS == [T for T in ARGS if T is not lltype.Void] + assert RESULT == v_func.concretetype.TO.RESULT + # ok + calldescr = self.cpu.calldescrof(NON_VOID_ARGS, RESULT) + return calldescr, non_void_args + if 0: # disabled def fixed_list_descr_for_tp(self, TP): @@ -668,13 +680,12 @@ def handle_residual_call(self, op): self.minimize_variables() - args = [x for x in op.args if x.concretetype is not lltype.Void] - argtypes = [v.concretetype for v in args] - resulttype = op.result.concretetype - calldescr = self.cpu.calldescrof(argtypes[1:], resulttype, op.args[0]) + calldescr, non_void_args = self.codewriter.getcalldescr(op.args[0], + op.args[1:], + op.result) self.emit('residual_call') self.emit(calldescr) - self.emit_varargs(args) + self.emit_varargs([op.args[0]] + non_void_args) self.register_var(op.result) def handle_builtin_call(self, op): @@ -717,10 +728,12 @@ opname = 'residual_call_pure' # XXX not for possibly-raising calls else: opname = 'residual_call' - calldescr = self.cpu.calldescrof(argtypes, resulttype, None) + + calldescr, non_void_args = self.codewriter.getcalldescr(c_func, args, + op.result) self.emit(opname) self.emit(calldescr) - self.emit_varargs([c_func] + args) + self.emit_varargs([c_func] + non_void_args) self.register_var(op.result) def handle_list_call(self, op, oopspec_name, args, TP): From cfbolz at codespeak.net Mon Mar 9 19:02:51 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 9 Mar 2009 19:02:51 +0100 (CET) Subject: [pypy-svn] r62773 - in pypy/branch/speedup-globals/pypy: config interpreter objspace objspace/fake objspace/std objspace/std/test Message-ID: <20090309180251.38711169EC3@codespeak.net> Author: cfbolz Date: Mon Mar 9 19:02:50 2009 New Revision: 62773 Modified: pypy/branch/speedup-globals/pypy/config/pypyoption.py pypy/branch/speedup-globals/pypy/interpreter/module.py pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py pypy/branch/speedup-globals/pypy/objspace/reflective.py pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py pypy/branch/speedup-globals/pypy/objspace/std/objspace.py pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py Log: First step to make global lookups faster: Introduce a special dict implementation for modules, where every value in the RPython-level dict is a cell that contains the real value. As long as the "valid" flag on such a cell is set, it is safe to store the cell somewhere else. Modified: pypy/branch/speedup-globals/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/speedup-globals/pypy/config/pypyoption.py (original) +++ pypy/branch/speedup-globals/pypy/config/pypyoption.py Mon Mar 9 19:02:50 2009 @@ -222,6 +222,13 @@ "use dictionaries optimized for flexibility", default=False), + BoolOption("withcelldict", + "use dictionaries that are opimized for being used as module dicts", + default=False, + requires=[("objspace.std.withmultidict", True), + ("objspace.opcodes.CALL_LIKELY_BUILTIN", False), + ("objspace.honor__builtins__", False)]), + BoolOption("withsharingdict", "use dictionaries that share the keys part", default=False, Modified: pypy/branch/speedup-globals/pypy/interpreter/module.py ============================================================================== --- pypy/branch/speedup-globals/pypy/interpreter/module.py (original) +++ pypy/branch/speedup-globals/pypy/interpreter/module.py Mon Mar 9 19:02:50 2009 @@ -11,7 +11,7 @@ def __init__(self, space, w_name, w_dict=None): self.space = space if w_dict is None: - w_dict = space.newdict(track_builtin_shadowing=True) + w_dict = space.newdict(module=True) self.w_dict = w_dict self.w_name = w_name if w_name is not None: Modified: pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py Mon Mar 9 19:02:50 2009 @@ -93,7 +93,7 @@ newint = make_dummy() newlong = make_dummy() newfloat = make_dummy() - def newdict(self, track_builtin_shadowing=False): + def newdict(self, module=False): return self.newfloat() newlist = make_dummy() emptylist = make_dummy() Modified: pypy/branch/speedup-globals/pypy/objspace/reflective.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/reflective.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/reflective.py Mon Mar 9 19:02:50 2009 @@ -137,8 +137,8 @@ return None if opname == "newdict": # grr grr kwargs - def fn(track_builtin_shadowing=False): - w_obj = parentfn(track_builtin_shadowing) + def fn(module=False): + w_obj = parentfn(module) w_newobj = user_hook(w_obj) if w_newobj is not None: return w_newobj Modified: pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py Mon Mar 9 19:02:50 2009 @@ -865,6 +865,134 @@ else: return None +class ModuleCell(object): + def __init__(self): + self.w_value = None + self.valid = True + + def invalidate(self): + self.w_value = None + self.valid = False + +class ModuleDictImplementation(DictImplementation): + def __init__(self, space): + self.space = space + self.content = {} + + def getcell(self, key, make_new=True): + try: + return self.content[key] + except KeyError: + if not make_new: + raise + result = self.content[key] = ModuleCell() + return result + + def setitem(self, w_key, w_value): + space = self.space + if space.is_w(space.type(w_key), space.w_str): + return self.setitem_str(w_key, w_value) + else: + return self._as_rdict().setitem(w_key, w_value) + + def setitem_str(self, w_key, w_value, shadows_type=True): + self.getcell(self.space.str_w(w_key)).w_value = w_value + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + cell = self.getcell(key, False) + cell.invalidate() + del self.content[key] + return self + elif _is_sane_hash(space, w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def length(self): + return len(self.content) + + def get(self, w_lookup): + space = self.space + w_lookup_type = space.type(w_lookup) + if space.is_w(w_lookup_type, space.w_str): + try: + return self.getcell(space.str_w(w_lookup), False).w_value + except KeyError: + return None + elif _is_sane_hash(space, w_lookup_type): + return None + else: + return self._as_rdict().get(w_lookup) + + def iteritems(self): + return ModuleDictItemIteratorImplementation(self.space, self) + + def iterkeys(self): + return ModuleDictKeyIteratorImplementation(self.space, self) + + def itervalues(self): + return ModuleDictValueIteratorImplementation(self.space, self) + + def keys(self): + space = self.space + return [space.wrap(key) for key in self.content.iterkeys()] + + def values(self): + return [cell.w_value for cell in self.content.itervalues()] + + def items(self): + space = self.space + return [space.newtuple([space.wrap(key), cell.w_value]) + for (key, cell) in self.content.iteritems()] + + def _as_rdict(self): + newimpl = self.space.DefaultDictImpl(self.space) + for k, cell in self.content.iteritems(): + newimpl.setitem(self.space.wrap(k), cell.w_value) + cell.invalidate() + return newimpl + +# grrrrr. just a copy-paste from StrKeyIteratorImplementation above +class ModuleDictKeyIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iterkeys() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key in self.iterator: + return self.space.wrap(key) + else: + return None + +class ModuleDictValueIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.itervalues() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for cell in self.iterator: + return cell.w_value + else: + return None + +class ModuleDictItemIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iteritems() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key, cell in self.iterator: + return self.space.newtuple([self.space.wrap(key), cell.w_value]) + else: + return None import time, py @@ -1038,8 +1166,10 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space, wary=False, sharing=False): - if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: + def __init__(w_self, space, wary=False, sharing=False, module=False): + if space.config.objspace.std.withcelldict and wary: + w_self.implementation = ModuleDictImplementation(space) + elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: w_self.implementation = WaryDictImplementation(space) elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) Modified: pypy/branch/speedup-globals/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/objspace.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/objspace.py Mon Mar 9 19:02:50 2009 @@ -580,8 +580,8 @@ from pypy.objspace.std.listobject import W_ListObject return W_ListObject(list_w) - def newdict(self, track_builtin_shadowing=False): - if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing: + def newdict(self, module=False): + if self.config.objspace.std.withmultidict and module: from pypy.objspace.std.dictmultiobject import W_DictMultiObject return W_DictMultiObject(self, wary=True) return self.DictObjectCls(self) Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py Mon Mar 9 19:02:50 2009 @@ -2,7 +2,8 @@ from pypy.objspace.std.dictmultiobject import \ W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \ EmptyDictImplementation, RDictImplementation, StrDictImplementation, \ - SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation + SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation, \ + ModuleDictImplementation from pypy.conftest import gettestobjspace from pypy.objspace.std.test import test_dictobject @@ -58,6 +59,26 @@ a.__dict__.items() == [("abc", 12)] +class AppTestModuleDict(object): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withcelldict": True}) + cls.w_impl_used = cls.space.appexec([], """(): + import __pypy__ + def impl_used(obj): + assert "ModuleDictImplementation" in __pypy__.internal_repr(obj) + return impl_used + """) + + + def test_check_module_uses_module_dict(self): + m = type(__builtins__)("abc") + self.impl_used(m.__dict__) + + def test_key_not_there(self): + d = type(__builtins__)("abc").__dict__ + raises(KeyError, "d['def']") + + class TestW_DictSmall(test_dictobject.TestW_DictObject): def setup_class(cls): @@ -233,3 +254,15 @@ def get_impl(self): return self.ImplementionClass(self.space, self.string, self.string2) + +class TestModuleDictImplementation(TestRDictImplementation): + ImplementionClass = ModuleDictImplementation + EmptyClass = ModuleDictImplementation + +class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation): + ImplementionClass = ModuleDictImplementation + EmptyClass = ModuleDictImplementation + + string = "int" + string2 = "isinstance" + Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py Mon Mar 9 19:02:50 2009 @@ -489,6 +489,7 @@ FakeSpace.config.objspace.std.withdictmeasurement = False FakeSpace.config.objspace.std.withsharingdict = False FakeSpace.config.objspace.std.withsmalldicts = False +FakeSpace.config.objspace.std.withcelldict = False FakeSpace.config.objspace.opcodes = Config() FakeSpace.config.objspace.opcodes.CALL_LIKELY_BUILTIN = False From arigo at codespeak.net Mon Mar 9 19:05:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Mar 2009 19:05:26 +0100 (CET) Subject: [pypy-svn] r62774 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309180526.AC0F1169EC8@codespeak.net> Author: arigo Date: Mon Mar 9 19:05:26 2009 New Revision: 62774 Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py pypy/trunk/pypy/jit/metainterp/pyjitpl.py Log: Redo this optimization. Fijal, feel free to revert again if I didn't fix the problem. Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/codewriter.py (original) +++ pypy/trunk/pypy/jit/metainterp/codewriter.py Mon Mar 9 19:05:26 2009 @@ -17,8 +17,10 @@ class JitCode(history.AbstractValue): - def __init__(self, name): + def __init__(self, name, cfnptr=None, calldescr=0): self.name = name + self.cfnptr = cfnptr + self.calldescr = calldescr def setup(self, code, constants): self.code = code @@ -68,6 +70,7 @@ class CodeWriter(object): + portal_graph = None def __init__(self, metainterp, policy): self.all_prebuilt_values = {} @@ -82,6 +85,7 @@ def make_portal_bytecode(self, graph): log.info("making JitCodes...") + self.portal_graph = graph jitcode = self.make_one_bytecode(graph, True) while self.unfinished_graphs: graph = self.unfinished_graphs.pop() @@ -100,11 +104,22 @@ def get_jitcode(self, graph): if graph in self.all_graphs: return self.all_graphs[graph] - bytecode = JitCode(graph.name) # 'graph.name' is for dump() + extra = self.get_jitcode_calldescr(graph) + bytecode = JitCode(graph.name, *extra) # 'graph.name' is for dump() self.all_graphs[graph] = bytecode self.unfinished_graphs.append(graph) return bytecode + def get_jitcode_calldescr(self, graph): + if self.portal_graph is None or graph is self.portal_graph: + return () + fnptr = self.rtyper.getcallable(graph) + cfnptr = history.ConstAddr(llmemory.cast_ptr_to_adr(fnptr), self.cpu) + FUNC = lltype.typeOf(fnptr).TO + NON_VOID_ARGS = [ARG for ARG in FUNC.ARGS if ARG is not lltype.Void] + calldescr = self.cpu.calldescrof(NON_VOID_ARGS, FUNC.RESULT) + return (cfnptr, calldescr) + def get_indirectcallset(self, graphs): key = tuple(sorted(graphs)) try: Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py Mon Mar 9 19:05:26 2009 @@ -396,9 +396,18 @@ @arguments("bytecode", "varargs") def opimpl_call(self, callee, varargs): - f = self.metainterp.newframe(callee) - f.setup_call(varargs) - return True + if (isinstance(self.metainterp.history, history.BlackHole) and + callee.cfnptr is not None): + # when producing only a BlackHole, we can implement this by + # calling the subfunction directly instead of interpreting it + varargs = [callee.cfnptr] + varargs + return self.execute_with_exc(rop.CALL, varargs, + descr=callee.calldescr) + else: + # when tracing, this bytecode causes the subfunction to be entered + f = self.metainterp.newframe(callee) + f.setup_call(varargs) + return True @arguments("int", "varargs") def opimpl_residual_call(self, calldescr, varargs): From fijal at codespeak.net Mon Mar 9 19:19:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 19:19:53 +0100 (CET) Subject: [pypy-svn] r62775 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309181953.D9E40169EBB@codespeak.net> Author: fijal Date: Mon Mar 9 19:19:51 2009 New Revision: 62775 Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py Log: actually this is the right order... Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/warmspot.py (original) +++ pypy/trunk/pypy/jit/metainterp/warmspot.py Mon Mar 9 19:19:51 2009 @@ -306,7 +306,7 @@ return unwrap(RESULT, e.resultbox) except ExitFrameWithException, e: value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) - if we_are_translated(): + if not we_are_translated(): type = e.typebox.getaddr(self.metainterp.cpu) type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) raise LLException(type, value) From fijal at codespeak.net Mon Mar 9 19:20:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 19:20:21 +0100 (CET) Subject: [pypy-svn] r62776 - in pypy/trunk/pypy: rpython/lltypesystem translator Message-ID: <20090309182021.5B774169ECB@codespeak.net> Author: fijal Date: Mon Mar 9 19:20:20 2009 New Revision: 62776 Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py pypy/trunk/pypy/translator/exceptiontransform.py Log: good, revert my hacks Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lloperation.py Mon Mar 9 19:20:20 2009 @@ -397,7 +397,6 @@ 'promote_virtualizable':LLOp(canrun=True), 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), - 'raise_exc_value' : LLOp(canraise=(Exception,)), # __________ GC operations __________ Modified: pypy/trunk/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/trunk/pypy/translator/exceptiontransform.py (original) +++ pypy/trunk/pypy/translator/exceptiontransform.py Mon Mar 9 19:20:20 2009 @@ -208,12 +208,6 @@ elif opname == 'get_exc_value_addr': # only for lltype block.operations[i].opname = "direct_call" block.operations[i].args.insert(0, self.rpyexc_get_exc_value_addr_ptr) - elif opname == 'raise_exc_value': - block.operations[i].opname = 'direct_call' - block.operations[i].args.insert(0, self.rpyexc_raise_ptr) - del block.operations[i + 1:] - l = Link([error_constant(graph.returnblock.inputargs[0].concretetype)], graph.returnblock) - block.recloseblock(l) def transform_block(self, graph, block): need_exc_matching = False From fijal at codespeak.net Mon Mar 9 19:20:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 19:20:36 +0100 (CET) Subject: [pypy-svn] r62777 - pypy/trunk/pypy/jit/metainterp Message-ID: <20090309182036.0FB6D169ECC@codespeak.net> Author: fijal Date: Mon Mar 9 19:20:35 2009 New Revision: 62777 Modified: pypy/trunk/pypy/jit/metainterp/support.py Log: kill kill kill Modified: pypy/trunk/pypy/jit/metainterp/support.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/support.py (original) +++ pypy/trunk/pypy/jit/metainterp/support.py Mon Mar 9 19:20:35 2009 @@ -222,20 +222,3 @@ rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT - -def raise_exc_value(tp, value): - from pypy.rpython.llinterp import LLException - raise LLException(tp, value) - -class Entry(ExtRegistryEntry): - _about_ = raise_exc_value - - def compute_result_annotation(self, s_tp, s_value): - return annmodel.s_ImpossibleValue - - def specialize_call(self, hop): - v_list = [hop.inputarg(hop.args_r[0], arg=0), - hop.inputarg(hop.args_r[1], arg=1)] - hop.has_implicit_exception(Exception) - hop.exception_is_here() - return hop.genop('raise_exc_value', v_list) From fijal at codespeak.net Mon Mar 9 19:23:59 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 19:23:59 +0100 (CET) Subject: [pypy-svn] r62778 - pypy/trunk/pypy/jit/tl Message-ID: <20090309182359.523FD169EBF@codespeak.net> Author: fijal Date: Mon Mar 9 19:23:58 2009 New Revision: 62778 Modified: pypy/trunk/pypy/jit/tl/pypyjit_demo.py Log: yet another working function Modified: pypy/trunk/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/trunk/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/trunk/pypy/jit/tl/pypyjit_demo.py Mon Mar 9 19:23:58 2009 @@ -27,4 +27,16 @@ print s assert s == 4950 +def f(): + try: + i = 100 + while i > 0: + if i == 10: + raise IndexError + i -= 1 + except IndexError: + pass + else: + raise AssertionError + f() From fijal at codespeak.net Mon Mar 9 22:54:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Mar 2009 22:54:28 +0100 (CET) Subject: [pypy-svn] r62780 - pypy/branch/pyjitpl5 Message-ID: <20090309215428.77A13169EC7@codespeak.net> Author: fijal Date: Mon Mar 9 22:54:26 2009 New Revision: 62780 Added: pypy/branch/pyjitpl5/ - copied from r62779, pypy/trunk/ Log: branch again to do even more experiments From afa at codespeak.net Tue Mar 10 00:38:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 00:38:10 +0100 (CET) Subject: [pypy-svn] r62783 - pypy/trunk/pypy/module/bz2 Message-ID: <20090309233810.2CEB1169EFC@codespeak.net> Author: afa Date: Tue Mar 10 00:38:07 2009 New Revision: 62783 Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py Log: CPython on Windows comes with a "bz2.lib" file which is NOT a bz2 library, but the import library of the bz2.pyd extension module; it contains only the init_bz2 function! TODO: really handle external libraries on Windows. Meanwhile, we check and skip the library if it does not match. Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/trunk/pypy/module/bz2/interp_bz2.py (original) +++ pypy/trunk/pypy/module/bz2/interp_bz2.py Tue Mar 10 00:38:07 2009 @@ -18,6 +18,8 @@ ) calling_conv = 'c' + CHECK_LIBRARY = platform.Has('dump("x", (int)&BZ2_bzCompress)') + off_t = platform.SimpleType("off_t", rffi.LONGLONG) size_t = platform.SimpleType("size_t", rffi.ULONG) BUFSIZ = platform.ConstantInteger("BUFSIZ") @@ -56,6 +58,8 @@ pass for k, v in platform.configure(CConfig).items(): setattr(cConfig, k, v) +if not cConfig.CHECK_LIBRARY: + raise ImportError("Invalid bz2 library") for name in constant_names: value = getattr(cConfig, name) From fijal at codespeak.net Tue Mar 10 00:44:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 00:44:19 +0100 (CET) Subject: [pypy-svn] r62784 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/x86 backend/x86/test metainterp metainterp/test Message-ID: <20090309234419.CC859168407@codespeak.net> Author: fijal Date: Tue Mar 10 00:44:18 2009 New Revision: 62784 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: break everything. descr is again AbstractValue instead of int. The main reason is that I want to be able to translated JIT without actually using ll2ctypes (which has bugs). Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Tue Mar 10 00:44:18 2009 @@ -520,43 +520,45 @@ # delegating to the builtins do_xxx() (done automatically for simple cases) def op_getarrayitem_gc(self, arraydescr, array, index): - if arraydescr & 1: + if arraydescr.getint() & 1: return do_getarrayitem_gc_ptr(array, index) else: return do_getarrayitem_gc_int(array, index, self.memocast) def op_getfield_gc(self, fielddescr, struct): + fielddescr = fielddescr.getint() if fielddescr & 1: return do_getfield_gc_ptr(struct, fielddescr) else: return do_getfield_gc_int(struct, fielddescr, self.memocast) def op_getfield_raw(self, fielddescr, struct): - if fielddescr & 1: + if fielddescr.getint() & 1: return do_getfield_raw_ptr(struct, fielddescr) else: return do_getfield_raw_int(struct, fielddescr, self.memocast) def op_new_with_vtable(self, size, vtable): - result = do_new(size) + result = do_new(size.getint()) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): - if arraydescr & 1: + if arraydescr.getint() & 1: do_setarrayitem_gc_ptr(array, index, newvalue) else: do_setarrayitem_gc_int(array, index, newvalue, self.memocast) def op_setfield_gc(self, fielddescr, struct, newvalue): + fielddescr = fielddescr.getint() if fielddescr & 1: do_setfield_gc_ptr(struct, fielddescr, newvalue) else: do_setfield_gc_int(struct, fielddescr, newvalue, self.memocast) def op_setfield_raw(self, fielddescr, struct, newvalue): - if fielddescr & 1: + if fielddescr.getint() & 1: do_setfield_raw_ptr(struct, fielddescr, newvalue) else: do_setfield_raw_int(struct, fielddescr, newvalue, self.memocast) @@ -565,12 +567,15 @@ _call_args[:] = args if calldescr == sys.maxint: err_result = None - elif calldescr & 1: + elif calldescr.getint() & 1: err_result = lltype.nullptr(llmemory.GCREF.TO) else: err_result = 0 return _do_call_common(func, self.memocast, err_result) + def op_new_array(self, arraydescr, count): + return do_new_array(arraydescr.getint(), count) + # ____________________________________________________________ def cast_to_int(x, memocast): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Tue Mar 10 00:44:18 2009 @@ -186,7 +186,7 @@ @staticmethod def sizeof(S): - return symbolic.get_size(S) + return history.ConstInt(symbolic.get_size(S)) @staticmethod def numof(S): @@ -202,7 +202,7 @@ bit = 1 else: bit = 0 - return ofs*2 + bit + return history.ConstInt(ofs*2 + bit) @staticmethod def arraydescrof(A): @@ -213,7 +213,7 @@ bit = 1 else: bit = 0 - return size*2 + bit + return history.ConstInt(size*2 + bit) @staticmethod def calldescrof(ARGS, RESULT): @@ -227,6 +227,7 @@ @staticmethod def typefor(fielddesc): + fielddesc = fielddesc.getint() if fielddesc == sys.maxint: return 'void' if fielddesc % 2: @@ -249,6 +250,12 @@ def cast_int_to_adr(self, int): return llimpl.cast_int_to_adr(self.memo_cast, int) + def ofs_from_descr(self, descr): + return descr.getint() + + def repack_descr(self, ofs): + return history.ConstInt(ofs) + # ---------- the backend-dependent operations ---------- def do_arraylen_gc(self, args, arraydescr): @@ -273,9 +280,10 @@ return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, self.memo_cast)) - def do_getfield_gc(self, args, fielddescr): + def do_getfield_gc(self, args, fieldbox): + fielddescr = fieldbox.getint() struct = args[0].getptr_base() - if self.typefor(fielddescr) == 'ptr': + if self.typefor(fieldbox) == 'ptr': return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, fielddescr)) else: @@ -294,18 +302,18 @@ self.memo_cast)) def do_new(self, args, size): - return history.BoxPtr(llimpl.do_new(size)) + return history.BoxPtr(llimpl.do_new(size.getint())) def do_new_with_vtable(self, args, size): vtable = args[0].getint() - result = llimpl.do_new(size) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable, vtable, - self.memo_cast) + result = llimpl.do_new(size.getint()) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.getint(), + vtable, self.memo_cast) return history.BoxPtr(result) def do_new_array(self, args, size): count = args[0].getint() - return history.BoxPtr(llimpl.do_new_array(size, count)) + return history.BoxPtr(llimpl.do_new_array(size.getint(), count)) def do_setarrayitem_gc(self, args, arraydescr): array = args[0].getptr_base() @@ -318,9 +326,10 @@ llimpl.do_setarrayitem_gc_int(array, index, newvalue, self.memo_cast) - def do_setfield_gc(self, args, fielddescr): + def do_setfield_gc(self, args, fieldbox): + fielddescr = fieldbox.getint() struct = args[0].getptr_base() - if self.typefor(fielddescr) == 'ptr': + if self.typefor(fieldbox) == 'ptr': newvalue = args[1].getptr_base() llimpl.do_setfield_gc_ptr(struct, fielddescr, newvalue) else: @@ -329,6 +338,7 @@ self.memo_cast) def do_setfield_raw(self, args, fielddescr): + fielddescr = fielddescr.getint() struct = self.cast_int_to_adr(args[0].getint()) if self.typefor(fielddescr) == 'ptr': newvalue = args[1].getptr_base() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Tue Mar 10 00:44:18 2009 @@ -68,7 +68,7 @@ self.make_sure_mc_exists() op0 = operations[0] op0.position = self.mc.tell() - regalloc = RegAlloc(operations, guard_op) + regalloc = RegAlloc(operations, guard_op, self.cpu.translate_support_code) if not we_are_translated(): self._regalloc = regalloc # for debugging computed_ops = regalloc.computed_ops @@ -405,7 +405,8 @@ def genop_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.cpu.translate_support_code) self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize), lower_byte(val_loc)) @@ -413,7 +414,8 @@ def genop_strlen(self, op, arglocs, resloc): base_loc = arglocs[0] - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.cpu.translate_support_code) self.mc.MOV(resloc, addr_add_const(base_loc, ofs_length)) def genop_arraylen_gc(self, op, arglocs, resloc): @@ -422,7 +424,8 @@ def genop_strgetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.cpu.translate_support_code) self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize)) def genop_merge_point(self, op, locs): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Tue Mar 10 00:44:18 2009 @@ -99,8 +99,9 @@ raise ValueError("convert_to_imm: got a %s" % c) class RegAlloc(object): - def __init__(self, operations, guard_op=None): + def __init__(self, operations, guard_op=None, translate_support_code=False): # variables that have place in register + self.translate_support_code = translate_support_code self.reg_bindings = newcheckdict() self.stack_bindings = {} # compute longevity of variables @@ -731,16 +732,14 @@ consider_call_pure = consider_call def consider_new(self, op, ignored): - return self._call(op, [imm(op.descr)]) + return self._call(op, [imm(op.descr.getint())]) def consider_new_with_vtable(self, op, ignored): - return self._call(op, [imm(op.descr), self.loc(op.args[0])]) + return self._call(op, [imm(op.descr.getint()), self.loc(op.args[0])]) def consider_newstr(self, op, ignored): - ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] - ofs_items = symbolic.get_field_token(rstr.STR.chars, 'items')[0] - ofs_length = symbolic.get_field_token(rstr.STR.chars, 'length')[0] - return self._malloc_varsize(ofs, ofs_items, ofs_length, 0, op.args[0], + ofs_items, _, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code) + return self._malloc_varsize(0, ofs_items, ofs, 0, op.args[0], op.result) def _malloc_varsize(self, ofs, ofs_items, ofs_length, size, v, res_v): @@ -768,7 +767,7 @@ return res def consider_new_array(self, op, ignored): - size_of_field, basesize = self._unpack_arraydescr(op.descr) + size_of_field, basesize, _ = self._unpack_arraydescr(op.descr) return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[0], op.result) @@ -805,7 +804,7 @@ [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) def consider_setarrayitem_gc(self, op, ignored): - scale, ofs = self._unpack_arraydescr(op.descr) + scale, ofs, _ = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) @@ -825,7 +824,7 @@ consider_getfield_gc_pure = consider_getfield_gc def consider_getarrayitem_gc(self, op, ignored): - scale, ofs = self._unpack_arraydescr(op.descr) + scale, ofs, _ = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars(op.args) @@ -891,7 +890,7 @@ return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] def consider_arraylen_gc(self, op, ignored): - _, ofs = self._unpack_arraydescr(op.descr) + _, ofs, _ = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Tue Mar 10 00:44:18 2009 @@ -4,11 +4,11 @@ from pypy.rpython.lltypesystem import lltype, llmemory, ll2ctypes, rffi, rstr from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize +from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize, Symbolic from pypy.rlib.objectmodel import we_are_translated, keepalive_until_here from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import rclass -from pypy.jit.metainterp import history +from pypy.jit.metainterp import history, codewriter from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN @@ -23,6 +23,32 @@ PTR = 1 INT = 2 +class ConstDescr3(Const): + def __init__(self, v): + self.v = v + + def _v(self): + l = [] + for i in self.v: + if isinstance(i, Symbolic): + l.append(id(i)) + else: + l.append(i) + return tuple(l) + + + def __hash__(self): + return hash(self._v()) + + def __eq__(self, other): + return self.__class__ is other.__class__ and self._v() == other._v() + + def __ne__(self, other): + return not self == other + + def _getrepr_(self): + return repr(self.v) + class CPU386(object): debug = True @@ -383,7 +409,7 @@ frame[mp.stacklocs[argindex]] = self.convert_box_to_int(valuebox) def sizeof(self, S): - return symbolic.get_size(S) + return ConstInt(symbolic.get_size(S, self.translate_support_code)) numof = sizeof # addresssuffix = str(symbolic.get_size(llmemory.Address)) @@ -405,11 +431,7 @@ def do_getarrayitem_gc(self, args, arraydescr): field = args[1].getint() gcref = args[0].getptr(llmemory.GCREF) - if arraydescr < 0: - ptr = True - else: - ptr = False - shift, ofs = self.unpack_arraydescr(arraydescr) + shift, ofs, ptr = self.unpack_arraydescr(arraydescr) size = 1 << shift if size == 1: return BoxInt(ord(rffi.cast(rffi.CArrayPtr(lltype.Char), gcref) @@ -427,11 +449,7 @@ def do_setarrayitem_gc(self, args, arraydescr): field = args[1].getint() gcref = args[0].getptr(llmemory.GCREF) - if arraydescr < 0: - ptr = True - else: - ptr = False - shift, ofs = self.unpack_arraydescr(arraydescr) + shift, ofs, ptr = self.unpack_arraydescr(arraydescr) size = 1 << shift if size == 1: v = args[2].getint() @@ -447,13 +465,15 @@ raise NotImplementedError("size = %d" % size) def do_strlen(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) gcref = args[0].getptr(llmemory.GCREF) v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] return BoxInt(v) def do_strgetitem(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) gcref = args[0].getptr(llmemory.GCREF) i = args[1].getint() v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] @@ -509,16 +529,16 @@ self._base_do_setfield(fielddescr, args[0].getint(), args[1]) def do_new(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize) + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.getint()) return BoxPtr(self.cast_int_to_gcref(res)) def do_new_with_vtable(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize) + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.getint()) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[0].getint() return BoxPtr(self.cast_int_to_gcref(res)) def do_new_array(self, args, arraydescr): - size_of_field, ofs = self.unpack_arraydescr(arraydescr) + size_of_field, ofs, ptr = self.unpack_arraydescr(arraydescr) num_elem = args[0].getint() size = ofs + (1 << size_of_field) * num_elem res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) @@ -526,7 +546,8 @@ return BoxPtr(self.cast_int_to_gcref(res)) def do_newstr(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) assert itemsize == 1 num_elem = args[0].getint() size = basesize + num_elem @@ -535,7 +556,8 @@ return BoxPtr(self.cast_int_to_gcref(res)) def do_strsetitem(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) index = args[1].getint() v = args[2].getint() a = args[0].getptr(llmemory.GCREF) @@ -565,73 +587,80 @@ adr = llmemory.cast_ptr_to_adr(x) return CPU386.cast_adr_to_int(adr) - @staticmethod - def arraydescrof(A): + def arraydescrof(self, A): assert isinstance(A, lltype.GcArray) - basesize, itemsize, ofs_length = symbolic.get_array_token(A) + basesize, itemsize, ofs_length = symbolic.get_array_token(A, + self.translate_support_code) assert ofs_length == 0 - counter = 0 - while itemsize != 1: - itemsize >>= 1 - counter += 1 - res = basesize + counter * 0x10000 if isinstance(A.OF, lltype.Ptr): - res = ~res + ptr = True + else: + ptr = False + return ConstDescr3((basesize, itemsize, ptr)) + + def ofs_from_descr(self, descr): + assert isinstance(descr, ConstDescr3) + x = (descr.v[0] << 16) + descr.v[1] + if descr.v[2]: + return ~x + return x + + def repack_descr(self, ofs): + orig_ofs = ofs + if ofs < 0: + ptr = True + ofs = ~ofs + else: + ptr = False + res = ConstDescr3((ofs>>16, ofs & 0xffff, ptr)) + assert self.ofs_from_descr(res) == orig_ofs return res @staticmethod def unpack_arraydescr(arraydescr): - # XXX move it to some saner place, regalloc is using it - if arraydescr < 0: - arraydescr = ~arraydescr - assert arraydescr - size_of_field = arraydescr >> 16 - ofs = arraydescr & 0xffff - return size_of_field, ofs + assert isinstance(arraydescr, ConstDescr3) + basesize, itemsize, ptr = arraydescr.v + counter = 0 + while itemsize != 1: + itemsize >>= 1 + counter += 1 + return counter, basesize, ptr - @staticmethod - def calldescrof(argtypes, resulttype): + def calldescrof(self, argtypes, resulttype): if resulttype is lltype.Void: size = 0 else: - size = symbolic.get_size(resulttype) - res = (len(argtypes) << 4) + size + size = symbolic.get_size(resulttype, self.translate_support_code) if isinstance(resulttype, lltype.Ptr): - return ~res - return res - - @staticmethod - def unpack_calldescr(calldescr): - if calldescr < 0: - calldescr = ~calldescr ptr = True else: ptr = False - return calldescr >> 4, calldescr & 0xf, ptr + return ConstDescr3((len(argtypes), size, ptr)) @staticmethod - def fielddescrof(S, fieldname): - ofs, size = symbolic.get_field_token(S, fieldname) - val = (size << 16) + ofs + def unpack_calldescr(calldescr): + assert isinstance(calldescr, ConstDescr3) + return calldescr.v + + def fielddescrof(self, S, fieldname): + ofs, size = symbolic.get_field_token(S, fieldname, + self.translate_support_code) if (isinstance(getattr(S, fieldname), lltype.Ptr) and getattr(S, fieldname).TO._gckind == 'gc'): - return ~val - return val + ptr = True + else: + ptr = False + return ConstDescr3((ofs, size, ptr)) @staticmethod def unpack_fielddescr(fielddescr): - ptr = False - if fielddescr < 0: - fielddescr = ~fielddescr - ptr = True - ofs = fielddescr & 0xffff - size = fielddescr >> 16 - return ofs, size, ptr + assert isinstance(fielddescr, ConstDescr3) + return fielddescr.v @staticmethod def typefor(fielddesc): - if fielddesc < 0: - return "ptr" + if fieldesc[2]: + return 'ptr' return "int" @staticmethod Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py Tue Mar 10 00:44:18 2009 @@ -1,34 +1,50 @@ import ctypes -from pypy.rpython.lltypesystem import lltype, ll2ctypes +from pypy.rpython.lltypesystem import lltype, ll2ctypes, llmemory from pypy.rlib.objectmodel import specialize @specialize.memo() -def get_field_token(STRUCT, fieldname): +def get_field_token(STRUCT, fieldname, translate_support_code): + if translate_support_code: + return (llmemory.offsetof(STRUCT, fieldname), + get_size(STRUCT, True)) cstruct = ll2ctypes.get_ctypes_type(STRUCT) cfield = getattr(cstruct, fieldname) return (cfield.offset, cfield.size) @specialize.memo() -def get_size(TYPE): +def get_size(TYPE, translate_support_code): + if translate_support_code: + if TYPE._is_varsize(): + return llmemory.sizeof(TYPE, 0) + return llmemory.sizeof(TYPE) ctype = ll2ctypes.get_ctypes_type(TYPE) return ctypes.sizeof(ctype) @specialize.memo() -def get_array_token(T): +def get_array_token(T, translate_support_code): # T can be an array or a var-sized structure - if isinstance(T, lltype.Struct): - assert T._arrayfld is not None, "%r is not variable-sized" % (T,) - cstruct = ll2ctypes.get_ctypes_type(T) - cfield = getattr(cstruct, T._arrayfld) - before_array_part = cfield.offset - T = getattr(T, T._arrayfld) + if translate_support_code: + basesize = llmemory.sizeof(T, 0) + if isinstance(T, lltype.Struct): + itemsize = llmemory.sizeof(getattr(T, T._arrayfld).OF) + ofs_length = llmemory.offsetof(T, T._arrayfld) + else: + itemsize = llmemory.sizeof(T.OF) + ofs_length = 0 else: - before_array_part = 0 - carray = ll2ctypes.get_ctypes_type(T) - assert carray.length.size == 4 - ofs_length = before_array_part + carray.length.offset - basesize = before_array_part + carray.items.offset - carrayitem = ll2ctypes.get_ctypes_type(T.OF) - itemsize = ctypes.sizeof(carrayitem) + if isinstance(T, lltype.Struct): + assert T._arrayfld is not None, "%r is not variable-sized" % (T,) + cstruct = ll2ctypes.get_ctypes_type(T) + cfield = getattr(cstruct, T._arrayfld) + before_array_part = cfield.offset + T = getattr(T, T._arrayfld) + else: + before_array_part = 0 + carray = ll2ctypes.get_ctypes_type(T) + assert carray.length.size == 4 + ofs_length = before_array_part + carray.length.offset + basesize = before_array_part + carray.items.offset + carrayitem = ll2ctypes.get_ctypes_type(T.OF) + itemsize = ctypes.sizeof(carrayitem) return basesize, itemsize, ofs_length Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Tue Mar 10 00:44:18 2009 @@ -204,6 +204,7 @@ (rop.INT_FLOORDIV, [ConstInt(42), BoxInt(10)], 4), (rop.INT_RSHIFT, [ConstInt(3), BoxInt(4)], 3>>4), (rop.INT_RSHIFT, [BoxInt(3), ConstInt(10)], 3>>10), + #(rop.INT_LSHIFT, [BoxInt(3), BoxInt(1)], 3<<1), ]: assert self.execute_operation(op, args, 'int').value == res @@ -235,7 +236,7 @@ try: saved_addr = self.cpu.assembler.malloc_func_addr self.cpu.assembler.malloc_func_addr = addr - ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] + ofs = symbolic.get_field_token(rstr.STR, 'chars', False)[0] res = self.execute_operation(rop.NEWSTR, [ConstInt(7)], 'ptr') assert allocs[0] == 7 + ofs + WORD @@ -252,7 +253,7 @@ # ------------------------------------------------------------ TP = lltype.GcArray(lltype.Signed) - ofs = symbolic.get_field_token(TP, 'length')[0] + ofs = symbolic.get_field_token(TP, 'length', False)[0] descr = self.cpu.arraydescrof(TP) res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)], @@ -274,8 +275,8 @@ def test_stringitems(self): from pypy.rpython.lltypesystem.rstr import STR - ofs = symbolic.get_field_token(STR, 'chars')[0] - ofs_items = symbolic.get_field_token(STR.chars, 'items')[0] + ofs = symbolic.get_field_token(STR, 'chars', False)[0] + ofs_items = symbolic.get_field_token(STR.chars, 'items', False)[0] res = self.execute_operation(rop.NEWSTR, [ConstInt(10)], 'ptr') self.execute_operation(rop.STRSETITEM, [res, ConstInt(2), ConstInt(ord('d'))], 'void') @@ -288,8 +289,8 @@ def test_arrayitems(self): TP = lltype.GcArray(lltype.Signed) - ofs = symbolic.get_field_token(TP, 'length')[0] - itemsofs = symbolic.get_field_token(TP, 'items')[0] + ofs = symbolic.get_field_token(TP, 'length', False)[0] + itemsofs = symbolic.get_field_token(TP, 'items', False)[0] descr = self.cpu.arraydescrof(TP) res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)], 'ptr', descr) @@ -540,3 +541,4 @@ # XXX cannot work without rtyper #s = execute(cpu, rop.INT_MUL_OVF, [BoxInt(sys.maxint/2), BoxInt(10)]) #assert cpu.get_exception() + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Tue Mar 10 00:44:18 2009 @@ -1,3 +1,5 @@ +import py +py.test.skip("update me") from pypy.jit.backend.x86.symbolic import * from pypy.jit.backend.x86.runner import CPU386 from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 10 00:44:18 2009 @@ -17,7 +17,7 @@ class JitCode(history.AbstractValue): - def __init__(self, name, cfnptr=None, calldescr=0): + def __init__(self, name, cfnptr=None, calldescr=None): self.name = name self.cfnptr = cfnptr self.calldescr = calldescr @@ -34,7 +34,6 @@ dump.dump_bytecode(self, file=file) print >> file - class IndirectCallset(history.AbstractValue): def __init__(self, codewriter, graphs): keys = [] @@ -226,12 +225,15 @@ self.bytecode.dump() else: print repr(self.bytecode) + self.bytecode.dump(open("/tmp/jitcodes/%s" % self.bytecode.name, "w")) def const_position(self, constvalue): """Generate a constant of the given value. Returns its index in the list self.positions[]. """ if constvalue is _we_are_jitted: constvalue = True + if isinstance(constvalue, history.Const): + return self.get_position(constvalue) const = Const._new(constvalue, self.cpu) return self.get_position(const) @@ -525,10 +527,10 @@ # store the vtable as an address -- that's fine, because the # GC doesn't need to follow them self.emit('new_with_vtable', - self.cpu.sizeof(STRUCT), + self.const_position(self.cpu.sizeof(STRUCT)), self.const_position(vtable)) else: - self.emit('new', self.cpu.sizeof(STRUCT)) + self.emit('new', self.const_position(self.cpu.sizeof(STRUCT))) self.register_var(op.result) def serialize_op_malloc_varsize(self, op): @@ -540,7 +542,7 @@ ARRAY = op.args[0].value arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('new_array') - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(op.args[2])) self.register_var(op.result) @@ -567,7 +569,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(offset) + self.emit(self.const_position(offset)) self.register_var(op.result) #self._eventualy_builtin(op.result) @@ -585,7 +587,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(offset) + self.emit(self.const_position(offset)) self.emit(self.var_position(v_value)) def is_typeptr_getset(self, op): @@ -604,7 +606,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('getarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(op.args[1])) self.register_var(op.result) @@ -614,7 +616,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('setarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(op.args[1])) self.emit(self.var_position(op.args[2])) @@ -699,7 +701,7 @@ op.args[1:], op.result) self.emit('residual_call') - self.emit(calldescr) + self.emit(self.const_position(calldescr)) self.emit_varargs([op.args[0]] + non_void_args) self.register_var(op.result) @@ -747,7 +749,7 @@ calldescr, non_void_args = self.codewriter.getcalldescr(c_func, args, op.result) self.emit(opname) - self.emit(calldescr) + self.emit(self.const_position(calldescr)) self.emit_varargs([c_func] + non_void_args) self.register_var(op.result) @@ -771,7 +773,7 @@ v_default.value != TP.TO.OF._defl()): return False # variable or non-null initial value self.emit('new_array') - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(args[0])) self.register_var(op.result) return True @@ -790,7 +792,7 @@ return False self.emit('setarrayitem_gc') self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(index)) self.emit(self.var_position(args[2])) self.register_var(op.result) @@ -800,7 +802,7 @@ oopspec_name == 'list.len_foldable'): self.emit('arraylen_gc') self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.register_var(op.result) return True # @@ -812,7 +814,7 @@ return False self.emit(opname) self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(index)) self.register_var(op.result) return True @@ -837,7 +839,7 @@ else: self.emit('check_neg_index') self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(args[1])) v_posindex = Variable('posindex') v_posindex.concretetype = lltype.Signed @@ -879,7 +881,7 @@ self.emit('guard_nonvirtualized') self.emit(self.var_position(op.args[0])) self.emit(self.get_position(virtualizabledesc)) - self.emit(guard_field) + self.emit(self.const_position(guard_field)) # ---------- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Tue Mar 10 00:44:18 2009 @@ -13,34 +13,34 @@ # ____________________________________________________________ -def do_int_add(cpu, args, descr=0): +def do_int_add(cpu, args, descr=None): return ConstInt(args[0].getint() + args[1].getint()) -def do_int_sub(cpu, args, descr=0): +def do_int_sub(cpu, args, descr=None): return ConstInt(args[0].getint() - args[1].getint()) -def do_int_mul(cpu, args, descr=0): +def do_int_mul(cpu, args, descr=None): return ConstInt(args[0].getint() * args[1].getint()) -def do_int_floordiv(cpu, args, descr=0): +def do_int_floordiv(cpu, args, descr=None): return ConstInt(args[0].getint() // args[1].getint()) -def do_int_mod(cpu, args, descr=0): +def do_int_mod(cpu, args, descr=None): return ConstInt(args[0].getint() % args[1].getint()) -def do_int_and(cpu, args, descr=0): +def do_int_and(cpu, args, descr=None): return ConstInt(args[0].getint() & args[1].getint()) -def do_int_or(cpu, args, descr=0): +def do_int_or(cpu, args, descr=None): return ConstInt(args[0].getint() | args[1].getint()) -def do_int_xor(cpu, args, descr=0): +def do_int_xor(cpu, args, descr=None): return ConstInt(args[0].getint() ^ args[1].getint()) -def do_int_rshift(cpu, args, descr=0): +def do_int_rshift(cpu, args, descr=None): return ConstInt(args[0].getint() >> args[1].getint()) -def do_int_lshift(cpu, args, descr=0): +def do_int_lshift(cpu, args, descr=None): return ConstInt(args[0].getint() << args[1].getint()) do_uint_add = do_int_add @@ -48,71 +48,71 @@ do_uint_mul = do_int_mul do_uint_lshift = do_int_lshift -def do_uint_rshift(cpu, args, descr=0): +def do_uint_rshift(cpu, args, descr=None): v = r_uint(args[0].getint()) >> r_uint(args[1].getint()) return ConstInt(intmask(v)) # ---------- -def do_int_lt(cpu, args, descr=0): +def do_int_lt(cpu, args, descr=None): return ConstInt(args[0].getint() < args[1].getint()) -def do_int_le(cpu, args, descr=0): +def do_int_le(cpu, args, descr=None): return ConstInt(args[0].getint() <= args[1].getint()) -def do_int_eq(cpu, args, descr=0): +def do_int_eq(cpu, args, descr=None): return ConstInt(args[0].getint() == args[1].getint()) -def do_int_ne(cpu, args, descr=0): +def do_int_ne(cpu, args, descr=None): return ConstInt(args[0].getint() != args[1].getint()) -def do_int_gt(cpu, args, descr=0): +def do_int_gt(cpu, args, descr=None): return ConstInt(args[0].getint() > args[1].getint()) -def do_int_ge(cpu, args, descr=0): +def do_int_ge(cpu, args, descr=None): return ConstInt(args[0].getint() >= args[1].getint()) -def do_uint_lt(cpu, args, descr=0): +def do_uint_lt(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) < r_uint(args[1].getint())) -def do_uint_le(cpu, args, descr=0): +def do_uint_le(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) <= r_uint(args[1].getint())) do_uint_eq = do_int_eq do_uint_ne = do_int_ne -def do_uint_gt(cpu, args, descr=0): +def do_uint_gt(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) > r_uint(args[1].getint())) -def do_uint_ge(cpu, args, descr=0): +def do_uint_ge(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) >= r_uint(args[1].getint())) # ---------- -def do_int_is_true(cpu, args, descr=0): +def do_int_is_true(cpu, args, descr=None): return ConstInt(bool(args[0].getint())) do_uint_is_true = do_int_is_true -def do_int_neg(cpu, args, descr=0): +def do_int_neg(cpu, args, descr=None): return ConstInt(-args[0].getint()) -def do_int_invert(cpu, args, descr=0): +def do_int_invert(cpu, args, descr=None): return ConstInt(~args[0].getint()) -def do_bool_not(cpu, args, descr=0): +def do_bool_not(cpu, args, descr=None): return ConstInt(not args[0].getint()) -def do_oononnull(cpu, args, descr=0): +def do_oononnull(cpu, args, descr=None): return ConstInt(bool(args[0].getptr_base())) -def do_ooisnull(cpu, args, descr=0): +def do_ooisnull(cpu, args, descr=None): return ConstInt(not args[0].getptr_base()) -def do_oois(cpu, args, descr=0): +def do_oois(cpu, args, descr=None): return ConstInt(args[0].getptr_base() == args[1].getptr_base()) -def do_ooisnot(cpu, args, descr=0): +def do_ooisnot(cpu, args, descr=None): return ConstInt(args[0].getptr_base() != args[1].getptr_base()) # ---------- @@ -136,7 +136,7 @@ # ---------- -def do_int_add_ovf(cpu, args, descr=0): +def do_int_add_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -146,7 +146,7 @@ z = 0 return BoxInt(z) -def do_int_sub_ovf(cpu, args, descr=0): +def do_int_sub_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -156,7 +156,7 @@ z = 0 return BoxInt(z) -def do_int_mul_ovf(cpu, args, descr=0): +def do_int_mul_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -166,7 +166,7 @@ z = 0 return BoxInt(z) -def do_int_neg_ovf(cpu, args, descr=0): +def do_int_neg_ovf(cpu, args, descr=None): x = args[0].getint() try: z = ovfcheck(-x) @@ -175,7 +175,7 @@ z = 0 return BoxInt(z) -def do_int_mod_ovf(cpu, args, descr=0): +def do_int_mod_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -213,7 +213,7 @@ return cpu._execute_list[opnum] get_execute_function._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, argboxes, descr=0): +def execute(cpu, opnum, argboxes, descr=None): func = get_execute_function(cpu, opnum) return func(cpu, argboxes, descr) execute._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Tue Mar 10 00:44:18 2009 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rlib.objectmodel import we_are_translated, r_dict, ComputedIntSymbolic +from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic from pypy.rlib.rarithmetic import intmask from pypy.tool.uid import uid from pypy.conftest import option @@ -109,13 +109,23 @@ return 'Const(%s)' % self._getrepr_() def __eq__(self, other): - return self.__class__ is other.__class__ and self.value == other.value + if self.__class__ is not other.__class__: + return False + if isinstance(self.value, Symbolic): + v = id(self.value) + else: + v = self.value + if isinstance(other.value, Symbolic): + v2 = id(other.value) + else: + v2 = other.value + return v == v2 def __ne__(self, other): return not (self == other) def __hash__(self): - if isinstance(self.value, ComputedIntSymbolic): + if isinstance(self.value, Symbolic): return id(self.value) return self.get_() @@ -125,7 +135,7 @@ def __init__(self, value): if not we_are_translated(): - assert isinstance(value, (int, ComputedIntSymbolic)) + assert isinstance(value, (int, Symbolic)) self.value = value def clonebox(self): @@ -251,7 +261,7 @@ def __init__(self, value=0): if not we_are_translated(): - assert isinstance(value, (int, ComputedIntSymbolic)) + assert isinstance(value, (int, Symbolic)) self.value = value def clonebox(self): @@ -367,17 +377,17 @@ def __init__(self, cpu): self.cpu = cpu self.operations = [] - def record(self, opnum, argboxes, resbox, descr=0): + def record(self, opnum, argboxes, resbox, descr=None): raise NotImplementedError class History(RunningMatcher): - def record(self, opnum, argboxes, resbox, descr=0): + def record(self, opnum, argboxes, resbox, descr=None): op = ResOperation(opnum, argboxes, resbox, descr) self.operations.append(op) return op class BlackHole(RunningMatcher): - def record(self, opnum, argboxes, resbox, descr=0): + def record(self, opnum, argboxes, resbox, descr=None): return None def mp_eq(greenkey1, greenkey2): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Mar 10 00:44:18 2009 @@ -33,6 +33,11 @@ class CancelInefficientLoop(Exception): pass +def convert_vdesc(cpu, vdesc): + if vdesc: + return [cpu.ofs_from_descr(i) for i in vdesc.virtuals] + return [] + class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate @@ -142,7 +147,7 @@ node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - if self.vdesc and key not in self.vdesc.virtuals: + if self.vdesc is not None and key not in self.vdesc: esc_self = True else: esc_self = False @@ -151,7 +156,7 @@ # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: - if self.vdesc and key not in self.vdesc.virtuals: + if self.vdesc is not None and key not in self.vdesc: esc_self = True else: esc_self = False @@ -162,8 +167,8 @@ for ofs, node in self.origfields.items(): if ofs in other.curfields: node.add_to_dependency_graph(other.curfields[ofs], dep_graph) - if (self.virtualized and self.vdesc and - ofs in self.vdesc.virtuals): + if (self.virtualized and self.vdesc is not None and + ofs in self.vdesc): node.add_to_dependency_graph(other.origfields[ofs], dep_graph) def intersect(self, other, nodes): @@ -255,7 +260,7 @@ # This does "Perfect specialization" as per doc/jitpl5.txt. perfect_specializer = PerfectSpecializer(loop, options) - perfect_specializer.find_nodes() + perfect_specializer.find_nodes(cpu) perfect_specializer.intersect_input_and_output() for old_loop in old_loops: if perfect_specializer.match_exactly(old_loop): @@ -268,7 +273,7 @@ return old_loops[0] perfect_specializer = PerfectSpecializer(bridge, options) - perfect_specializer.find_nodes() + perfect_specializer.find_nodes(cpu) for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): perfect_specializer.adapt_for_match(old_loop.operations) @@ -339,7 +344,7 @@ ## instnode.cursize += 1 ## self.dependency_graph.append((instnode, fieldnode)) - def find_nodes(self): + def find_nodes(self, cpu): # Steps (1) and (2) self.first_escaping_op = True # only catch can have consts @@ -421,19 +426,19 @@ continue elif opnum == rop.SETFIELD_GC: instnode = self.getnode(op.args[0]) - field = op.descr + field = cpu.ofs_from_descr(op.descr) self.find_nodes_setfield(instnode, field, self.getnode(op.args[1])) continue elif opnum == rop.GETFIELD_GC: instnode = self.getnode(op.args[0]) - field = op.descr + field = cpu.ofs_from_descr(op.descr) box = op.result self.find_nodes_getfield(instnode, field, box) continue elif opnum == rop.GETFIELD_GC_PURE: instnode = self.getnode(op.args[0]) - field = op.descr + field = cpu.ofs_from_descr(op.descr) if not instnode.const: box = op.result self.find_nodes_getfield(instnode, field, box) @@ -532,7 +537,7 @@ instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) - instnode.vdesc = op.vdesc + instnode.vdesc = convert_vdesc(cpu, op.vdesc) continue elif op.is_always_pure(): for arg in op.args: @@ -593,14 +598,14 @@ specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes - def expanded_version_of(self, boxlist, oplist): + def expanded_version_of(self, boxlist, oplist, cpu): # oplist is None means at the start newboxlist = [] assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) + specnode.expand_boxlist(self.nodes[box], newboxlist, oplist, cpu) return newboxlist def optimize_guard(self, op, cpu): @@ -718,7 +723,7 @@ # self.ready_results[newoperations[-1].results[0]] = None opnum = op.opnum if opnum == rop.MERGE_POINT: - args = self.expanded_version_of(op.args, None) + args = self.expanded_version_of(op.args, None, cpu) op = ResOperation(rop.MERGE_POINT, args, None) newoperations.append(op) #for arg in op.args: @@ -728,11 +733,11 @@ # for arg in op.args: # self.ready_results[arg] = None elif opnum == rop.JUMP: - args = self.expanded_version_of(op.args, newoperations) + args = self.expanded_version_of(op.args, newoperations, cpu) for arg in args: if arg in self.nodes: assert not self.nodes[arg].virtual - self.cleanup_field_caches(newoperations) + self.cleanup_field_caches(newoperations, cpu) op = ResOperation(rop.JUMP, args, None) newoperations.append(op) continue @@ -792,14 +797,16 @@ continue elif opnum == rop.GETFIELD_GC: instnode = self.nodes[op.args[0]] - if self.optimize_getfield(instnode, op.descr, op.result): + ofs = cpu.ofs_from_descr(op.descr) + if self.optimize_getfield(instnode, ofs, op.result): continue # otherwise we need this getfield, but it does not # invalidate caches elif opnum == rop.GETFIELD_GC_PURE: instnode = self.nodes[op.args[0]] if not instnode.const: - if self.optimize_getfield(instnode, op.descr, op.result): + ofs = cpu.ofs_from_descr(op.descr) + if self.optimize_getfield(instnode, ofs, op.result): continue elif opnum == rop.GETARRAYITEM_GC: instnode = self.nodes[op.args[0]] @@ -880,7 +887,7 @@ elif opnum == rop.SETFIELD_GC: instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[1]] - ofs = op.descr + ofs = cpu.ofs_from_descr(op.descr) self.optimize_setfield(instnode, ofs, valuenode, op.args[1]) continue elif opnum == rop.SETARRAYITEM_GC: @@ -947,7 +954,7 @@ opnum != rop.SETARRAYITEM_GC): # the setfield operations do not clean up caches, although # they have side effects - self.cleanup_field_caches(newoperations) + self.cleanup_field_caches(newoperations, cpu) if op.can_raise(): exception_might_have_happened = True box = op.result @@ -959,7 +966,7 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations - def cleanup_field_caches(self, newoperations): + def cleanup_field_caches(self, newoperations, cpu): # we need to invalidate everything for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): @@ -972,8 +979,9 @@ [node.source, ConstInt(ofs), valuenode.source], None, ld.arraydescr)) else: + descr = cpu.repack_descr(ofs) newoperations.append(ResOperation(rop.SETFIELD_GC, - [node.source, valuenode.source], None, ofs)) + [node.source, valuenode.source], None, descr)) node.dirtyfields = {} node.cleanfields = {} @@ -1046,8 +1054,9 @@ box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) + descr = metainterp.cpu.repack_descr(ofs) metainterp.execute_and_record(rop.SETFIELD_GC, - [box, fieldbox], ofs) + [box, fieldbox], descr) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 10 00:44:18 2009 @@ -24,7 +24,7 @@ for arg in args: assert isinstance(arg, (Box, Const)) -LLDEBUG = False +LLDEBUG = True class arguments(object): def __init__(self, *argtypes, **kwargs): @@ -313,38 +313,38 @@ except KeyError: pass - @arguments("int") + @arguments("constbox") def opimpl_new(self, size): self.execute(rop.NEW, [], descr=size) - @arguments("int", "constbox") + @arguments("constbox", "constbox") def opimpl_new_with_vtable(self, size, vtablebox): self.execute(rop.NEW_WITH_VTABLE, [vtablebox], descr=size) - @arguments("int", "box") + @arguments("constbox", "box") def opimpl_new_array(self, itemsize, countbox): self.execute(rop.NEW_ARRAY, [countbox], descr=itemsize) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): self.execute(rop.GETARRAYITEM_GC, [arraybox, indexbox], descr=arraydesc) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): self.execute(rop.GETARRAYITEM_GC_PURE, [arraybox, indexbox], descr=arraydesc) - @arguments("box", "int", "box", "box") + @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): self.execute(rop.SETARRAYITEM_GC, [arraybox, indexbox, itembox], descr=arraydesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_arraylen_gc(self, arraybox, arraydesc): self.execute(rop.ARRAYLEN_GC, [arraybox], descr=arraydesc) - @arguments("orgpc", "box", "int", "box") + @arguments("orgpc", "box", "constbox", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): negbox = self.metainterp.execute_and_record( rop.INT_LT, [indexbox, ConstInt(0)]) @@ -374,23 +374,23 @@ self.execute(rop.OOISNOT, [box1, box2]) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_gc(self, box, fielddesc): self.execute(rop.GETFIELD_GC, [box], descr=fielddesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_gc_pure(self, box, fielddesc): self.execute(rop.GETFIELD_GC_PURE, [box], descr=fielddesc) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_GC, [box, valuebox], descr=fielddesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_raw(self, box, fielddesc): self.execute(rop.GETFIELD_RAW, [box], descr=fielddesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_raw_pure(self, box, fielddesc): self.execute(rop.GETFIELD_RAW_PURE, [box], descr=fielddesc) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc) @@ -409,11 +409,11 @@ f.setup_call(varargs) return True - @arguments("int", "varargs") + @arguments("constbox", "varargs") def opimpl_residual_call(self, calldescr, varargs): return self.execute_with_exc(rop.CALL, varargs, descr=calldescr) - @arguments("int", "varargs") + @arguments("constbox", "varargs") def opimpl_residual_call_pure(self, calldescr, varargs): self.execute(rop.CALL_PURE, varargs, descr=calldescr) @@ -659,13 +659,13 @@ return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) @specialize.arg(1) - def execute(self, opnum, argboxes, descr=0): + def execute(self, opnum, argboxes, descr=None): resbox = self.metainterp.execute_and_record(opnum, argboxes, descr) if resbox is not None: self.make_result_box(resbox) @specialize.arg(1) - def execute_with_exc(self, opnum, argboxes, descr=0): + def execute_with_exc(self, opnum, argboxes, descr=None): cpu = self.metainterp.cpu resbox = executor.execute(cpu, opnum, argboxes, descr) if not we_are_translated(): @@ -776,7 +776,7 @@ return False return True - def execute_and_record(self, opnum, argboxes, descr=0): + def execute_and_record(self, opnum, argboxes, descr=None): # execute the operation first resbox = executor.execute(self.cpu, opnum, argboxes, descr) # check if the operation can be constant-folded away Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Tue Mar 10 00:44:18 2009 @@ -17,7 +17,8 @@ # for 'guard_nonvirtualizable' vdesc = None - def __init__(self, opnum, args, result, descr=0): + def __init__(self, opnum, args, result, descr=None): + from pypy.jit.metainterp.history import AbstractValue assert isinstance(opnum, int) self.opnum = opnum self.args = list(args) @@ -25,7 +26,8 @@ self.result = result # for 'call', 'new', 'getfield_gc'...: the descr is a number provided # by the backend holding details about the type of the operation - assert isinstance(descr, int) + if descr is not None: + assert isinstance(descr, AbstractValue) self.descr = descr def __repr__(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Tue Mar 10 00:44:18 2009 @@ -4,7 +4,7 @@ class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist, start, cpu): newboxlist.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): @@ -119,15 +119,16 @@ return False return True - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist, start, cpu): for ofs, subspecnode in self.fields: subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start) + subspecnode.expand_boxlist(subinstnode, newboxlist, start, cpu) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: + descr = cpu.repack_descr(ofs) fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox], ofs) + [valuebox], descr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): @@ -136,9 +137,10 @@ class VirtualizedSpecNode(SpecNodeWithFields): - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist, start, cpu): newboxlist.append(instnode.source) - SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) + SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start, + cpu) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) @@ -150,7 +152,7 @@ class DelayedSpecNode(VirtualizedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist): + def expand_boxlist(self, instnode, newboxlist, oplist, cpu): newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) @@ -162,13 +164,14 @@ newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() + descr = cpu.repack_descr(ofs) oplist.append(ResOperation(rop.GETFIELD_GC, - [instnode.source], box, ofs)) + [instnode.source], box, descr)) newboxlist.append(box) class DelayedFixedListSpecNode(DelayedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist): + def expand_boxlist(self, instnode, newboxlist, oplist, cpu): from pypy.jit.metainterp.history import ResOperation, ConstInt from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Tue Mar 10 00:44:18 2009 @@ -70,7 +70,7 @@ # Box._extended_display = saved return True -def ResOperation(opname, args, result, descr=0): +def ResOperation(opname, args, result, descr=None): if opname == 'escape': opnum = -123 # random number not in the list else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 10 00:44:18 2009 @@ -168,7 +168,7 @@ locals().update(B.__dict__) n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v2 = BoxInt(13) - sizebox = ConstInt(cpu.sizeof(NODE)) + sizebox = cpu.sizeof(NODE) ops = [ ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], From fijal at codespeak.net Tue Mar 10 00:47:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 00:47:10 +0100 (CET) Subject: [pypy-svn] r62785 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090309234710.F2164169EFE@codespeak.net> Author: fijal Date: Tue Mar 10 00:47:10 2009 New Revision: 62785 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: fix translation Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 10 00:47:10 2009 @@ -521,7 +521,7 @@ [clsbox]) if op: op.vdesc = vdesc - op.descr = guard_field + op.descr = ConstInt(guard_field) @arguments("box") def opimpl_keepalive(self, box): From fijal at codespeak.net Tue Mar 10 00:47:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 00:47:57 +0100 (CET) Subject: [pypy-svn] r62786 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090309234757.C3920169EFF@codespeak.net> Author: fijal Date: Tue Mar 10 00:47:57 2009 New Revision: 62786 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: this is useful, but was not meant to be checked in Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 10 00:47:57 2009 @@ -225,7 +225,7 @@ self.bytecode.dump() else: print repr(self.bytecode) - self.bytecode.dump(open("/tmp/jitcodes/%s" % self.bytecode.name, "w")) + #self.bytecode.dump(open("/tmp/jitcodes/%s" % self.bytecode.name, "w")) def const_position(self, constvalue): """Generate a constant of the given value. From fijal at codespeak.net Tue Mar 10 01:09:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 01:09:00 +0100 (CET) Subject: [pypy-svn] r62787 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090310000900.347BC169F0C@codespeak.net> Author: fijal Date: Tue Mar 10 01:08:57 2009 New Revision: 62787 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py Log: oops Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py Tue Mar 10 01:08:57 2009 @@ -6,7 +6,7 @@ def get_field_token(STRUCT, fieldname, translate_support_code): if translate_support_code: return (llmemory.offsetof(STRUCT, fieldname), - get_size(STRUCT, True)) + get_size(getattr(STRUCT, fieldname), True)) cstruct = ll2ctypes.get_ctypes_type(STRUCT) cfield = getattr(cstruct, fieldname) return (cfield.offset, cfield.size) From afa at codespeak.net Tue Mar 10 08:51:45 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 08:51:45 +0100 (CET) Subject: [pypy-svn] r62788 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090310075145.76A741684A8@codespeak.net> Author: afa Date: Tue Mar 10 08:51:43 2009 New Revision: 62788 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_os.py Log: Fix some of the failures in test_os on Windows: - Raising OSError instead of WindowsError is an implementation detail IMO - fix test_access and test_chmod to actually use the function they want to test. Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_os.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_os.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_os.py Tue Mar 10 08:51:43 2009 @@ -407,25 +407,25 @@ class Win32ErrorTests(unittest.TestCase): def test_rename(self): - self.assertRaises(WindowsError, os.rename, test_support.TESTFN, test_support.TESTFN+".bak") + self.assertRaises(OSError, os.rename, test_support.TESTFN, test_support.TESTFN+".bak") def test_remove(self): - self.assertRaises(WindowsError, os.remove, test_support.TESTFN) + self.assertRaises(OSError, os.remove, test_support.TESTFN) def test_chdir(self): - self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) + self.assertRaises(OSError, os.chdir, test_support.TESTFN) def test_mkdir(self): - self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) + self.assertRaises(OSError, os.chdir, test_support.TESTFN) def test_utime(self): - self.assertRaises(WindowsError, os.utime, test_support.TESTFN, None) + self.assertRaises(OSError, os.utime, test_support.TESTFN, None) def test_access(self): - self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) + self.assertRaises(OSError, os.access, test_support.TESTFN, 0) def test_chmod(self): - self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) + self.assertRaises(OSError, os.chmod, test_support.TESTFN, 0) if sys.platform != 'win32': class Win32ErrorTests(unittest.TestCase): From afa at codespeak.net Tue Mar 10 09:49:08 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 09:49:08 +0100 (CET) Subject: [pypy-svn] r62789 - pypy/trunk/lib-python Message-ID: <20090310084908.112491684F6@codespeak.net> Author: afa Date: Tue Mar 10 09:49:07 2009 New Revision: 62789 Modified: pypy/trunk/lib-python/conftest.py Log: Skip some tests on windows Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Tue Mar 10 09:49:07 2009 @@ -118,10 +118,17 @@ m.test_main() ''' % locals()) +if sys.platform == 'win32': + skip_win32 = "Not supported on Windows" + only_win32 = False +else: + skip_win32 = False + only_win32 = "Only on Windows" + testmap = [ RegrTest('test___all__.py', core=True), RegrTest('test___future__.py', core=True), - RegrTest('test__locale.py'), + RegrTest('test__locale.py', skip=skip_win32), RegrTest('test_aepack.py', skip=True), RegrTest('test_al.py', skip=True), RegrTest('test_ast.py', skip="unsupported module _ast"), @@ -187,7 +194,7 @@ RegrTest('test_copy.py', core=True), RegrTest('test_copy_reg.py', core=True), RegrTest('test_cpickle.py', core=True), - RegrTest('test_crypt.py', usemodules='crypt'), + RegrTest('test_crypt.py', usemodules='crypt', skip=skip_win32), RegrTest('test_csv.py'), RegrTest('test_curses.py', skip="unsupported extension module"), @@ -219,7 +226,7 @@ RegrTest('test_errno.py'), RegrTest('test_exceptions.py', core=True), RegrTest('test_extcall.py', core=True), - RegrTest('test_fcntl.py', usemodules='fcntl'), + RegrTest('test_fcntl.py', usemodules='fcntl', skip=skip_win32), RegrTest('test_file.py', usemodules="posix", core=True), RegrTest('test_filecmp.py', core=True), RegrTest('test_fileinput.py', core=True), @@ -247,7 +254,7 @@ RegrTest('test_glob.py', core=True), RegrTest('test_global.py', core=True), RegrTest('test_grammar.py', core=True), - RegrTest('test_grp.py'), + RegrTest('test_grp.py', skip=skip_win32), RegrTest('test_gzip.py'), RegrTest('test_hash.py', core=True), @@ -318,14 +325,14 @@ RegrTest('test_peepholer.py'), RegrTest('test_pep247.py'), RegrTest('test_pep263.py'), - RegrTest('test_pep277.py', skip="NT only"), + RegrTest('test_pep277.py', skip=only_win32), RegrTest('test_pep292.py'), RegrTest('test_pickle.py', core=True), RegrTest('test_pickletools.py', core=False), RegrTest('test_pkg.py', core=True), RegrTest('test_pkgimport.py', core=True), RegrTest('test_plistlib.py', skip="unsupported module"), - RegrTest('test_poll.py'), + RegrTest('test_poll.py', skip=skip_win32), RegrTest('test_popen.py'), RegrTest('test_popen2.py'), RegrTest('test_posix.py'), @@ -335,7 +342,7 @@ RegrTest('test_profile.py'), RegrTest('test_profilehooks.py', core=True), RegrTest('test_pty.py', skip="unsupported extension module"), - RegrTest('test_pwd.py'), + RegrTest('test_pwd.py', skip=skip_win32), RegrTest('test_pyclbr.py'), RegrTest('test_pyexpat.py'), @@ -345,7 +352,7 @@ RegrTest('test_re.py', core=True), RegrTest('test_repr.py', core=True), - RegrTest('test_resource.py'), + RegrTest('test_resource.py', skip=skip_win32), RegrTest('test_rfc822.py'), RegrTest('test_rgbimg.py', skip="unsupported extension module"), RegrTest('test_richcmp.py', core=True), @@ -440,7 +447,7 @@ RegrTest('test_weakref.py', core=True, usemodules='_weakref'), RegrTest('test_whichdb.py'), - RegrTest('test_winreg.py', skip=sys.platform != 'win32'), + RegrTest('test_winreg.py', skip=only_win32), RegrTest('test_winsound.py', skip="unsupported extension module"), RegrTest('test_xmllib.py'), RegrTest('test_xmlrpc.py'), From fijal at codespeak.net Tue Mar 10 10:02:41 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 10:02:41 +0100 (CET) Subject: [pypy-svn] r62790 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp/test Message-ID: <20090310090241.1CD571684F6@codespeak.net> Author: fijal Date: Tue Mar 10 10:02:40 2009 New Revision: 62790 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: fix tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Tue Mar 10 10:02:40 2009 @@ -19,6 +19,7 @@ from pypy.jit.metainterp import heaptracker, resoperation, executor from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.llgraph import symbolic +from pypy.jit.metainterp import history from pypy.rlib.objectmodel import ComputedIntSymbolic from pypy.rlib.rarithmetic import r_uint, intmask @@ -139,6 +140,8 @@ self.opnum = opnum self.args = [] self.result = None + if descr: + assert isinstance(descr, history.AbstractValue) self.descr = descr self.livevars = [] # for guards only @@ -565,7 +568,7 @@ def op_call(self, calldescr, func, *args): _call_args[:] = args - if calldescr == sys.maxint: + if calldescr.getint() == sys.maxint: err_result = None elif calldescr.getint() & 1: err_result = lltype.nullptr(llmemory.GCREF.TO) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Tue Mar 10 10:02:40 2009 @@ -218,12 +218,12 @@ @staticmethod def calldescrof(ARGS, RESULT): if RESULT is lltype.Void: - return sys.maxint + return history.ConstInt(sys.maxint) token = history.getkind(RESULT) if token == 'ptr': - return 1 + return history.ConstInt(1) else: - return 0 + return history.ConstInt(0) @staticmethod def typefor(fielddesc): @@ -291,9 +291,10 @@ fielddescr, self.memo_cast)) - def do_getfield_raw(self, args, fielddescr): + def do_getfield_raw(self, args, fieldbox): + fielddescr = fieldbox.getint() struct = self.cast_int_to_adr(args[0].getint()) - if self.typefor(fielddescr) == 'ptr': + if self.typefor(fieldbox) == 'ptr': return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, fielddescr)) else: @@ -359,6 +360,7 @@ llimpl.do_strsetitem(0, string, index, newvalue) def do_call(self, args, calldescr): + assert isinstance(calldescr, history.ConstInt) func = args[0].getint() for arg in args[1:]: if (isinstance(arg, history.BoxPtr) or Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Tue Mar 10 10:02:40 2009 @@ -30,20 +30,20 @@ def test_A_find_nodes(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) node = spec.nodes[A.l] assert isinstance(node.cls.source, FixedList) assert node.expanded_fields.keys() == [0] def test_A_intersect(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert isinstance(spec.specnodes[0], DelayedFixedListSpecNode) def test_A_optimize_loop(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() spec.optimize_loop(None) equaloplists(spec.loop.operations, [ @@ -72,7 +72,7 @@ def test_B_optimize_loop(): spec = PerfectSpecializer(Loop(B.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() spec.optimize_loop(None) equaloplists(spec.loop.operations, [ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Tue Mar 10 10:02:40 2009 @@ -109,7 +109,7 @@ def test_A_find_nodes(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) assert spec.nodes[A.sum] is not spec.nodes[A.sum2] assert spec.nodes[A.n1] is not spec.nodes[A.n2] assert spec.nodes[A.n1].cls.source.value == node_vtable_adr @@ -119,21 +119,21 @@ def test_A_intersect_input_and_output(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert len(spec.specnodes) == 2 spec_sum, spec_n = spec.specnodes assert isinstance(spec_sum, NotSpecNode) assert isinstance(spec_n, VirtualInstanceSpecNode) assert spec_n.known_class.value == node_vtable_adr - assert spec_n.fields[0][0] == A.ofs_value + assert spec_n.fields[0][0] == A.ofs_value.getint() assert isinstance(spec_n.fields[0][1], NotSpecNode) def test_A_optimize_loop(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [A.sum, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), @@ -161,7 +161,7 @@ def test_B_find_nodes(): spec = PerfectSpecializer(Loop(B.ops)) - spec.find_nodes() + spec.find_nodes(cpu) assert spec.nodes[B.n1].cls.source.value == node_vtable_adr assert spec.nodes[B.n1].escaped assert spec.nodes[B.n2].cls.source.value == node_vtable_adr @@ -169,7 +169,7 @@ def test_B_intersect_input_and_output(): spec = PerfectSpecializer(Loop(B.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert len(spec.specnodes) == 2 spec_sum, spec_n = spec.specnodes @@ -179,9 +179,9 @@ def test_B_optimize_loop(): spec = PerfectSpecializer(Loop(B.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [B.sum, B.n1], None), # guard_class is gone @@ -216,14 +216,14 @@ def test_C_find_nodes(): spec = PerfectSpecializer(Loop(C.ops)) - spec.find_nodes() + spec.find_nodes(cpu) assert spec.nodes[C.n1].cls.source.value == node_vtable_adr assert spec.nodes[C.n1].escaped assert spec.nodes[C.n2].cls.source.value == node_vtable_adr def test_C_intersect_input_and_output(): spec = PerfectSpecializer(Loop(C.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[C.n2].escaped assert len(spec.specnodes) == 2 @@ -234,9 +234,9 @@ def test_C_optimize_loop(): spec = PerfectSpecializer(Loop(C.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone @@ -270,7 +270,7 @@ def test_D_intersect_input_and_output(): spec = PerfectSpecializer(Loop(D.ops)) - spec.find_nodes() + spec.find_nodes(cpu) py.test.raises(CancelInefficientLoop, spec.intersect_input_and_output) # ____________________________________________________________ @@ -293,9 +293,9 @@ def test_E_optimize_loop(): spec = PerfectSpecializer(Loop(E.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [E.sum, E.v], None), # guard_class is gone @@ -309,7 +309,7 @@ assert guard_op.liveboxes == [E.sum2, E.v2] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, E.ofs_value, -2)] + assert guard_op.storage_info.setfields == [(0, E.ofs_value.value, -2)] def test_E_rebuild_after_failure(): class FakeMetaInterp(object): @@ -325,9 +325,9 @@ return 'stuff' spec = PerfectSpecializer(Loop(E.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) guard_op = spec.loop.operations[-2] v_sum_b = BoxInt(13) v_v_b = BoxInt(14) @@ -376,16 +376,16 @@ def test_F_find_nodes(): spec = PerfectSpecializer(Loop(F.ops)) - spec.find_nodes() + spec.find_nodes(cpu) assert not spec.nodes[F.n1].escaped assert not spec.nodes[F.n2].escaped def test_F_optimize_loop(): spec = PerfectSpecializer(Loop(F.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [F.sum, F.v, F.n3], None), ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), @@ -415,9 +415,9 @@ def test_F2_optimize_loop(): spec = PerfectSpecializer(Loop(F2.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, F2.ops) # ____________________________________________________________ @@ -445,9 +445,9 @@ def test_G_optimize_loop(): spec = PerfectSpecializer(Loop(G.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [G.sum, G.v], None), # guard_class is gone @@ -461,7 +461,7 @@ assert guard_op.liveboxes == [G.sum2, ConstInt(124)] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, G.ofs_value, -2)] + assert guard_op.storage_info.setfields == [(0, G.ofs_value.value, -2)] # ____________________________________________________________ @@ -492,7 +492,7 @@ def test_H_intersect_input_and_output(): spec = PerfectSpecializer(Loop(H.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[H.n0].escaped assert spec.nodes[H.n1].escaped @@ -520,7 +520,7 @@ def test_I_intersect_input_and_output(): spec = PerfectSpecializer(Loop(I.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[I.n0].escaped assert spec.nodes[I.n2].escaped @@ -549,7 +549,7 @@ def test_J_intersect_input_and_output(): spec = PerfectSpecializer(Loop(J.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert not spec.nodes[J.n0].escaped assert spec.nodes[J.n1].escaped @@ -575,9 +575,9 @@ def test_K0_optimize_loop(): spec = PerfectSpecializer(Loop(K0.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K0.sum, K0.n1, K0.v], None), @@ -609,9 +609,9 @@ def test_K1_optimize_loop(): spec = PerfectSpecializer(Loop(K1.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K1.sum, K1.n1, K1.v], None), @@ -642,9 +642,9 @@ def test_K_optimize_loop(): spec = PerfectSpecializer(Loop(K.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K.sum, K.n1, K.v], None), ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), @@ -673,9 +673,9 @@ def test_L_optimize_loop(): spec = PerfectSpecializer(Loop(L.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [L.sum, L.n1, L.v], None), ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), @@ -704,9 +704,9 @@ def test_M_optimize_loop(): spec = PerfectSpecializer(Loop(M.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [M.sum, M.n1, M.v], None), @@ -735,9 +735,9 @@ def test_N_optimize_loop(): spec = PerfectSpecializer(Loop(N.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [N.sum, N.n1, N.v], None), @@ -764,9 +764,9 @@ def test_O1_optimize_loop(): spec = PerfectSpecializer(Loop(O1.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O1.n1), @@ -794,9 +794,9 @@ def test_O2_optimize_loop(): spec = PerfectSpecializer(Loop(O2.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O2.n1), @@ -826,9 +826,9 @@ def test_O3_optimize_loop(): spec = PerfectSpecializer(Loop(O3.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O3.n1), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 10 10:02:40 2009 @@ -101,12 +101,12 @@ def test_A_find_nodes(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) assert spec.nodes[A.fr].virtualized def test_A_intersect_input_and_output(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[A.fr].escaped assert spec.nodes[A.fr].virtualized @@ -116,9 +116,9 @@ def test_A_optimize_loop(): spec = PerfectSpecializer(Loop(A.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop(cpu) equaloplists(spec.loop.operations, [ ResOperation('merge_point', [A.sum, A.fr, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), @@ -152,14 +152,14 @@ def test_B_intersect_input_and_output(): spec = PerfectSpecializer(Loop(B.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[B.fr].escaped assert spec.nodes[B.fr].virtualized assert spec.nodes[B.n1].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 - assert spec.specnodes[0].fields[0][0] == B.ofs_node + assert spec.specnodes[0].fields[0][0] == B.ofs_node.value assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) # ____________________________________________________________ @@ -188,7 +188,7 @@ def test_C_intersect_input_and_output(): spec = PerfectSpecializer(Loop(C.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[C.fr].escaped assert spec.nodes[C.fr].virtualized @@ -196,7 +196,7 @@ assert spec.nodes[C.n2].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 - assert spec.specnodes[0].fields[0][0] == C.ofs_node + assert spec.specnodes[0].fields[0][0] == C.ofs_node.value assert isinstance(spec.specnodes[0].fields[0][1], DelayedSpecNode) @@ -228,7 +228,7 @@ def test_D_intersect_input_and_output(): py.test.skip("XXX") spec = PerfectSpecializer(Loop(D.ops)) - spec.find_nodes() + spec.find_nodes(cpu) spec.intersect_input_and_output() assert spec.nodes[D.fr].escaped assert spec.nodes[D.fr].virtualized From fijal at codespeak.net Tue Mar 10 10:04:13 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 10:04:13 +0100 (CET) Subject: [pypy-svn] r62791 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090310090413.514A31684F9@codespeak.net> Author: fijal Date: Tue Mar 10 10:04:12 2009 New Revision: 62791 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: ARGH. how we can get reasonable code if we don't actually enable optimizations? Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Tue Mar 10 10:04:12 2009 @@ -25,6 +25,7 @@ from pypy.jit.backend.detect_cpu import getcpuclass warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=getcpuclass(), translate_support_code=True, + listops=True, **kwds) warmrunnerdesc.finish() From afa at codespeak.net Tue Mar 10 10:13:38 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 10:13:38 +0100 (CET) Subject: [pypy-svn] r62792 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090310091338.D9EFB1684F6@codespeak.net> Author: afa Date: Tue Mar 10 10:13:36 2009 New Revision: 62792 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_isinstance.py Log: pypy does not use the recursion limit, but its own stack check. On windows, this function fails with a recursion of 18600. Speed up the test and avoid the timeout! Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_isinstance.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_isinstance.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_isinstance.py Tue Mar 10 10:13:36 2009 @@ -262,7 +262,8 @@ tuple_arg = (compare_to,) for cnt in xrange(sys.maxint): tuple_arg = (tuple_arg,) - fxn(arg, tuple_arg) + if cnt % 100 == 0: + fxn(arg, tuple_arg) def test_main(): From afa at codespeak.net Tue Mar 10 10:14:40 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 10:14:40 +0100 (CET) Subject: [pypy-svn] r62793 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090310091440.B58E31684F6@codespeak.net> Author: afa Date: Tue Mar 10 10:14:37 2009 New Revision: 62793 Added: pypy/trunk/lib-python/modified-2.5.2/test/test_pkgimport.py - copied, changed from r62778, pypy/trunk/lib-python/2.5.2/test/test_pkgimport.py Log: Don't rely on refcounting to close the file. Copied: pypy/trunk/lib-python/modified-2.5.2/test/test_pkgimport.py (from r62778, pypy/trunk/lib-python/2.5.2/test/test_pkgimport.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_pkgimport.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_pkgimport.py Tue Mar 10 10:14:37 2009 @@ -22,7 +22,8 @@ self.package_dir = os.path.join(self.test_dir, self.package_name) os.mkdir(self.package_dir) - open(os.path.join(self.package_dir, '__init__'+os.extsep+'py'), 'w') + f = open(os.path.join(self.package_dir, '__init__'+os.extsep+'py'), 'w') + f.close() self.module_path = os.path.join(self.package_dir, 'foo'+os.extsep+'py') def tearDown(self): From fijal at codespeak.net Tue Mar 10 10:23:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 10:23:31 +0100 (CET) Subject: [pypy-svn] r62794 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090310092331.7C8411684F6@codespeak.net> Author: fijal Date: Tue Mar 10 10:23:30 2009 New Revision: 62794 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: some missing trivial ops Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Tue Mar 10 10:23:30 2009 @@ -276,7 +276,9 @@ genop_int_lt = _cmpop("L", "G") genop_int_le = _cmpop("LE", "GE") genop_int_eq = _cmpop("E", "NE") + genop_oois = _cmpop("E", "NE") genop_int_ne = _cmpop("NE", "E") + genop_ooisnot = _cmpop("NE", "E") genop_int_gt = _cmpop("G", "L") genop_int_ge = _cmpop("GE", "LE") Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Tue Mar 10 10:23:30 2009 @@ -684,6 +684,8 @@ xxx_consider_char_eq = _consider_compop consider_int_ne = _consider_compop consider_int_eq = _consider_compop + consider_oois = _consider_compop + consider_ooisnot = _consider_compop consider_uint_gt = _consider_compop consider_uint_lt = _consider_compop consider_uint_le = _consider_compop From afa at codespeak.net Tue Mar 10 10:31:57 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 10:31:57 +0100 (CET) Subject: [pypy-svn] r62795 - pypy/trunk/lib-python/modified-2.5.2 Message-ID: <20090310093157.1D8431684E9@codespeak.net> Author: afa Date: Tue Mar 10 10:31:57 2009 New Revision: 62795 Modified: pypy/trunk/lib-python/modified-2.5.2/gettext.py Log: fix test_gettext on windows by explicitely closing the file Modified: pypy/trunk/lib-python/modified-2.5.2/gettext.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/gettext.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/gettext.py Tue Mar 10 10:31:57 2009 @@ -481,7 +481,11 @@ key = os.path.abspath(mofile) t = _translations.get(key) if t is None: - t = _translations.setdefault(key, class_(open(mofile, 'rb'))) + fp = open(mofile, 'rb') + try: + t = _translations.setdefault(key, class_(fp)) + finally: + fp.close() # Copy the translation object to allow setting fallbacks and # output charset. All other instance data is shared with the # cached object. From hpk at codespeak.net Tue Mar 10 11:01:29 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 10 Mar 2009 11:01:29 +0100 (CET) Subject: [pypy-svn] r62796 - pypy/extradoc/talk/openbossa2009/pypy-mobile Message-ID: <20090310100129.23D6A1683E3@codespeak.net> Author: hpk Date: Tue Mar 10 11:01:28 2009 New Revision: 62796 Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Log: second draft, mostly complete, except review + layout issues Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt ============================================================================== --- pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Tue Mar 10 11:01:28 2009 @@ -2,6 +2,16 @@ PyPy: status and mobile perspectives ===================================== +Where i come from ... +======================== + +.. image:: little_red_riding_hood_by_marikaz.jpg + :scale: 100 + :align: left + +http://marikaz.deviantart.com/ CC 3.0 AN-ND + + What this talk is about ======================= @@ -9,25 +19,32 @@ * resource usage / startup time -* some ideas for improvements - +* ideas/visions PyPy? ======== -In this talk mostly: +In this talk mostly: PyPy = PyPy Python Interpreter + +.. image:: arch-pypy-basic.png + :scale: 50 + :align: center - PyPy = PyPy Python Interpreter PyPy - developer motivation ================================= -* Separate language specification from low-level details +* high level language specification! * layer GCs, JIT, Stackless atop the spec * generate interpreters for C, .NET, JVM, embedded platforms, ... + +.. image:: pypy-multitarget.png + :scale: 50 + :align: center + PyPy - user motivation ======================= @@ -37,20 +54,24 @@ * support more programming paradigms -* Just-in-time compiler should make number-crunching - and static-enough code fast enough +what else is PyPy? +======================= -Getting Production ready -========================== +Virtual Machine translation framework! -* we worked a lot on running - existing applications on top of PyPy +.. image:: mario.png + :scale: 100 + :align: center -* PyPy today very (most?) compatible to Python 2.5 +Getting Production ready / PyPy 1.1 +===================================== -* main blocker for running apps will be **missing external modules** +.. image:: new_color_in_dark_old_city_by_marikaz.jpg + :scale: 100 + :align: left +http://marikaz.deviantart.com/ CC 3.0 AN-ND Sqlite ====== @@ -72,12 +93,10 @@ http://code.djangoproject.com/wiki/DjangoAndPyPy - Pylons ====== -* worked almost out of the box once eggs - were working (1 day) +* works out of the box * no SQLAlchemy yet, obscure problems ahead @@ -89,14 +108,10 @@ Twisted & Nevow =============== -* twisted works (60/4500 tests failing) +* twisted works (<30/4500 tests failing) * nevow works -* we don't support PyCrypto nor PyOpenSSL and we - won't anytime soon (if nobody contributes CTypes or rpython - versions) - * http://twistedmatrix.com/ @@ -109,193 +124,229 @@ * BitTorrent -* PyPy translation toolchain - -* py lib +* PyPy translation toolchain, py lib * sympy -CTypes -====== - -* official way to have bindings to - external (C) libraries for PyPy +So why doesn't PyPy work for me? +==================================== -* can handle i.e. pysqlite-ctypes, pyglet, pymunk or Sole Scion, - almost whatever.... +* PyPy not compatible to CPython extensions +* we have many builtin modules +* but 3rd party modules largely missing -* contribution to original ctypes - (better errno handling, bugfixes, tests...) +PyPy Answers for Extension modules +==================================== -* part of google sponsoring +- for using C-libs: CTypes +- for speed: JIT or if need be, RPython +- for using C++ libs: ??? -* XXX 32bit and a bit slow +CTypes status +==================== -CTypes configure -================ +* dynamically interact with C objects from Python +* examples: pyslite, pyglet (opengl), many others +* only 32Bit and a bit slow -* our own small addition to general - CTypes usefulness +PyPy resource usage +================================== -* invokes C compiler for small details - -* can handle #defines, types, structure layout - etc. - -Memory - comparison with CPython -=================================== - -* PyPy has pluggable Garbage Collection - -* gcbench - 0.8 (because of our faster GCs) - -* better handling of unusual patterns - -* care needed with communication with C - -* GCs are semi-decent +.. image:: end_of_a_age_by_marikaz.jpg + :scale: 100 + :align: left +http://marikaz.deviantart.com/ CC 3.0 AN-ND Speed of executing bytecode =============================== -* we're something between 0.8-4x slower than - CPython on executing bytecode +* somewhere between 0.8-4x times CPython speed * our JIT is to be the huge leap beyond CPython +* some more static optimizations? -Threading / Stackless +A Memory benchmark =================================== -* currently using GIL, quite robust +* gcbench performs at 0.8 the time of CPython -* free threading? requires research + some work - -* pypy-c has software threading / stackless - -* added during translation - -Other backends -============== - -* PyPy-jvm runs! - -* more integration between pypy-cli and .NET - -* general speed improvements +* PyPy has pluggable Garbage Collection -* both backends are progressing - very slowly though +* better handling of unusual patterns -* contributors wanted! +Threading / Stackless +=================================== -Sandboxing -========== +* pypy-c has massive software threading -* fully sandboxed python interpreter +* OS-threads: currently using GIL, quite robust -* all external calls to C goes via another - python process +* free threading? requires research + some work -* special library for making custom - policies +* all threading: added during translation! -.. image:: sandboxed.png - :scale: 30 - :align: center pypy-c measurements on Maemo =============================== - cross-compiled to Maemo -- measurements done on N810 device -- done with http://codespeak.net/svn/pypy/build/benchmem/pypy/ -- python object sizes, application benchmarks, startup time + +- measurements were done on N810 device + +- python object sizes, app benchmarks, startup time + - base interpreter size, GC pauses, interpretation speed +- see http://codespeak.net/svn/pypy/build/benchmem + Python object sizes ======================= - PyPy has smaller "per-object" RAM usage -- class instances usually at 50% of CPython size or less -- a lot of room for further optimizations -see table at http://codespeak.net/~hpk/openbossa09/table-objsizes.html +- instances usually at 50% of CPython size -startup time -======================= +- as efficient as CPython's __slots__ without the caveats + +- room for further optimizations + +table at http://codespeak.net/~hpk/openbossa2009/table-objsize.html + +Maemo Interpreter startup time +=============================== - +--------------+--------+-------------+---------------+ - |startup |python |pypy-Omem-opt|python-launcher| - +--------------+--------+-------------+---------------+ - |site |**0.24**|**0.16**/0.13|**0.11**/0.00 | - +--------------+--------+-------------+---------------+ - |nosite |**0.21**|**0.04**/0.03|**0.11**/0.00 | - +--------------+--------+-------------+---------------+ - |importos |**0.21**|**0.04**/0.03|**0.11**/0.00 | - +--------------+--------+-------------+---------------+ - |importdecimal |**0.47**|**0.42**/0.39|**0.34**/0.00 | - +--------------+--------+-------------+---------------+ - |importoptparse|**0.54**|**0.04**/0.01|**0.11**/0.00 | - +--------------+--------+-------------+---------------+ ++--------------+--------+--------+---------------+ +|startup |python |Omem-opt|python-launcher| ++--------------+--------+--------+---------------+ +|site |**0.24**|**0.16**|**0.11** | ++--------------+--------+--------+---------------+ +|nosite |**0.21**|**0.04**|**0.11** | ++--------------+--------+--------+---------------+ +|importos |**0.21**|**0.04**|**0.11** | ++--------------+--------+--------+---------------+ +|importdecimal |**0.47**|**0.42**|**0.34** | ++--------------+--------+--------+---------------+ +|importoptparse|**0.54**|**0.04**|**0.11** | ++--------------+--------+--------+---------------+ + +PyPy has faster startup if few bytecode execution is involved where pypy is currently worse =================================== -- interpreter size: larger than cpython, but mostly shareable -- gc collection pauses can be larger: needs work +- larger (but shareable) base interpreter size +- gc collection pauses can be larger: tuning? - bytecode execution speed: 1-4 times slower than CPython -(FYI also our parser and compiler implementation is bad) +(oh, and our parser and compiler speed is particularly bad) + +Python Application benchmarks +============================== + + +------------------------+-----------------+-----------------+ + |app benchmark |python |pypy-Omem | + +------------------------+-----------------+-----------------+ + |allocate_and_throw_away |**28152** / 20578|**17700** / 9845 | + +------------------------+-----------------+-----------------+ + |allocate_constant_number|**11528** / 11279|**7712** / 4792 | + +------------------------+-----------------+-----------------+ + |allocate_couple |**28136** / 21254|**17712** / 9882 | + +------------------------+-----------------+-----------------+ + |cpython_nasty |**30592** / 23743|**15648** / 9061 | + +------------------------+-----------------+-----------------+ + |gcbench |**9548** / 7454 |**17936** / 13419| + +------------------------+-----------------+-----------------+ + |list_of_messages |**31908** / 13924|**14000** / 7879 | + +------------------------+-----------------+-----------------+ -Where pypy is already better +Summary measurements ============================= -- more efficient RAM usage -- faster startup -- more secure - -Extension modules -=================== - -- for binding to C-libs: ctypes -- for speed: JIT or if need be: rpython -- binding to C++? +* slower bytecode execution speed +* larger (but shareable) base interpreter size +* smaller objects +* better app behaviour +* faster startup (if few imports are involved) + +Note: not much work to optimise non-speed issues was done yet! + + +Ideas and visions +============================= + +.. image:: flying_lady_by_marikaz.jpg + :scale: 100 + :align: left + +http://marikaz.deviantart.com/ CC 3.0 AN-ND Idea: C++ Extension modules ============================= - idea: use CERN's Reflex mechanism -- generate shared "introspect" library for each C++ lib -- write generic small extension module in Python +- tool compiles shared "introspect" library for each C++ lib +- introspect-library handled by generic helper module +- maybe generically work with C++ libs? +- otherwise: small module to do extra bits +- IOW, some more thought and experimentation needed -Idea: perfect PYC files +perfect PYC files ============================ -- PYC file gets MMAPed into process memory -- interpreter directly works with memory data structures -- executes bytecode to construct __dict__ - --> total sharing of bytecode and constants --> no allocation of redundant objects during import +- MMAP (newstyle) PYC file into into memory +- execute bytecode to construct module namespace +- but: directly work with PYC data, zero-copy +- don't touch mmaped pages unless needed +- **no allocs of redundant objects during import** +- **total sharing of bytecode and constants** + +JIT for overhead elimination +==================================== + +- JIT to speed up code up to 100 times +- keep a good memory/speed gain balance! +- parametrize JIT heuristics to care for very hot paths +- JIT could remove overheads for calling into C++! -Idea: next-generation GC work -=============================== +Next-generation Garbage Collection +==================================== - currently: naive Mark&Compact (500 lines of code) -- port/implement researched techniques +- port/implement newer techniques - malloc-directed inlining - maximize shared interpreter state -- minimize collection pauses / incremental collection a word about doing GCs =================================== - program your GC in Python - test your GC in Python -- get tracebacks on memory faults +- get Python tracebacks instead of segfaults - once ready, translate with Python Interpreter +One last bit +================= + +.. image:: mystical_color_statue_by_marikaz.jpg + :scale: 100 + :align: left + +http://marikaz.deviantart.com/ CC 3.0 AN-ND + +Sandboxing / Virtualization +================================= + +* we have a fully sandboxed interpreter! + +* all IO and OS external calls serialized to + separate process + +.. image:: sandboxed.png + :scale: 30 + :align: center + Outlook / ========= @@ -309,14 +360,14 @@ Contact / Q&A ========================== -holger krekel -at http://merlinux.eu +holger krekel at http://merlinux.eu +Blog: http://tetamap.wordpress.com PyPy: http://codespeak.net/pypy - -My Blog: http://tetamap.wordpress.com PyPy Blog: http://morepypy.blogspot.com +Photos: http://marikaz.deviantart.com/gallery/ + .. raw:: latex \begin{figure} From afa at codespeak.net Tue Mar 10 11:34:05 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 11:34:05 +0100 (CET) Subject: [pypy-svn] r62801 - in pypy/trunk/lib-python: 2.5.2/test modified-2.5.2 Message-ID: <20090310103405.29ECD1683E8@codespeak.net> Author: afa Date: Tue Mar 10 11:34:04 2009 New Revision: 62801 Added: pypy/trunk/lib-python/modified-2.5.2/mailbox.py - copied, changed from r62778, pypy/trunk/lib-python/2.5.2/mailbox.py Modified: pypy/trunk/lib-python/2.5.2/test/test_mailbox.py Log: Fix test_mailbox on windows by carefully closing every opened file. Phew. I'm not sure I got it right everywhere. Modified: pypy/trunk/lib-python/2.5.2/test/test_mailbox.py ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_mailbox.py (original) +++ pypy/trunk/lib-python/2.5.2/test/test_mailbox.py Tue Mar 10 11:34:04 2009 @@ -135,6 +135,7 @@ msg = self._box.get(key1) self.assert_(msg['from'] == 'foo') self.assert_(msg.fp.read() == '1') + msg.fp.close() def test_getitem(self): # Retrieve message using __getitem__() @@ -167,10 +168,12 @@ # Get file representations of messages key0 = self._box.add(self._template % 0) key1 = self._box.add(_sample_message) - self.assert_(self._box.get_file(key0).read().replace(os.linesep, '\n') - == self._template % 0) - self.assert_(self._box.get_file(key1).read().replace(os.linesep, '\n') - == _sample_message) + f0 = self._box.get_file(key0) + self.assert_(f0.read().replace(os.linesep, '\n') == self._template % 0) + f0.close() + f1 = self._box.get_file(key1) + self.assert_(f1.read().replace(os.linesep, '\n') == _sample_message) + f1.close() def test_iterkeys(self): # Get keys using iterkeys() @@ -398,6 +401,11 @@ self._box.add(contents[1]) self._box.add(contents[2]) method() + + # XXX this makes some tests not useful any more, + # but the mailbox really must closed before we replace the variable. + self._box.close() + self._box = self._factory(self._path) keys = self._box.keys() self.assert_(len(keys) == 3) @@ -757,7 +765,10 @@ self._box._file.seek(0) contents = self._box._file.read() self._box.close() - self.assert_(contents == open(self._path, 'rb').read()) + f = open(self._path, 'rb') + initial = f.read() + f.close() + self.assert_(contents == initial) self._box = self._factory(self._path) def test_lock_conflict(self): @@ -1736,43 +1747,57 @@ #self.assert_(len(self.mbox.boxes) == 0) self.assert_(self.mbox.next() is None) self.assert_(self.mbox.next() is None) + self.mbox.close() def test_nonempty_maildir_cur(self): self.createMessage("cur") self.mbox = mailbox.Maildir(test_support.TESTFN) #self.assert_(len(self.mbox.boxes) == 1) - self.assert_(self.mbox.next() is not None) + msg = self.mbox.next() + self.assert_(msg is not None) + msg.fp.close() self.assert_(self.mbox.next() is None) self.assert_(self.mbox.next() is None) + self.mbox.close() def test_nonempty_maildir_new(self): self.createMessage("new") self.mbox = mailbox.Maildir(test_support.TESTFN) #self.assert_(len(self.mbox.boxes) == 1) - self.assert_(self.mbox.next() is not None) + msg = self.mbox.next() + self.assert_(msg is not None) + msg.fp.close() self.assert_(self.mbox.next() is None) self.assert_(self.mbox.next() is None) + self.mbox.close() def test_nonempty_maildir_both(self): self.createMessage("cur") self.createMessage("new") self.mbox = mailbox.Maildir(test_support.TESTFN) #self.assert_(len(self.mbox.boxes) == 2) - self.assert_(self.mbox.next() is not None) - self.assert_(self.mbox.next() is not None) + msg = self.mbox.next() + self.assert_(msg is not None) + msg.fp.close() + msg = self.mbox.next() + self.assert_(msg is not None) + msg.fp.close() self.assert_(self.mbox.next() is None) self.assert_(self.mbox.next() is None) + self.mbox.close() def test_unix_mbox(self): ### should be better! import email.Parser fname = self.createMessage("cur", True) n = 0 - for msg in mailbox.PortableUnixMailbox(open(fname), + fp = open(fname) + for msg in mailbox.PortableUnixMailbox(fp, email.Parser.Parser().parse): n += 1 self.assertEqual(msg["subject"], "Simple Test") self.assertEqual(len(str(msg)), len(FROM_)+len(DUMMY_MESSAGE)) + fp.close() self.assertEqual(n, 1) ## End: classes from the original module (for backward compatibility). Copied: pypy/trunk/lib-python/modified-2.5.2/mailbox.py (from r62778, pypy/trunk/lib-python/2.5.2/mailbox.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/mailbox.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/mailbox.py Tue Mar 10 11:34:04 2009 @@ -1780,6 +1780,7 @@ def close(self): """Close the file.""" + self._file.close() del self._file def _read(self, size, read_method): @@ -1801,6 +1802,11 @@ self._start = start self._stop = stop + def close(self): + """Close the file.""" + # But do not close the underlying file + del self._file + def tell(self): """Return the position with respect to start.""" return _ProxyFile.tell(self) - self._start From hruske at codespeak.net Tue Mar 10 11:53:04 2009 From: hruske at codespeak.net (hruske at codespeak.net) Date: Tue, 10 Mar 2009 11:53:04 +0100 (CET) Subject: [pypy-svn] r62806 - pypy/dist/pypy/lib Message-ID: <20090310105304.E046A168505@codespeak.net> Author: hruske Date: Tue Mar 10 11:53:04 2009 New Revision: 62806 Added: pypy/dist/pypy/lib/_sha512.py Log: Adding pure-Python SHA512 implementation, ported from CPython. Added: pypy/dist/pypy/lib/_sha512.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/_sha512.py Tue Mar 10 11:53:04 2009 @@ -0,0 +1,270 @@ +""" +This code was Ported from CPython's sha512module.c +""" + +import struct + +SHA_BLOCKSIZE = 128 +SHA_DIGESTSIZE = 64 + + +def new_shaobject(): + return { + 'digest': [0L]*8, + 'count_lo': 0, + 'count_hi': 0, + 'data': [0]* SHA_BLOCKSIZE, + 'local': 0, + 'digestsize': 0 + } + +ROR64 = lambda x, y: (((x & 0xffffffffffffffff) >> (y & 63)) | (x << (64 - (y & 63)))) & 0xffffffffffffffff +Ch = lambda x, y, z: (z ^ (x & (y ^ z))) +Maj = lambda x, y, z: (((x | y) & z) | (x & y)) +S = lambda x, n: ROR64(x, n) +R = lambda x, n: (x & 0xffffffffffffffff) >> n +Sigma0 = lambda x: (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +Sigma1 = lambda x: (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +Gamma0 = lambda x: (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +Gamma1 = lambda x: (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + +def sha_transform(sha_info): + W = [] + + d = sha_info['data'] + for i in xrange(0,16): + W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7]) + + for i in xrange(16,80): + W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff ) + + ss = sha_info['digest'][:] + + def RND(a,b,c,d,e,f,g,h,i,ki): + t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff + t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff + d = (d + t0) & 0xffffffffffffffff + h = (t0 + t1) & 0xffffffffffffffff + return d & 0xffffffffffffffff, h & 0xffffffffffffffff + + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],3,0xe9b5dba58189dbbc) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],4,0x3956c25bf348b538) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],5,0x59f111f1b605d019) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],6,0x923f82a4af194f9b) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],7,0xab1c5ed5da6d8118) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],8,0xd807aa98a3030242) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],9,0x12835b0145706fbe) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],10,0x243185be4ee4b28c) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],11,0x550c7dc3d5ffb4e2) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],12,0x72be5d74f27b896f) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],13,0x80deb1fe3b1696b1) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],14,0x9bdc06a725c71235) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],15,0xc19bf174cf692694) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],16,0xe49b69c19ef14ad2) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],17,0xefbe4786384f25e3) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],18,0x0fc19dc68b8cd5b5) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],19,0x240ca1cc77ac9c65) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],20,0x2de92c6f592b0275) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],21,0x4a7484aa6ea6e483) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],22,0x5cb0a9dcbd41fbd4) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],23,0x76f988da831153b5) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],24,0x983e5152ee66dfab) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],25,0xa831c66d2db43210) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],26,0xb00327c898fb213f) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],27,0xbf597fc7beef0ee4) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],28,0xc6e00bf33da88fc2) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],29,0xd5a79147930aa725) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],30,0x06ca6351e003826f) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],31,0x142929670a0e6e70) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],32,0x27b70a8546d22ffc) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],33,0x2e1b21385c26c926) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],34,0x4d2c6dfc5ac42aed) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],35,0x53380d139d95b3df) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],36,0x650a73548baf63de) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],37,0x766a0abb3c77b2a8) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],38,0x81c2c92e47edaee6) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],39,0x92722c851482353b) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],40,0xa2bfe8a14cf10364) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],41,0xa81a664bbc423001) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],42,0xc24b8b70d0f89791) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],43,0xc76c51a30654be30) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],44,0xd192e819d6ef5218) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],45,0xd69906245565a910) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],46,0xf40e35855771202a) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],47,0x106aa07032bbd1b8) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],48,0x19a4c116b8d2d0c8) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],49,0x1e376c085141ab53) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],50,0x2748774cdf8eeb99) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],51,0x34b0bcb5e19b48a8) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],52,0x391c0cb3c5c95a63) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],53,0x4ed8aa4ae3418acb) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],54,0x5b9cca4f7763e373) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],55,0x682e6ff3d6b2b8a3) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],56,0x748f82ee5defb2fc) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],57,0x78a5636f43172f60) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],58,0x84c87814a1f0ab72) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],59,0x8cc702081a6439ec) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],60,0x90befffa23631e28) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],61,0xa4506cebde82bde9) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],62,0xbef9a3f7b2c67915) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],63,0xc67178f2e372532b) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],64,0xca273eceea26619c) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],65,0xd186b8c721c0c207) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],66,0xeada7dd6cde0eb1e) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],67,0xf57d4f7fee6ed178) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],68,0x06f067aa72176fba) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],69,0x0a637dc5a2c898a6) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],70,0x113f9804bef90dae) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],71,0x1b710b35131c471b) + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],72,0x28db77f523047d84) + ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],73,0x32caab7b40c72493) + ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],74,0x3c9ebe0a15c9bebc) + ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],75,0x431d67c49c100d4c) + ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],76,0x4cc5d4becb3e42b6) + ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a) + ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec) + ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817) + + + dig = [] + for i, x in enumerate(sha_info['digest']): + dig.append( (x + ss[i]) & 0xffffffffffffffff ) + sha_info['digest'] = dig + +def sha_init(): + sha_info = new_shaobject() + sha_info['digest'] = [ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179] + sha_info['count_lo'] = 0 + sha_info['count_hi'] = 0 + sha_info['local'] = 0 + sha_info['digestsize'] = 64 + return sha_info + +def sha384_init(sha_info): + sha_info = new_shaobject() + sha_info['digest'] = [ 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4] + sha_info['count_lo'] = 0 + sha_info['count_hi'] = 0 + sha_info['local'] = 0 + sha_info['digestsize'] = 48 + return sha_info + +def sha_update(sha_info, buffer): + count = len(buffer) + buffer_idx = 0 + clo = (sha_info['count_lo'] + (count << 3)) & 0xffffffff + if clo < sha_info['count_lo']: + sha_info['count_hi'] += 1 + sha_info['count_lo'] = clo + + sha_info['count_hi'] += (count >> 29) + + if sha_info['local']: + i = SHA_BLOCKSIZE - sha_info['local'] + if i > count: + i = count + + # copy buffer + for x in enumerate(buffer[buffer_idx:buffer_idx+i]): + sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0] + + count -= i + buffer_idx += i + + sha_info['local'] += i + if sha_info['local'] == SHA_BLOCKSIZE: + sha_transform(sha_info) + sha_info['local'] = 0 + else: + return + + while count >= SHA_BLOCKSIZE: + # copy buffer + sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]] + count -= SHA_BLOCKSIZE + buffer_idx += SHA_BLOCKSIZE + sha_transform(sha_info) + + + # copy buffer + pos = sha_info['local'] + sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]] + sha_info['local'] = count + +def sha_final(sha_info): + lo_bit_count = sha_info['count_lo'] + hi_bit_count = sha_info['count_hi'] + count = (lo_bit_count >> 3) & 0x7f + sha_info['data'][count] = 0x80; + count += 1 + if count > SHA_BLOCKSIZE - 16: + # zero the bytes in data after the count + sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) + sha_transform(sha_info) + # zero bytes in data + sha_info['data'] = [0] * SHA_BLOCKSIZE + else: + sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) + + sha_info['data'][112] = 0; + sha_info['data'][113] = 0; + sha_info['data'][114] = 0; + sha_info['data'][115] = 0; + sha_info['data'][116] = 0; + sha_info['data'][117] = 0; + sha_info['data'][118] = 0; + sha_info['data'][119] = 0; + + sha_info['data'][120] = (hi_bit_count >> 24) & 0xff + sha_info['data'][121] = (hi_bit_count >> 16) & 0xff + sha_info['data'][122] = (hi_bit_count >> 8) & 0xff + sha_info['data'][123] = (hi_bit_count >> 0) & 0xff + sha_info['data'][124] = (lo_bit_count >> 24) & 0xff + sha_info['data'][125] = (lo_bit_count >> 16) & 0xff + sha_info['data'][126] = (lo_bit_count >> 8) & 0xff + sha_info['data'][127] = (lo_bit_count >> 0) & 0xff + + sha_transform(sha_info) + + dig = [] + for i in sha_info['digest']: + dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) + return ''.join([chr(i) for i in dig]) + +class sha512: + def __init__(self, s=None): + self._sha = sha_init() + if s: + sha_update(self._sha, s) + + def update(self, s): + sha_update(self._sha, s) + + def digest(self): + return sha_final(self._sha.copy())[:self._sha['digestsize']] + + def hexdigest(self): + return ''.join(['%.2x' % ord(i) for i in self.digest()]) + +class sha384(sha512): + def __init__(self, s=None): + self._sha = sha384_init() + if s: + sha_update(self._sha, s) + +def test(): + a_str = "just a test string" + + assert _sha512.sha512().hexdigest() == sha512().hexdigest() + assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest() + assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest() + + s = sha512(a_str) + s.update(a_str) + assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest() + +if __name__ == "__main__": + test() From afa at codespeak.net Tue Mar 10 13:22:53 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 13:22:53 +0100 (CET) Subject: [pypy-svn] r62809 - pypy/trunk/pypy/lib Message-ID: <20090310122253.C0D6D1684E7@codespeak.net> Author: afa Date: Tue Mar 10 13:22:51 2009 New Revision: 62809 Added: pypy/trunk/pypy/lib/_sha512.py - copied, changed from r62808, pypy/dist/pypy/lib/_sha512.py Modified: pypy/trunk/pypy/lib/hashlib.py Log: Merge the pure-python _sha512 module provided by hruske. Thanks! test_hashlib now passes on Windows. Copied: pypy/trunk/pypy/lib/_sha512.py (from r62808, pypy/dist/pypy/lib/_sha512.py) ============================================================================== --- pypy/dist/pypy/lib/_sha512.py (original) +++ pypy/trunk/pypy/lib/_sha512.py Tue Mar 10 13:22:51 2009 @@ -143,7 +143,7 @@ sha_info['digestsize'] = 64 return sha_info -def sha384_init(sha_info): +def sha384_init(): sha_info = new_shaobject() sha_info['digest'] = [ 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4] sha_info['count_lo'] = 0 Modified: pypy/trunk/pypy/lib/hashlib.py ============================================================================== --- pypy/trunk/pypy/lib/hashlib.py (original) +++ pypy/trunk/pypy/lib/hashlib.py Tue Mar 10 13:22:51 2009 @@ -68,6 +68,12 @@ elif name in ('SHA224', 'sha224'): import _sha256 return _sha256.sha224 + elif name in ('SHA512', 'sha512'): + import _sha512 + return _sha512.sha512 + elif name in ('SHA384', 'sha384'): + import _sha512 + return _sha512.sha384 raise ValueError, "unsupported hash type" def __hash_new(name, string=''): @@ -118,5 +124,5 @@ sha1 = __get_builtin_constructor('sha1') sha224 = __get_builtin_constructor('sha224') sha256 = __get_builtin_constructor('sha256') - #sha384 = __get_builtin_constructor('sha384') - #sha512 = __get_builtin_constructor('sha512') + sha384 = __get_builtin_constructor('sha384') + sha512 = __get_builtin_constructor('sha512') From afa at codespeak.net Tue Mar 10 15:14:17 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 15:14:17 +0100 (CET) Subject: [pypy-svn] r62810 - pypy/trunk/pypy/rpython/module/test Message-ID: <20090310141417.AE6901684F2@codespeak.net> Author: afa Date: Tue Mar 10 15:14:14 2009 New Revision: 62810 Modified: pypy/trunk/pypy/rpython/module/test/test_posix.py Log: (again) fix an os.stat test. Modified: pypy/trunk/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/trunk/pypy/rpython/module/test/test_posix.py (original) +++ pypy/trunk/pypy/rpython/module/test/test_posix.py Tue Mar 10 15:14:14 2009 @@ -31,7 +31,7 @@ func = self.interpret(fo,[fi]) stat = os.fstat(fi) for i in range(len(stat)): - assert getattr(func, 'item%d' % i) == stat[i] + assert long(getattr(func, 'item%d' % i)) == stat[i] def test_times(self): From cfbolz at codespeak.net Tue Mar 10 16:00:54 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 10 Mar 2009 16:00:54 +0100 (CET) Subject: [pypy-svn] r62811 - in pypy/branch/speedup-globals/pypy/objspace/std: . test Message-ID: <20090310150054.1EFBC16804C@codespeak.net> Author: cfbolz Date: Tue Mar 10 16:00:52 2009 New Revision: 62811 Added: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py (contents, props changed) pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py (contents, props changed) Modified: pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py pypy/branch/speedup-globals/pypy/objspace/std/objspace.py pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py Log: Actually use the cell-dict stuff to cache global lookups in frames. Added: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py ============================================================================== --- (empty file) +++ pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Tue Mar 10 16:00:52 2009 @@ -0,0 +1,247 @@ +from pypy.objspace.std.dictmultiobject import DictImplementation +from pypy.objspace.std.dictmultiobject import IteratorImplementation +from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash + +class ModuleCell(object): + def __init__(self, valid=True): + self.w_value = None + self.valid = valid + + def invalidate(self): + self.w_value = None + self.valid = False + + def __repr__(self): + if self.valid: + return "" % (self.w_value, ) + else: + return "" + +class ModuleDictImplementation(DictImplementation): + def __init__(self, space): + self.space = space + self.content = {} + self.unshadowed_builtins = {} + + def getcell(self, key, make_new=True): + try: + return self.content[key] + except KeyError: + if not make_new: + raise + result = self.content[key] = ModuleCell() + return result + + def add_unshadowed_builtin(self, name, builtin_impl): + assert isinstance(builtin_impl, ModuleDictImplementation) + self.unshadowed_builtins[name] = builtin_impl + + def invalidate_unshadowed_builtin(self, name): + impl = self.unshadowed_builtins[name] + cell = impl.content[name] + w_value = cell.w_value + cell.invalidate() + cell = impl.content[name] = ModuleCell() + cell.w_value = w_value + + def setitem(self, w_key, w_value): + space = self.space + if space.is_w(space.type(w_key), space.w_str): + return self.setitem_str(w_key, w_value) + else: + return self._as_rdict().setitem(w_key, w_value) + + def setitem_str(self, w_key, w_value, shadows_type=True): + name = self.space.str_w(w_key) + self.getcell(name).w_value = w_value + + if name in self.unshadowed_builtins: + self.invalidate_unshadowed_builtin(name) + del self.unshadowed_builtins[name] + + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + cell = self.getcell(key, False) + cell.invalidate() + del self.content[key] + return self + elif _is_sane_hash(space, w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def length(self): + return len(self.content) + + def get(self, w_lookup): + space = self.space + w_lookup_type = space.type(w_lookup) + if space.is_w(w_lookup_type, space.w_str): + try: + return self.getcell(space.str_w(w_lookup), False).w_value + except KeyError: + return None + elif _is_sane_hash(space, w_lookup_type): + return None + else: + return self._as_rdict().get(w_lookup) + + def iteritems(self): + return ModuleDictItemIteratorImplementation(self.space, self) + + def iterkeys(self): + return ModuleDictKeyIteratorImplementation(self.space, self) + + def itervalues(self): + return ModuleDictValueIteratorImplementation(self.space, self) + + def keys(self): + space = self.space + return [space.wrap(key) for key in self.content.iterkeys()] + + def values(self): + return [cell.w_value for cell in self.content.itervalues()] + + def items(self): + space = self.space + return [space.newtuple([space.wrap(key), cell.w_value]) + for (key, cell) in self.content.iteritems()] + + def _as_rdict(self): + newimpl = self.space.DefaultDictImpl(self.space) + for k, cell in self.content.iteritems(): + newimpl.setitem(self.space.wrap(k), cell.w_value) + cell.invalidate() + for k in self.unshadowed_builtins: + self.invalidate_unshadowed_builtin(k) + return newimpl + +# grrrrr. just a copy-paste from StrKeyIteratorImplementation in dictmultiobject +class ModuleDictKeyIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iterkeys() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key in self.iterator: + return self.space.wrap(key) + else: + return None + +class ModuleDictValueIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.itervalues() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for cell in self.iterator: + return cell.w_value + else: + return None + +class ModuleDictItemIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iteritems() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key, cell in self.iterator: + return self.space.newtuple([self.space.wrap(key), cell.w_value]) + else: + return None + + + + + + + +class State(object): + def __init__(self, space): + self.space = space + self.code_to_index = {} + self.caches = [] + self.dictimpls = [] + self.invalidcell = ModuleCell(valid=False) + self.always_invalid_cache = [] + + def getcache(self, code, w_globals): + implementation = getimplementation(w_globals) + if code in self.code_to_index: + index = self.code_to_index[code] + if self.dictimpls[index] is implementation: + return self.caches[index] + in_dict = True + else: + in_dict = False + if not isinstance(implementation, ModuleDictImplementation): + missing_length = max(len(code.co_names_w) - len(self.always_invalid_cache), 0) + self.always_invalid_cache.extend([self.invalidcell] * missing_length) + return self.always_invalid_cache + if not in_dict: + index = len(self.code_to_index) + self.code_to_index[code] = index + self.dictimpls.append(None) + self.caches.append(None) + cache = [self.invalidcell] * len(code.co_names_w) + self.caches[index] = cache + self.dictimpls[index] = implementation + return cache + + + +def get_global_cache(space, code, w_globals): + from pypy.interpreter.pycode import PyCode + if not isinstance(code, PyCode): + return [] + cache = space.fromcache(State).getcache(code, w_globals) + return cache + +def getimplementation(w_dict): + if type(w_dict) is W_DictMultiObject: + return w_dict.implementation + else: + return None + +def LOAD_GLOBAL(f, nameindex, *ignored): + cell = f.cache_for_globals[nameindex] + if cell.valid: + result = cell.w_value + else: + # slow path + result = load_global_fill_cache(f, nameindex) + f.pushvalue(result) +LOAD_GLOBAL._always_inline_ = True + +def find_cell_from_dict(implementation, name): + if isinstance(implementation, ModuleDictImplementation): + try: + return implementation.getcell(name, False) + except KeyError: + return None + return None + +def load_global_fill_cache(f, nameindex): + name = f.space.str_w(f.getname_w(nameindex)) + implementation = getimplementation(f.w_globals) + if isinstance(implementation, ModuleDictImplementation): + cell = find_cell_from_dict(implementation, name) + if cell is None: + builtin_impl = getimplementation(f.get_builtin().getdict()) + cell = find_cell_from_dict(builtin_impl, name) + if cell is not None: + implementation.add_unshadowed_builtin(name, builtin_impl) + + if cell is not None: + f.cache_for_globals[nameindex] = cell + return cell.w_value + return f._load_global(f.getname_w(nameindex)) +load_global_fill_cache._dont_inline_ = True Modified: pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py Tue Mar 10 16:00:52 2009 @@ -865,135 +865,6 @@ else: return None -class ModuleCell(object): - def __init__(self): - self.w_value = None - self.valid = True - - def invalidate(self): - self.w_value = None - self.valid = False - -class ModuleDictImplementation(DictImplementation): - def __init__(self, space): - self.space = space - self.content = {} - - def getcell(self, key, make_new=True): - try: - return self.content[key] - except KeyError: - if not make_new: - raise - result = self.content[key] = ModuleCell() - return result - - def setitem(self, w_key, w_value): - space = self.space - if space.is_w(space.type(w_key), space.w_str): - return self.setitem_str(w_key, w_value) - else: - return self._as_rdict().setitem(w_key, w_value) - - def setitem_str(self, w_key, w_value, shadows_type=True): - self.getcell(self.space.str_w(w_key)).w_value = w_value - return self - - def delitem(self, w_key): - space = self.space - w_key_type = space.type(w_key) - if space.is_w(w_key_type, space.w_str): - key = space.str_w(w_key) - cell = self.getcell(key, False) - cell.invalidate() - del self.content[key] - return self - elif _is_sane_hash(space, w_key_type): - raise KeyError - else: - return self._as_rdict().delitem(w_key) - - def length(self): - return len(self.content) - - def get(self, w_lookup): - space = self.space - w_lookup_type = space.type(w_lookup) - if space.is_w(w_lookup_type, space.w_str): - try: - return self.getcell(space.str_w(w_lookup), False).w_value - except KeyError: - return None - elif _is_sane_hash(space, w_lookup_type): - return None - else: - return self._as_rdict().get(w_lookup) - - def iteritems(self): - return ModuleDictItemIteratorImplementation(self.space, self) - - def iterkeys(self): - return ModuleDictKeyIteratorImplementation(self.space, self) - - def itervalues(self): - return ModuleDictValueIteratorImplementation(self.space, self) - - def keys(self): - space = self.space - return [space.wrap(key) for key in self.content.iterkeys()] - - def values(self): - return [cell.w_value for cell in self.content.itervalues()] - - def items(self): - space = self.space - return [space.newtuple([space.wrap(key), cell.w_value]) - for (key, cell) in self.content.iteritems()] - - def _as_rdict(self): - newimpl = self.space.DefaultDictImpl(self.space) - for k, cell in self.content.iteritems(): - newimpl.setitem(self.space.wrap(k), cell.w_value) - cell.invalidate() - return newimpl - -# grrrrr. just a copy-paste from StrKeyIteratorImplementation above -class ModuleDictKeyIteratorImplementation(IteratorImplementation): - def __init__(self, space, dictimplementation): - IteratorImplementation.__init__(self, space, dictimplementation) - self.iterator = dictimplementation.content.iterkeys() - - def next_entry(self): - # note that this 'for' loop only runs once, at most - for key in self.iterator: - return self.space.wrap(key) - else: - return None - -class ModuleDictValueIteratorImplementation(IteratorImplementation): - def __init__(self, space, dictimplementation): - IteratorImplementation.__init__(self, space, dictimplementation) - self.iterator = dictimplementation.content.itervalues() - - def next_entry(self): - # note that this 'for' loop only runs once, at most - for cell in self.iterator: - return cell.w_value - else: - return None - -class ModuleDictItemIteratorImplementation(IteratorImplementation): - def __init__(self, space, dictimplementation): - IteratorImplementation.__init__(self, space, dictimplementation) - self.iterator = dictimplementation.content.iteritems() - - def next_entry(self): - # note that this 'for' loop only runs once, at most - for key, cell in self.iterator: - return self.space.newtuple([self.space.wrap(key), cell.w_value]) - else: - return None - import time, py class DictInfo(object): @@ -1168,6 +1039,7 @@ def __init__(w_self, space, wary=False, sharing=False, module=False): if space.config.objspace.std.withcelldict and wary: + from pypy.objspace.std.celldict import ModuleDictImplementation w_self.implementation = ModuleDictImplementation(space) elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: w_self.implementation = WaryDictImplementation(space) Modified: pypy/branch/speedup-globals/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/objspace.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/objspace.py Tue Mar 10 16:00:52 2009 @@ -72,7 +72,16 @@ # Import all the object types and implementations self.model = StdTypeModel(self.config) + from pypy.objspace.std.celldict import get_global_cache + class StdObjSpaceFrame(pyframe.PyFrame): + if self.config.objspace.std.withcelldict: + def __init__(self, space, code, w_globals, closure): + pyframe.PyFrame.__init__(self, space, code, w_globals, closure) + self.cache_for_globals = get_global_cache(space, code, w_globals) + + from pypy.objspace.std.celldict import LOAD_GLOBAL + if self.config.objspace.std.optimized_int_add: if self.config.objspace.std.withsmallint: def BINARY_ADD(f, oparg, *ignored): Added: pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py ============================================================================== --- (empty file) +++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py Tue Mar 10 16:00:52 2009 @@ -0,0 +1,226 @@ +from pypy.conftest import gettestobjspace +from pypy.objspace.std.celldict import get_global_cache, ModuleCell, ModuleDictImplementation +from pypy.interpreter import gateway + +# this file tests mostly the effects of caching global lookup. The dict +# implementation itself is tested in test_dictmultiobject.py + + +class AppTestCellDict(object): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withcelldict": True}) + cls.w_impl_used = cls.space.appexec([], """(): + import __pypy__ + def impl_used(obj): + assert "ModuleDictImplementation" in __pypy__.internal_repr(obj) + return impl_used + """) + def is_in_cache(space, w_code, w_globals, w_name): + name = space.str_w(w_name) + cache = get_global_cache(space, w_code, w_globals) + index = [space.str_w(w_n) for w_n in w_code.co_names_w].index(name) + return space.wrap(cache[index].valid) + is_in_cache = gateway.interp2app(is_in_cache) + cls.w_is_in_cache = cls.space.wrap(is_in_cache) + stored_builtins = [] + def rescue_builtins(space): + w_dict = space.builtin.getdict() + content = {} + for key, cell in w_dict.implementation.content.iteritems(): + newcell = ModuleCell() + newcell.w_value = cell.w_value + content[key] = newcell + stored_builtins.append(content) + rescue_builtins = gateway.interp2app(rescue_builtins) + cls.w_rescue_builtins = cls.space.wrap(rescue_builtins) + def restore_builtins(space): + w_dict = space.builtin.getdict() + if not isinstance(w_dict.implementation, ModuleDictImplementation): + w_dict.implementation = ModuleDictImplementation(space) + w_dict.implementation.content = stored_builtins.pop() + restore_builtins = gateway.interp2app(restore_builtins) + cls.w_restore_builtins = cls.space.wrap(restore_builtins) + + def test_same_code_in_different_modules(self): + import sys + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + mod2 = type(sys)("abc") + self.impl_used(mod2.__dict__) + glob2 = mod2.__dict__ + def f(): + return x + 1 + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = 1 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + mod1.x = 2 + assert f1() == 3 + assert self.is_in_cache(code, glob1, "x") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "x") + f2 = type(f)(code, glob2) + mod2.x = 5 + assert not self.is_in_cache(code, glob2, "x") + assert f2() == 6 + assert self.is_in_cache(code, glob2, "x") + assert f2() == 6 + assert self.is_in_cache(code, glob2, "x") + mod2.x = 7 + assert f2() == 8 + assert self.is_in_cache(code, glob2, "x") + assert f2() == 8 + assert self.is_in_cache(code, glob2, "x") + + def test_override_builtins(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + return len(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 0 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + assert f1() == 0 + mod1.x.append(1) + assert f1() == 1 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + mod1.len = lambda x: 15 + assert not self.is_in_cache(code, glob1, "len") + mod1.x.append(1) + assert f1() == 15 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 15 + assert self.is_in_cache(code, glob1, "len") + del mod1.len + mod1.x.append(1) + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "len") + orig_len = __builtins__.len + try: + __builtins__.len = lambda x: 12 + mod1.x.append(1) + assert self.is_in_cache(code, glob1, "len") + assert f1() == 12 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 12 + assert self.is_in_cache(code, glob1, "len") + finally: + __builtins__.len = orig_len + + def test_generator(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + yield 1 + yield x + yield len(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + gen = f1() + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v == 1 + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v is mod1.x + assert not self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v == 0 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + + def test_degenerate_to_rdict(self): + import sys + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + def f(): + return x + 1 + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = 1 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + glob1[1] = 2 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert not self.is_in_cache(code, glob1, "x") + + def test_degenerate_builtin_to_rdict(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + def f(): + return len(x) + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = [1, 2] + assert not self.is_in_cache(code, glob1, "x") + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + assert self.is_in_cache(code, glob1, "len") + self.rescue_builtins() + try: + __builtin__.__dict__[1] = 2 + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 2 + assert not self.is_in_cache(code, glob1, "len") + finally: + self.restore_builtins() + + def test_mapping_as_locals(self): + import sys + if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'): + skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements") + class M(object): + def __getitem__(self, key): + return key + def __setitem__(self, key, value): + self.result[key] = value + m = M() + m.result = {} + exec "x=m" in {}, m + assert m.result == {'x': 'm'} + exec "y=n" in m # NOTE: this doesn't work in CPython 2.4 + assert m.result == {'x': 'm', 'y': 'n'} + + def test_subclass_of_dict_as_locals(self): + import sys + if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'): + skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements") + class M(dict): + def __getitem__(self, key): + return key + def __setitem__(self, key, value): + dict.__setitem__(self, key, value) + m = M() + exec "x=m" in {}, m + assert m == {'x': 'm'} + exec "y=n" in m # NOTE: this doesn't work in CPython 2.4 + assert m == {'x': 'm', 'y': 'n'} + Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py Tue Mar 10 16:00:52 2009 @@ -2,8 +2,9 @@ from pypy.objspace.std.dictmultiobject import \ W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \ EmptyDictImplementation, RDictImplementation, StrDictImplementation, \ - SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation, \ - ModuleDictImplementation + SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation + +from pypy.objspace.std.celldict import ModuleDictImplementation from pypy.conftest import gettestobjspace from pypy.objspace.std.test import test_dictobject From fijal at codespeak.net Tue Mar 10 16:13:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 16:13:01 +0100 (CET) Subject: [pypy-svn] r62813 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090310151301.845491684D8@codespeak.net> Author: fijal Date: Tue Mar 10 16:13:00 2009 New Revision: 62813 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: this is hopefully gone by now Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Mar 10 16:13:00 2009 @@ -1032,11 +1032,7 @@ for vtable in storage.allocations: if metainterp.cpu.translate_support_code: vtable_addr = metainterp.cpu.cast_int_to_adr(vtable) - try: - size = metainterp.class_sizes[vtable_addr] - except KeyError: - print vtable_addr, vtable, "CRAAAAAAAASH" - raise + size = metainterp.class_sizes[vtable_addr] else: size = metainterp.class_sizes[vtable] vtablebox = ConstInt(vtable) From cfbolz at codespeak.net Tue Mar 10 16:34:18 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 10 Mar 2009 16:34:18 +0100 (CET) Subject: [pypy-svn] r62816 - pypy/branch/speedup-globals/pypy/objspace/std Message-ID: <20090310153418.567EB168097@codespeak.net> Author: cfbolz Date: Tue Mar 10 16:34:17 2009 New Revision: 62816 Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Log: help flow space Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/celldict.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Tue Mar 10 16:34:17 2009 @@ -175,6 +175,7 @@ def getcache(self, code, w_globals): implementation = getimplementation(w_globals) + index = -1 # for flow space if code in self.code_to_index: index = self.code_to_index[code] if self.dictimpls[index] is implementation: From afa at codespeak.net Tue Mar 10 16:53:18 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Mar 2009 16:53:18 +0100 (CET) Subject: [pypy-svn] r62817 - in pypy/trunk/pypy: rlib rpython/module rpython/module/test Message-ID: <20090310155318.509EC168515@codespeak.net> Author: afa Date: Tue Mar 10 16:53:17 2009 New Revision: 62817 Added: pypy/trunk/pypy/rpython/module/test/test_ll_os_stat.py Modified: pypy/trunk/pypy/rlib/rwin32.py pypy/trunk/pypy/rpython/module/ll_os_stat.py Log: The llinterpreter has trouble when passing strings, but we can still execute the fake implementation directly. and While we're at it, fix one test in test_os.py, when os.stat is applied to a locked file: CPython falls back to reading the directory entry. Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Tue Mar 10 16:53:17 2009 @@ -64,6 +64,7 @@ HANDLE = rffi.ULONG LPHANDLE = rffi.CArrayPtr(HANDLE) HMODULE = HANDLE + INVALID_HANDLE_VALUE = rffi.cast(HANDLE, -1) PFILETIME = rffi.CArrayPtr(FILETIME) GetLastError = winexternal('GetLastError', [], DWORD) Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Tue Mar 10 16:53:17 2009 @@ -309,6 +309,8 @@ 'FILE_ATTRIBUTE_DIRECTORY') FILE_ATTRIBUTE_READONLY = platform.ConstantInteger( 'FILE_ATTRIBUTE_READONLY') + ERROR_SHARING_VIOLATION = platform.ConstantInteger( + 'ERROR_SHARING_VIOLATION') _S_IFDIR = platform.ConstantInteger('_S_IFDIR') _S_IFREG = platform.ConstantInteger('_S_IFREG') @@ -333,6 +335,16 @@ ('ftLastAccessTime', rwin32.FILETIME), ('ftLastWriteTime', rwin32.FILETIME)]) + WIN32_FIND_DATA = platform.Struct( + 'WIN32_FIND_DATAA', + # Only interesting fields + [('dwFileAttributes', rwin32.DWORD), + ('nFileSizeHigh', rwin32.DWORD), + ('nFileSizeLow', rwin32.DWORD), + ('ftCreationTime', rwin32.FILETIME), + ('ftLastAccessTime', rwin32.FILETIME), + ('ftLastWriteTime', rwin32.FILETIME)]) + globals().update(platform.configure(CConfig)) GET_FILEEX_INFO_LEVELS = rffi.ULONG # an enumeration @@ -349,6 +361,18 @@ rwin32.BOOL, calling_conv='win') + FindFirstFile = rffi.llexternal( + 'FindFirstFileA', + [rffi.CCHARP, lltype.Ptr(WIN32_FIND_DATA)], + rwin32.HANDLE, + calling_conv='win') + + FindClose = rffi.llexternal( + 'FindClose', + [rwin32.HANDLE], + rwin32.BOOL, + calling_conv='win') + def attributes_to_mode(attributes): m = 0 if attributes & FILE_ATTRIBUTE_DIRECTORY: @@ -384,9 +408,9 @@ result = (st_mode, 0, 0, 0, 0, 0, st_size, - atime + atime_ns * 1e-9, - mtime + mtime_ns * 1e-9, - ctime + ctime_ns * 1e-9) + float(atime) + atime_ns * 1e-9, + float(mtime) + mtime_ns * 1e-9, + float(ctime) + ctime_ns * 1e-9) return make_stat_result(result) @@ -411,14 +435,33 @@ return make_stat_result(result) + def attributes_from_dir(l_path, data): + filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw') + hFindFile = FindFirstFile(l_path, filedata) + if hFindFile == rwin32.INVALID_HANDLE_VALUE: + return 0 + FindClose(hFindFile) + data.c_dwFileAttributes = filedata.c_dwFileAttributes + rffi.structcopy(data.c_ftCreationTime, filedata.c_ftCreationTime) + rffi.structcopy(data.c_ftLastAccessTime, filedata.c_ftLastAccessTime) + rffi.structcopy(data.c_ftLastWriteTime, filedata.c_ftLastWriteTime) + data.c_nFileSizeHigh = filedata.c_nFileSizeHigh + data.c_nFileSizeLow = filedata.c_nFileSizeLow + return 1 + def win32_stat_llimpl(path): data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw') try: l_path = rffi.str2charp(path) res = GetFileAttributesEx(l_path, GetFileExInfoStandard, data) + errcode = rwin32.GetLastError() + if res == 0: + if errcode == ERROR_SHARING_VIOLATION: + res = attributes_from_dir(l_path, data) + errcode = rwin32.GetLastError() rffi.free_charp(l_path) if res == 0: - raise WindowsError(rwin32.GetLastError(), "os_stat failed") + raise WindowsError(errcode, "os_stat failed") return attribute_data_to_stat(data) finally: lltype.free(data, flavor='raw') Added: pypy/trunk/pypy/rpython/module/test/test_ll_os_stat.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/rpython/module/test/test_ll_os_stat.py Tue Mar 10 16:53:17 2009 @@ -0,0 +1,17 @@ +from pypy.rpython.module import ll_os_stat +import sys, os +import py + +class TestWin32Implementation: + def setup_class(cls): + if sys.platform != 'win32': + py.test.skip("win32 specific tests") + + def test_stat(self): + stat = ll_os_stat.win32_stat_llimpl + def check(f): + assert stat(f).st_mtime == os.stat(f).st_mtime + + check('c:/') + check('c:/temp') + check('c:/pagefile.sys') From fijal at codespeak.net Tue Mar 10 17:28:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 17:28:56 +0100 (CET) Subject: [pypy-svn] r62818 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090310162856.124F8168509@codespeak.net> Author: fijal Date: Tue Mar 10 17:28:55 2009 New Revision: 62818 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Log: a complex logic that preserves parentlinks when passing around pointers to subclasses. A bit obscure, but works. Also I'm not sure about is not vs != in lltype, but it's needed since ctypes objects are not the same Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Tue Mar 10 17:28:55 2009 @@ -25,6 +25,7 @@ _ctypes_cache = {} _eci_cache = {} +_parent_cache = {} def _setup_ctypes_cache(): from pypy.rpython.lltypesystem import rffi @@ -620,6 +621,8 @@ raise NotImplementedError(T) container._ctypes_storage_was_allocated() storage = container._storage + if lltype.parentlink(container)[0] is not None: + _parent_cache[ctypes.addressof(storage)] = lltype.parentlink(container) p = ctypes.pointer(storage) if index: p = ctypes.cast(p, ctypes.c_void_p) @@ -683,6 +686,9 @@ ctypes.cast(cobj, ctypes_instance))) container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) + addr = ctypes.addressof(cobj.contents) + if addr in _parent_cache: + container._setparentstructure(*_parent_cache[addr]) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Tue Mar 10 17:28:55 2009 @@ -1163,7 +1163,7 @@ if parent is None: raise RuntimeError("widening to trash: %r" % self) PARENTTYPE = struc._parent_type - if getattr(parent, PARENTTYPE._names[0]) is not struc: + if getattr(parent, PARENTTYPE._names[0]) != struc: raise InvalidCast(CURTYPE, PTRTYPE) # xxx different exception perhaps? struc = parent u -= 1 From cfbolz at codespeak.net Tue Mar 10 17:54:45 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 10 Mar 2009 17:54:45 +0100 (CET) Subject: [pypy-svn] r62819 - pypy/branch/speedup-globals/pypy/translator/benchmark Message-ID: <20090310165445.57FE41684F5@codespeak.net> Author: cfbolz Date: Tue Mar 10 17:54:44 2009 New Revision: 62819 Modified: pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py Log: fix typo Modified: pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py ============================================================================== --- pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py (original) +++ pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py Tue Mar 10 17:54:44 2009 @@ -65,7 +65,7 @@ def run_pystone(executable='/usr/local/bin/python', n=''): from pypy.tool import autopath distdir = py.path.local(autopath.pypydir).dirpath() - pyston = py.path.local(autopath.libpythondir).join('test', 'pystone.py') + pystone = py.path.local(autopath.libpythondir).join('test', 'pystone.py') txt = run_cmd('"%s" "%s" %s' % (executable, pystone, n)) return get_result(txt, PYSTONE_PATTERN) From fijal at codespeak.net Tue Mar 10 17:55:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 17:55:42 +0100 (CET) Subject: [pypy-svn] r62820 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090310165542.565C01684F5@codespeak.net> Author: fijal Date: Tue Mar 10 17:55:42 2009 New Revision: 62820 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: cast arg to int... Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Tue Mar 10 17:55:42 2009 @@ -457,7 +457,7 @@ elif size == WORD: a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) if not ptr: - a[ofs/WORD + field] = args[2].getint() + a[ofs/WORD + field] = int(args[2].getint()) else: p = args[2].getptr(llmemory.GCREF) a[ofs/WORD + field] = self.cast_gcref_to_int(p) From fijal at codespeak.net Tue Mar 10 17:56:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 17:56:00 +0100 (CET) Subject: [pypy-svn] r62821 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090310165600.81623168512@codespeak.net> Author: fijal Date: Tue Mar 10 17:56:00 2009 New Revision: 62821 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py Log: we can now run this test at least Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py Tue Mar 10 17:56:00 2009 @@ -1,6 +1,5 @@ import py -py.test.skip("Widening to trash error") from pypy.jit.metainterp.test.test_tl import ToyLanguageTests from pypy.jit.backend.x86.test.test_basic import Jit386Mixin From fijal at codespeak.net Tue Mar 10 17:57:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 17:57:21 +0100 (CET) Subject: [pypy-svn] r62822 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090310165721.11E621680A3@codespeak.net> Author: fijal Date: Tue Mar 10 17:57:20 2009 New Revision: 62822 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Log: * Support for bool (a bit) * Support for nested structures with parents (seems not to work perfectly though) Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Tue Mar 10 17:57:20 2009 @@ -622,7 +622,7 @@ container._ctypes_storage_was_allocated() storage = container._storage if lltype.parentlink(container)[0] is not None: - _parent_cache[ctypes.addressof(storage)] = lltype.parentlink(container) + _parent_cache[ctypes.addressof(storage)] = parentchain(container) p = ctypes.pointer(storage) if index: p = ctypes.cast(p, ctypes.c_void_p) @@ -688,7 +688,10 @@ struct_use_ctypes_storage(container, cobj.contents) addr = ctypes.addressof(cobj.contents) if addr in _parent_cache: - container._setparentstructure(*_parent_cache[addr]) + setparentstructure(container, _parent_cache[addr]) + else: + import pdb + pdb.set_trace() elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) @@ -720,6 +723,8 @@ llobj = _lladdress(cobj) elif T is lltype.Char: llobj = chr(cobj) + elif T is lltype.Bool: + llobj = bool(cobj) elif T is lltype.UniChar: llobj = unichr(cobj) elif T is lltype.Signed: @@ -1059,6 +1064,24 @@ return hop.genop('cast_adr_to_int', [adr], resulttype = lltype.Signed) +# ------------------------------------------------------------ + +def parentchain(container): + current = container + links = [] + while True: + link = lltype.parentlink(current) + if link[0] is None: + return links + links.append(link) + current = link[0] + +def setparentstructure(container, chain): + current = container + for elem in chain: + current._setparentstructure(*elem) + current = elem[0] + # ____________________________________________________________ # errno Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Tue Mar 10 17:57:20 2009 @@ -1161,6 +1161,8 @@ while u: parent = struc._parentstructure() if parent is None: + import pdb + pdb.set_trace() raise RuntimeError("widening to trash: %r" % self) PARENTTYPE = struc._parent_type if getattr(parent, PARENTTYPE._names[0]) != struc: From cfbolz at codespeak.net Tue Mar 10 17:57:57 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 10 Mar 2009 17:57:57 +0100 (CET) Subject: [pypy-svn] r62823 - pypy/branch/speedup-globals/pypy/translator/benchmark Message-ID: <20090310165757.4312A16840B@codespeak.net> Author: cfbolz Date: Tue Mar 10 17:57:56 2009 New Revision: 62823 Modified: pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py Log: fix gadfly Modified: pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py ============================================================================== --- pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py (original) +++ pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py Tue Mar 10 17:57:56 2009 @@ -149,6 +149,8 @@ command = 'PYTHONPATH="%s" "%s" "%s"' % (gadfly, executable, testscript) txt = run_cmd(command) lines = [line for line in txt.split('\n') if line.strip()] + if "NOTE" in lines[-1]: + del lines[-1] if lines[-1].strip() != 'OK': raise BenchmarkFailed lastword = lines[-2].split()[-1] From hpk at codespeak.net Tue Mar 10 18:09:47 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 10 Mar 2009 18:09:47 +0100 (CET) Subject: [pypy-svn] r62824 - pypy/extradoc/talk/openbossa2009/pypy-mobile Message-ID: <20090310170947.DECF2168473@codespeak.net> Author: hpk Date: Tue Mar 10 18:09:44 2009 New Revision: 62824 Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/end_of_a_age_by_marikaz.jpg (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/flying_lady_by_marikaz.jpg (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/license-jpg.txt (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/little_red_riding_hood_by_marikaz.jpg (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/mystical_color_statue_by_marikaz.jpg (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/new_color_in_dark_old_city_by_marikaz.jpg (contents, props changed) Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Log: add the pictures and a license file for them. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/end_of_a_age_by_marikaz.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/flying_lady_by_marikaz.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/license-jpg.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/license-jpg.txt Tue Mar 10 18:09:44 2009 @@ -0,0 +1,4 @@ + +the *.jpgs are all copyright marikaz, please +see http://marikaz.deviantart.com/ +licensed under CC 3.0 AN-ND Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/little_red_riding_hood_by_marikaz.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/mystical_color_statue_by_marikaz.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/new_color_in_dark_old_city_by_marikaz.jpg ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt ============================================================================== --- pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Tue Mar 10 18:09:44 2009 @@ -191,15 +191,15 @@ pypy-c measurements on Maemo =============================== -- cross-compiled to Maemo +- PyPy now cross-compiles via Scratchbox -- measurements were done on N810 device +- we measured pypy-c on N810 device - python object sizes, app benchmarks, startup time - base interpreter size, GC pauses, interpretation speed -- see http://codespeak.net/svn/pypy/build/benchmem +- tool see http://codespeak.net/svn/pypy/build/benchmem Python object sizes ======================= From hpk at codespeak.net Tue Mar 10 18:12:10 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 10 Mar 2009 18:12:10 +0100 (CET) Subject: [pypy-svn] r62825 - pypy/extradoc/talk/openbossa2009/pypy-mobile Message-ID: <20090310171210.D7CB1168473@codespeak.net> Author: hpk Date: Tue Mar 10 18:12:09 2009 New Revision: 62825 Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/arch-pypy-basic.png (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/mario.png (contents, props changed) pypy/extradoc/talk/openbossa2009/pypy-mobile/pypy-multitarget.png (contents, props changed) Log: another pictures Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/arch-pypy-basic.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/mario.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/openbossa2009/pypy-mobile/pypy-multitarget.png ============================================================================== Binary file. No diff available. From fijal at codespeak.net Tue Mar 10 19:06:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 19:06:39 +0100 (CET) Subject: [pypy-svn] r62826 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090310180639.6C5801684F5@codespeak.net> Author: fijal Date: Tue Mar 10 19:06:38 2009 New Revision: 62826 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Improve debugging info Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 10 19:06:38 2009 @@ -590,6 +590,9 @@ self.env = argboxes if not we_are_translated(): self.metainterp._debug_history[-1][-1] = argboxes + elif LLDEBUG: + args_s = ", ".join([str(arg.get_()) for arg in argboxes]) + print " (%s)" % args_s #self.starts_with_greens() #assert len(argboxes) == len(self.graph.getargs()) @@ -637,6 +640,8 @@ liveboxes.append(const_if_fail) if box is not None: extraargs = [box] + extraargs + if LLDEBUG: + print " g(%s)" % str(box.get_()) guard_op = self.metainterp.history.record(opnum, extraargs, None) guard_op.liveboxes = liveboxes saved_pc = self.pc @@ -661,6 +666,13 @@ @specialize.arg(1) def execute(self, opnum, argboxes, descr=None): resbox = self.metainterp.execute_and_record(opnum, argboxes, descr) + if LLDEBUG: + args_s = ", ".join([str(arg.get_()) for arg in argboxes]) + if resbox: + print " (%s) -> %s" % (args_s, str(resbox.get_())) + else: + print " (%s) -> void" % (args_s,) + if resbox is not None: self.make_result_box(resbox) @@ -668,6 +680,13 @@ def execute_with_exc(self, opnum, argboxes, descr=None): cpu = self.metainterp.cpu resbox = executor.execute(cpu, opnum, argboxes, descr) + if LLDEBUG: + args_s = ", ".join([str(arg.get_()) for arg in argboxes]) + if resbox: + print " e(%s) -> %s" % (args_s, str(resbox.get_())) + else: + print " e(%s) -> void" % (args_s,) + if not we_are_translated(): self.metainterp._debug_history.append(['call', argboxes[0], argboxes[1:]]) @@ -734,9 +753,8 @@ frame = self.framestack.pop() if not we_are_translated(): self._debug_history.append(['leave', frame.jitcode, None]) - else: - if LLDEBUG: - print "LEAVE %s" % frame.jitcode.name + elif LLDEBUG: + print "LEAVE %s" % frame.jitcode.name if self.framestack: if resultbox is not None: self.framestack[-1].make_result_box(resultbox) From cfbolz at codespeak.net Tue Mar 10 19:07:12 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 10 Mar 2009 19:07:12 +0100 (CET) Subject: [pypy-svn] r62827 - in pypy/branch/speedup-globals/pypy: interpreter objspace/std Message-ID: <20090310180712.DFA03168513@codespeak.net> Author: cfbolz Date: Tue Mar 10 19:07:12 2009 New Revision: 62827 Modified: pypy/branch/speedup-globals/pypy/interpreter/pycode.py pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Log: It turns out that using one additional dict lookup per call negates many of the benefits of this optimization. Therefore, attach the cache to the code object directly. Modified: pypy/branch/speedup-globals/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/speedup-globals/pypy/interpreter/pycode.py (original) +++ pypy/branch/speedup-globals/pypy/interpreter/pycode.py Tue Mar 10 19:07:12 2009 @@ -111,6 +111,10 @@ self._compute_flatcall() + if space.config.objspace.std.withcelldict: + from pypy.objspace.std.celldict import init_code + init_code(self) + co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/celldict.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Tue Mar 10 19:07:12 2009 @@ -167,44 +167,46 @@ class State(object): def __init__(self, space): self.space = space - self.code_to_index = {} - self.caches = [] - self.dictimpls = [] self.invalidcell = ModuleCell(valid=False) self.always_invalid_cache = [] + self.neverused_dictimpl = ModuleDictImplementation(space) - def getcache(self, code, w_globals): +class GlobalCacheHolder(object): + def __init__(self, space): + self.cache = None + state = space.fromcache(State) + self.dictimpl = state.neverused_dictimpl + + def getcache(self, space, code, w_globals): implementation = getimplementation(w_globals) - index = -1 # for flow space - if code in self.code_to_index: - index = self.code_to_index[code] - if self.dictimpls[index] is implementation: - return self.caches[index] - in_dict = True - else: - in_dict = False + if self.dictimpl is implementation: + return self.cache + return self.getcache_slow(space, code, w_globals, implementation) + getcache._always_inline_ = True + + def getcache_slow(self, space, code, w_globals, implementation): + state = space.fromcache(State) if not isinstance(implementation, ModuleDictImplementation): - missing_length = max(len(code.co_names_w) - len(self.always_invalid_cache), 0) - self.always_invalid_cache.extend([self.invalidcell] * missing_length) - return self.always_invalid_cache - if not in_dict: - index = len(self.code_to_index) - self.code_to_index[code] = index - self.dictimpls.append(None) - self.caches.append(None) - cache = [self.invalidcell] * len(code.co_names_w) - self.caches[index] = cache - self.dictimpls[index] = implementation + missing_length = max(len(code.co_names_w) - len(state.always_invalid_cache), 0) + state.always_invalid_cache.extend([state.invalidcell] * missing_length) + cache = state.always_invalid_cache + else: + cache = [state.invalidcell] * len(code.co_names_w) + self.cache = cache + self.dictimpl = implementation return cache + getcache_slow._dont_inline_ = True +def init_code(code): + code.globalcacheholder = GlobalCacheHolder(code.space) def get_global_cache(space, code, w_globals): from pypy.interpreter.pycode import PyCode if not isinstance(code, PyCode): return [] - cache = space.fromcache(State).getcache(code, w_globals) - return cache + holder = code.globalcacheholder + return holder.getcache(space, code, w_globals) def getimplementation(w_dict): if type(w_dict) is W_DictMultiObject: From fijal at codespeak.net Tue Mar 10 19:38:30 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 19:38:30 +0100 (CET) Subject: [pypy-svn] r62828 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090310183830.9AE1A1684CB@codespeak.net> Author: fijal Date: Tue Mar 10 19:38:28 2009 New Revision: 62828 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: shave shave shave. make debug prints a bit more informative and fix things when running on top of x86 backend untranslated (symbolics) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Tue Mar 10 19:38:28 2009 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic +from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic,\ + ComputedIntSymbolic from pypy.rlib.rarithmetic import intmask from pypy.tool.uid import uid from pypy.conftest import option @@ -144,13 +145,15 @@ nonconstbox = clonebox def getint(self): + if isinstance(self.value, ComputedIntSymbolic): + return self.value.compute_fn() return self.value def getaddr(self, cpu): return cpu.cast_int_to_adr(self.value) def get_(self): - return self.value + return self.getint() def equals(self, other): return self.value == other.getint() @@ -271,10 +274,12 @@ return ConstInt(self.value) def getint(self): + if isinstance(self.value, ComputedIntSymbolic): + return self.value.compute_fn() return self.value def get_(self): - return self.value + return self.getint() def _getrepr_(self): return self.value Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 10 19:38:28 2009 @@ -10,7 +10,7 @@ from pypy.jit.metainterp import history, support from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr, Box, BoxInt, BoxPtr, Options) -from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) @@ -179,6 +179,8 @@ def make_result_box(self, box): assert isinstance(box, Box) or isinstance(box, Const) + if LLDEBUG: + print " => %s" % (box.get_(),) self.env.append(box) ## def starts_with_greens(self): @@ -590,7 +592,7 @@ self.env = argboxes if not we_are_translated(): self.metainterp._debug_history[-1][-1] = argboxes - elif LLDEBUG: + if LLDEBUG: args_s = ", ".join([str(arg.get_()) for arg in argboxes]) print " (%s)" % args_s #self.starts_with_greens() @@ -617,7 +619,11 @@ #print self.metainterp.opcode_names[op] self.pc = pc + 1 if LLDEBUG: - print "EXECUTE %d %d" % (pc, op) + try: + name = opname[op] + except KeyError: + name = "<%d>" % op + print "EXECUTE %d %s" % (pc, name) stop = self.metainterp.opcode_implementations[op](self, pc) #self.metainterp.most_recent_mp = None if stop: @@ -641,7 +647,8 @@ if box is not None: extraargs = [box] + extraargs if LLDEBUG: - print " g(%s)" % str(box.get_()) + if box is not None: + print " g(%s)" % str(box.get_()) guard_op = self.metainterp.history.record(opnum, extraargs, None) guard_op.liveboxes = liveboxes saved_pc = self.pc @@ -690,7 +697,7 @@ if not we_are_translated(): self.metainterp._debug_history.append(['call', argboxes[0], argboxes[1:]]) - elif LLDEBUG: + if LLDEBUG: print "CALL %d" % argboxes[0].getint() # record the operation in the history self.metainterp.history.record(opnum, argboxes, resbox, descr) @@ -743,7 +750,7 @@ self._recompute_class_sizes() if not we_are_translated(): self._debug_history.append(['enter', jitcode, None]) - elif LLDEBUG: + if LLDEBUG: print "ENTER %s" % jitcode.name f = MIFrame(self, jitcode) self.framestack.append(f) @@ -753,7 +760,7 @@ frame = self.framestack.pop() if not we_are_translated(): self._debug_history.append(['leave', frame.jitcode, None]) - elif LLDEBUG: + if LLDEBUG: print "LEAVE %s" % frame.jitcode.name if self.framestack: if resultbox is not None: @@ -773,7 +780,7 @@ return True if not we_are_translated(): self._debug_history.append(['leave_exc', frame.jitcode, None]) - elif LLDEBUG: + if LLDEBUG: print "LEAVE_EXC %s" % frame.jitcode.name self.framestack.pop() raise self.ExitFrameWithException(exceptionbox, excvaluebox) @@ -1003,7 +1010,7 @@ def rebuild_state_after_failure(self, key, newboxes): if not we_are_translated(): self._debug_history.append(['guard_failure', None, None]) - elif LLDEBUG: + if LLDEBUG: print "GUARD_FAILURE" self.framestack = [] nbindex = 0 From fijal at codespeak.net Tue Mar 10 19:50:41 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 10 Mar 2009 19:50:41 +0100 (CET) Subject: [pypy-svn] r62829 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090310185041.06FED1684F4@codespeak.net> Author: fijal Date: Tue Mar 10 19:50:40 2009 New Revision: 62829 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: yet another level of hacks to work on top of llinterp Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Tue Mar 10 19:50:40 2009 @@ -219,6 +219,10 @@ return llmemory.cast_ptr_to_adr(self.value) def equals(self, other): + if not we_are_translated(): + from pypy.rpython.lltypesystem import ll2ctypes + if isinstance(other.getptr_base(), ll2ctypes._llgcref): + return other.getptr_base() == self.value return self.value == other.getptr_base() _getrepr_ = repr_pointer From cfbolz at codespeak.net Tue Mar 10 20:38:31 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 10 Mar 2009 20:38:31 +0100 (CET) Subject: [pypy-svn] r62830 - pypy/branch/speedup-globals/pypy/translator/microbench Message-ID: <20090310193831.002081684EB@codespeak.net> Author: cfbolz Date: Tue Mar 10 20:38:30 2009 New Revision: 62830 Modified: pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py Log: two more microbenchmarks Modified: pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py ============================================================================== --- pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py (original) +++ pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py Tue Mar 10 20:38:30 2009 @@ -201,3 +201,15 @@ y = y + 1 c += 1 +def test_count_with_True(): + x = 0 + n = N + while x < n: + x = x + True + +increment = 1 +def test_count_with_global_increment(): + x = 0 + n = N + while x < n: + x = x + increment From fijal at codespeak.net Wed Mar 11 00:21:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 00:21:20 +0100 (CET) Subject: [pypy-svn] r62834 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090310232120.4581B1684F1@codespeak.net> Author: fijal Date: Wed Mar 11 00:21:17 2009 New Revision: 62834 Added: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes_sup.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: Do the correct thing about parent structures. It's separated into different file to make --fork-before behave as expected. Except this hack to go away Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Wed Mar 11 00:21:17 2009 @@ -689,9 +689,6 @@ addr = ctypes.addressof(cobj.contents) if addr in _parent_cache: setparentstructure(container, _parent_cache[addr]) - else: - import pdb - pdb.set_trace() elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) @@ -1067,20 +1064,12 @@ # ------------------------------------------------------------ def parentchain(container): - current = container - links = [] - while True: - link = lltype.parentlink(current) - if link[0] is None: - return links - links.append(link) - current = link[0] + from pypy.rpython.lltypesystem.ll2ctypes_sup import parentchain + return parentchain(container) def setparentstructure(container, chain): - current = container - for elem in chain: - current._setparentstructure(*elem) - current = elem[0] + from pypy.rpython.lltypesystem.ll2ctypes_sup import setparentstructure + setparentstructure(container, chain) # ____________________________________________________________ # errno Added: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes_sup.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes_sup.py Wed Mar 11 00:21:17 2009 @@ -0,0 +1,26 @@ + +from pypy.rpython.lltypesystem import lltype, ll2ctypes +import ctypes + +def parentchain(container): + current = container + links = [] + while True: + link = lltype.parentlink(current) + if link[0] is None: + try: + addr = ctypes.addressof(container._storage) + actual = ll2ctypes._parent_cache[addr] + if len(links) < len(actual): + return actual + except KeyError: + pass + return links + links.append(link) + current = link[0] + +def setparentstructure(container, chain): + current = container + for elem in chain: + current._setparentstructure(*elem) + current = elem[0] From hpk at codespeak.net Wed Mar 11 10:42:19 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 11 Mar 2009 10:42:19 +0100 (CET) Subject: [pypy-svn] r62837 - pypy/extradoc/talk/openbossa2009/pypy-mobile Message-ID: <20090311094219.4DF4F1684FF@codespeak.net> Author: hpk Date: Wed Mar 11 10:42:17 2009 New Revision: 62837 Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Log: some last bits for my talk in a few hours Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex ============================================================================== --- pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/author.latex Wed Mar 11 10:42:17 2009 @@ -1,7 +1,7 @@ \definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} \title[PyPy status / mobile perspectives]{PyPy status / mobile perspectives} -\author[H. Krekel]{Holger Krekel \\ Merlinux GmbH} +\author[H. Krekel]{Holger Krekel \\ http://merlinux.eu} \institute[OpenBossa 2009, Recife, Brazil]{OpenBossa 2009, Brazil} \date{March 11, 2009} Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt ============================================================================== --- pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Wed Mar 11 10:42:17 2009 @@ -12,14 +12,25 @@ http://marikaz.deviantart.com/ CC 3.0 AN-ND +Some technical background +============================ + +- started with programming small devices in 1986 +- Motorola assembler for game companies +- studied computer science in the nineties +- C++, C, Corba, Java, UML, consulting ... +- 2001: arrived at Python and FOSS +- founded PyPy and py.test projects +- founded merlinux, a developer company + What this talk is about ======================= * Status of PyPy / 1.1 release -* resource usage / startup time +* resource usage -* ideas/visions +* ideas, visions, next steps PyPy? ======== @@ -34,11 +45,11 @@ PyPy - developer motivation ================================= -* high level language specification! +* **high level Python specification**! * layer GCs, JIT, Stackless atop the spec -* generate interpreters for C, .NET, JVM, embedded platforms, ... +* **generate interpreters** for targets .. image:: pypy-multitarget.png @@ -133,16 +144,16 @@ * PyPy not compatible to CPython extensions * we have many builtin modules -* but 3rd party modules largely missing +* many 3rd party modules missing PyPy Answers for Extension modules ==================================== - for using C-libs: CTypes -- for speed: JIT or if need be, RPython -- for using C++ libs: ??? +- for speed: JIT (or if one must, RPython) +- for using C++ libs: Reflex? -CTypes status +CTypes ==================== * dynamically interact with C objects from Python @@ -165,7 +176,7 @@ * our JIT is to be the huge leap beyond CPython -* some more static optimizations? +* we can also do more source optimizations A Memory benchmark =================================== @@ -181,11 +192,11 @@ * pypy-c has massive software threading -* OS-threads: currently using GIL, quite robust +* OS-threads: currently using GIL -* free threading? requires research + some work +* free threading? -* all threading: added during translation! +* threading aspects: added during translation! pypy-c measurements on Maemo @@ -195,10 +206,6 @@ - we measured pypy-c on N810 device -- python object sizes, app benchmarks, startup time - -- base interpreter size, GC pauses, interpretation speed - - tool see http://codespeak.net/svn/pypy/build/benchmem Python object sizes @@ -206,71 +213,60 @@ - PyPy has smaller "per-object" RAM usage -- instances usually at 50% of CPython size +- **instances usually at 50% of CPython size** -- as efficient as CPython's __slots__ without the caveats +- like CPython's __slots__ without the caveats - room for further optimizations table at http://codespeak.net/~hpk/openbossa2009/table-objsize.html -Maemo Interpreter startup time -=============================== +Maemo PyPy Interpreter startup time +===================================== +--------------+--------+--------+---------------+ |startup |python |Omem-opt|python-launcher| +--------------+--------+--------+---------------+ -|site |**0.24**|**0.16**|**0.11** | +|site | 0.24 | 0.16 | 0.11 | +--------------+--------+--------+---------------+ -|nosite |**0.21**|**0.04**|**0.11** | +|nosite | 0.21 | 0.04 | 0.11 | +--------------+--------+--------+---------------+ -|importos |**0.21**|**0.04**|**0.11** | +|importos | 0.21 | 0.04 | 0.11 | +--------------+--------+--------+---------------+ -|importdecimal |**0.47**|**0.42**|**0.34** | +|impdec | 0.47 | 0.42 | 0.34 | +--------------+--------+--------+---------------+ -|importoptparse|**0.54**|**0.04**|**0.11** | +|impopt | 0.54 | 0.04 | 0.11 | +--------------+--------+--------+---------------+ -PyPy has faster startup if few bytecode execution is involved +PyPy has faster startup on "pre-imported" modules + + +Python Application benchmarks +============================== + +- pypy-c better on avg/maximum usage app-benchmarks +- gcbench for some uninvestigated reason much worse + +see http://codespeak.net/~hpk/openbossa2009/table-appprofiles.html + where pypy is currently worse =================================== - larger (but shareable) base interpreter size -- gc collection pauses can be larger: tuning? +- gc collection pauses can be larger: needs tuning - bytecode execution speed: 1-4 times slower than CPython -(oh, and our parser and compiler speed is particularly bad) - -Python Application benchmarks -============================== - - +------------------------+-----------------+-----------------+ - |app benchmark |python |pypy-Omem | - +------------------------+-----------------+-----------------+ - |allocate_and_throw_away |**28152** / 20578|**17700** / 9845 | - +------------------------+-----------------+-----------------+ - |allocate_constant_number|**11528** / 11279|**7712** / 4792 | - +------------------------+-----------------+-----------------+ - |allocate_couple |**28136** / 21254|**17712** / 9882 | - +------------------------+-----------------+-----------------+ - |cpython_nasty |**30592** / 23743|**15648** / 9061 | - +------------------------+-----------------+-----------------+ - |gcbench |**9548** / 7454 |**17936** / 13419| - +------------------------+-----------------+-----------------+ - |list_of_messages |**31908** / 13924|**14000** / 7879 | - +------------------------+-----------------+-----------------+ +(btw, our parser and compiler speed is particularly bad) Summary measurements ============================= * slower bytecode execution speed * larger (but shareable) base interpreter size -* smaller objects -* better app behaviour -* faster startup (if few imports are involved) - -Note: not much work to optimise non-speed issues was done yet! +* smaller Python objects +* better app allocation behaviour +* faster startup Ideas and visions @@ -282,15 +278,15 @@ http://marikaz.deviantart.com/ CC 3.0 AN-ND -Idea: C++ Extension modules -============================= +Idea for C++ Extension modules +================================ -- idea: use CERN's Reflex mechanism +- use CERN's Reflex tools/approach - tool compiles shared "introspect" library for each C++ lib - introspect-library handled by generic helper module -- maybe generically work with C++ libs? -- otherwise: small module to do extra bits -- IOW, some more thought and experimentation needed +- probably a very good approach for PyPy + +http://root.cern.ch/drupal/content/reflex perfect PYC files ============================ @@ -300,23 +296,25 @@ - but: directly work with PYC data, zero-copy - don't touch mmaped pages unless needed - **no allocs of redundant objects during import** -- **total sharing of bytecode and constants** +- **interpreters share all code objects** JIT for overhead elimination ==================================== - JIT to speed up code up to 100 times -- keep a good memory/speed gain balance! - parametrize JIT heuristics to care for very hot paths -- JIT could remove overheads for calling into C++! +- keep a good memory/speed gain balance +- JIT could maybe also remove overheads for calling into C++ Next-generation Garbage Collection ==================================== -- currently: naive Mark&Compact (500 lines of code) -- port/implement newer techniques +- currently: naive Mark&Compact (600 lines of code) +- port/implement newer techniques (e.g. deferred refcounting) +- even more compact GC headers - malloc-directed inlining -- maximize shared interpreter state +- maximize shared interpreter state +- co-operate with kernel in swapping/collect situations a word about doing GCs =================================== @@ -326,6 +324,14 @@ - get Python tracebacks instead of segfaults - once ready, translate with Python Interpreter +other optimizations +===================== + +- revisit/measure decisions in ARM context +- splitting static data into immutable/modifiable +- group data to avoid fragmentation +- run multiple apps in one process, isolated and robust + One last bit ================= @@ -338,7 +344,7 @@ Sandboxing / Virtualization ================================= -* we have a fully sandboxed interpreter! +* PyPy can generate a virtualized Python! * all IO and OS external calls serialized to separate process @@ -347,23 +353,23 @@ :scale: 30 :align: center -Outlook / -========= +Current priorities and interests +================================== -- PyPy 1.1 release in 1-2 months -- get the JIT to surpass CPython speed +- expect PyPy 1.1 release in around 2 months +- then: JIT to surpass CPython speed - perfect/commoditize Python sandboxing - help/do compatibility work, ext modules -- C++? -- bring PyPy to symbian and more mobiles? Contact / Q&A ========================== holger krekel at http://merlinux.eu + Blog: http://tetamap.wordpress.com PyPy: http://codespeak.net/pypy + PyPy Blog: http://morepypy.blogspot.com Photos: http://marikaz.deviantart.com/gallery/ From arigo at codespeak.net Wed Mar 11 11:01:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 11:01:32 +0100 (CET) Subject: [pypy-svn] r62838 - in pypy/trunk/pypy: rpython rpython/lltypesystem translator Message-ID: <20090311100132.BB7441684F1@codespeak.net> Author: arigo Date: Wed Mar 11 11:01:32 2009 New Revision: 62838 Modified: pypy/trunk/pypy/rpython/llinterp.py pypy/trunk/pypy/rpython/lltypesystem/llmemory.py pypy/trunk/pypy/translator/exceptiontransform.py Log: Properly revert fijal's hack. Fijal, please try to use "svn merge" or some other tool to revert, instead of using techniques that leave behind a few minor changes. Modified: pypy/trunk/pypy/rpython/llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/llinterp.py (original) +++ pypy/trunk/pypy/rpython/llinterp.py Wed Mar 11 11:01:32 2009 @@ -1181,9 +1181,6 @@ def op_oohash(self, s): return ootype.oohash(s) - def op_raise_exc_value(self, etype, evalue): - raise LLException(etype, evalue) - class Tracer(object): Counter = 0 file = None Modified: pypy/trunk/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/llmemory.py Wed Mar 11 11:01:32 2009 @@ -411,10 +411,8 @@ def __nonzero__(self): return self.ptr is not None - def __hash__(self): - if not self._fixup().ptr: - return 0 - return hash(self._fixup().ptr._obj) + #def __hash__(self): + # raise TypeError("don't put addresses in a prebuilt dictionary") def __eq__(self, other): if isinstance(other, fakeaddress): Modified: pypy/trunk/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/trunk/pypy/translator/exceptiontransform.py (original) +++ pypy/trunk/pypy/translator/exceptiontransform.py Wed Mar 11 11:01:32 2009 @@ -170,7 +170,7 @@ n_gen_exc_checks = 0 for block in list(graph.iterblocks()): self.replace_stack_unwind(block) - self.replace_fetch_restore_operations(graph, block) + self.replace_fetch_restore_operations(block) need_exc_matching, gen_exc_checks = self.transform_block(graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks @@ -189,7 +189,7 @@ block.operations[i].opname = "direct_call" block.operations[i].args = [self.rpyexc_raise_runtime_error_ptr] - def replace_fetch_restore_operations(self, graph, block): + def replace_fetch_restore_operations(self, block): # the gctransformer will create these operations. It looks as if the # order of transformations is important - but the gctransformer will # put them in a new graph, so all transformations will run again. From arigo at codespeak.net Wed Mar 11 11:01:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 11:01:48 +0100 (CET) Subject: [pypy-svn] r62839 - pypy/trunk/pypy/rpython Message-ID: <20090311100148.E40EF168500@codespeak.net> Author: arigo Date: Wed Mar 11 11:01:48 2009 New Revision: 62839 Modified: pypy/trunk/pypy/rpython/llinterp.py Log: Tag LLException as NOT_RPYTHON. Modified: pypy/trunk/pypy/rpython/llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/llinterp.py (original) +++ pypy/trunk/pypy/rpython/llinterp.py Wed Mar 11 11:01:48 2009 @@ -14,6 +14,9 @@ log = py.log.Producer('llinterp') class LLException(Exception): + def __init__(self, *args): + "NOT_RPYTHON" + Exception.__init__(self, *args) def __str__(self): etype = self.args[0] #evalue = self.args[1] From arigo at codespeak.net Wed Mar 11 11:04:05 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 11:04:05 +0100 (CET) Subject: [pypy-svn] r62840 - in pypy/branch/pyjitpl5/pypy: rpython rpython/lltypesystem translator Message-ID: <20090311100405.1CEE21684F1@codespeak.net> Author: arigo Date: Wed Mar 11 11:04:04 2009 New Revision: 62840 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py Log: Merge r62838 and r62839 from the trunk. Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Wed Mar 11 11:04:04 2009 @@ -14,6 +14,9 @@ log = py.log.Producer('llinterp') class LLException(Exception): + def __init__(self, *args): + "NOT_RPYTHON" + Exception.__init__(self, *args) def __str__(self): etype = self.args[0] #evalue = self.args[1] @@ -1181,9 +1184,6 @@ def op_oohash(self, s): return ootype.oohash(s) - def op_raise_exc_value(self, etype, evalue): - raise LLException(etype, evalue) - class Tracer(object): Counter = 0 file = None Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py Wed Mar 11 11:04:04 2009 @@ -411,10 +411,8 @@ def __nonzero__(self): return self.ptr is not None - def __hash__(self): - if not self._fixup().ptr: - return 0 - return hash(self._fixup().ptr._obj) + #def __hash__(self): + # raise TypeError("don't put addresses in a prebuilt dictionary") def __eq__(self, other): if isinstance(other, fakeaddress): Modified: pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/exceptiontransform.py Wed Mar 11 11:04:04 2009 @@ -170,7 +170,7 @@ n_gen_exc_checks = 0 for block in list(graph.iterblocks()): self.replace_stack_unwind(block) - self.replace_fetch_restore_operations(graph, block) + self.replace_fetch_restore_operations(block) need_exc_matching, gen_exc_checks = self.transform_block(graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks @@ -189,7 +189,7 @@ block.operations[i].opname = "direct_call" block.operations[i].args = [self.rpyexc_raise_runtime_error_ptr] - def replace_fetch_restore_operations(self, graph, block): + def replace_fetch_restore_operations(self, block): # the gctransformer will create these operations. It looks as if the # order of transformations is important - but the gctransformer will # put them in a new graph, so all transformations will run again. From arigo at codespeak.net Wed Mar 11 11:05:53 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 11:05:53 +0100 (CET) Subject: [pypy-svn] r62841 - pypy/trunk/pypy/translator Message-ID: <20090311100553.1487D1684F1@codespeak.net> Author: arigo Date: Wed Mar 11 11:05:52 2009 New Revision: 62841 Modified: pypy/trunk/pypy/translator/exceptiontransform.py Log: Oups, forgot to add this method to the OOType class. Modified: pypy/trunk/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/trunk/pypy/translator/exceptiontransform.py (original) +++ pypy/trunk/pypy/translator/exceptiontransform.py Wed Mar 11 11:05:52 2009 @@ -512,6 +512,9 @@ def check_for_alloc_shortcut(self, spaceop): return False + def build_extra_funcs(self): + pass + def ExceptionTransformer(translator): type_system = translator.rtyper.type_system.name if type_system == 'lltypesystem': From fijal at codespeak.net Wed Mar 11 11:42:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 11:42:04 +0100 (CET) Subject: [pypy-svn] r62843 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090311104204.22C6216852D@codespeak.net> Author: fijal Date: Wed Mar 11 11:42:03 2009 New Revision: 62843 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: a version that explodes on top of x86 backend Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Wed Mar 11 11:42:03 2009 @@ -17,15 +17,14 @@ print i assert i == 102 -def f(): +def f2(): print "range object, but outside the loop" s = 0 - for i in range(100): - # XXX implement inplace_add method for ints + for i in range(1000000): s = s + i print s - assert s == 4950 + assert s == 499999500000L def f(): try: @@ -39,4 +38,4 @@ else: raise AssertionError -f() +f2() From fijal at codespeak.net Wed Mar 11 11:42:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 11:42:19 +0100 (CET) Subject: [pypy-svn] r62844 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090311104219.54E3D168531@codespeak.net> Author: fijal Date: Wed Mar 11 11:42:18 2009 New Revision: 62844 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: use x86 backend here Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Wed Mar 11 11:42:18 2009 @@ -2,7 +2,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp import warmspot from pypy.module.pypyjit.portal import PyPyJitPolicy - +from pypy.jit.backend.x86.runner import CPU386 # Current output: http://paste.pocoo.org/show/106540/ # @@ -39,7 +39,7 @@ option.view = True try: warmspot.jittify_and_run(interp, graph, [], policy=policy, - listops=True) + listops=True, CPUClass=CPU386) except Exception, e: print '%s: %s' % (e.__class__, e) pdb.post_mortem(sys.exc_info()[2]) From cfbolz at codespeak.net Wed Mar 11 11:54:46 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 11 Mar 2009 11:54:46 +0100 (CET) Subject: [pypy-svn] r62845 - in pypy/branch/speedup-globals/pypy/objspace/std: . test Message-ID: <20090311105446.401271684DE@codespeak.net> Author: cfbolz Date: Wed Mar 11 11:54:45 2009 New Revision: 62845 Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py Log: get rid of invalid flag Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/celldict.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Wed Mar 11 11:54:45 2009 @@ -3,19 +3,16 @@ from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash class ModuleCell(object): - def __init__(self, valid=True): - self.w_value = None - self.valid = valid + def __init__(self, w_value=None): + self.w_value = w_value def invalidate(self): + w_value = self.w_value self.w_value = None - self.valid = False + return w_value def __repr__(self): - if self.valid: - return "" % (self.w_value, ) - else: - return "" + return "" % (self.w_value, ) class ModuleDictImplementation(DictImplementation): def __init__(self, space): @@ -37,12 +34,11 @@ self.unshadowed_builtins[name] = builtin_impl def invalidate_unshadowed_builtin(self, name): + # XXX what if the builtin was deleted in the meantime? impl = self.unshadowed_builtins[name] cell = impl.content[name] - w_value = cell.w_value - cell.invalidate() - cell = impl.content[name] = ModuleCell() - cell.w_value = w_value + w_value = cell.invalidate() + cell = impl.content[name] = ModuleCell(w_value) def setitem(self, w_key, w_value): space = self.space @@ -167,7 +163,7 @@ class State(object): def __init__(self, space): self.space = space - self.invalidcell = ModuleCell(valid=False) + self.invalidcell = ModuleCell() self.always_invalid_cache = [] self.neverused_dictimpl = ModuleDictImplementation(space) @@ -216,12 +212,11 @@ def LOAD_GLOBAL(f, nameindex, *ignored): cell = f.cache_for_globals[nameindex] - if cell.valid: - result = cell.w_value - else: + w_value = cell.w_value + if w_value is None: # slow path - result = load_global_fill_cache(f, nameindex) - f.pushvalue(result) + w_value = load_global_fill_cache(f, nameindex) + f.pushvalue(w_value) LOAD_GLOBAL._always_inline_ = True def find_cell_from_dict(implementation, name): Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py Wed Mar 11 11:54:45 2009 @@ -19,7 +19,7 @@ name = space.str_w(w_name) cache = get_global_cache(space, w_code, w_globals) index = [space.str_w(w_n) for w_n in w_code.co_names_w].index(name) - return space.wrap(cache[index].valid) + return space.wrap(cache[index].w_value is not None) is_in_cache = gateway.interp2app(is_in_cache) cls.w_is_in_cache = cls.space.wrap(is_in_cache) stored_builtins = [] From fijal at codespeak.net Wed Mar 11 11:56:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 11:56:11 +0100 (CET) Subject: [pypy-svn] r62846 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090311105611.598281684DE@codespeak.net> Author: fijal Date: Wed Mar 11 11:56:10 2009 New Revision: 62846 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: a bit broken test, I admit, but should work anyway Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Wed Mar 11 11:56:10 2009 @@ -370,6 +370,30 @@ res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == f(10) + + def test_read_after_loop(self): + py.test.skip("FIXME") + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + def __init__(self, x): + self.x = x + + def f(n): + frame = Frame(10) + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n) + jitdriver.jit_merge_point(frame=frame, n=n) + frame.x = hint(frame.x, promote=True) + n -= 1 + frame.x += 1 + return frame.x + + res = self.meta_interp(f, [30]) + assert res == f(10) def test_external_read(self): From fijal at codespeak.net Wed Mar 11 11:57:59 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 11:57:59 +0100 (CET) Subject: [pypy-svn] r62847 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090311105759.7A0E11684DE@codespeak.net> Author: fijal Date: Wed Mar 11 11:57:59 2009 New Revision: 62847 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: this is the original test, works Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Wed Mar 11 11:57:59 2009 @@ -394,7 +394,33 @@ res = self.meta_interp(f, [30]) assert res == f(10) - + + def test_read_after_loop_2(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + def __init__(self, x): + self.x = x + + def f(n): + frame = Frame(10) + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n) + jitdriver.jit_merge_point(frame=frame, n=n) + frame.x = hint(frame.x, promote=True) + frame.x += 1 + if n == 2: + break + frame.x -= 1 + n -= 1 + return frame.x + + res = self.meta_interp(f, [30]) + assert res == 11 + def test_external_read(self): py.test.skip("Fails") From fijal at codespeak.net Wed Mar 11 12:00:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 12:00:23 +0100 (CET) Subject: [pypy-svn] r62848 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090311110023.B9E1916852C@codespeak.net> Author: fijal Date: Wed Mar 11 12:00:23 2009 New Revision: 62848 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: welll... my fault Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Wed Mar 11 12:00:23 2009 @@ -372,7 +372,6 @@ assert res == f(10) def test_read_after_loop(self): - py.test.skip("FIXME") jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) @@ -393,7 +392,7 @@ return frame.x res = self.meta_interp(f, [30]) - assert res == f(10) + assert res == f(30) def test_read_after_loop_2(self): jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], From arigo at codespeak.net Wed Mar 11 12:18:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 12:18:10 +0100 (CET) Subject: [pypy-svn] r62849 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090311111810.79E401684BC@codespeak.net> Author: arigo Date: Wed Mar 11 12:18:08 2009 New Revision: 62849 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Log: Cancel accidentally reverted fix (e.g. for pypy/rlib/test/test_rzipfile). Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Wed Mar 11 12:18:08 2009 @@ -929,14 +929,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. From arigo at codespeak.net Wed Mar 11 12:20:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 12:20:27 +0100 (CET) Subject: [pypy-svn] r62850 - pypy/trunk/pypy/translator/platform/test Message-ID: <20090311112027.D652C1684BC@codespeak.net> Author: arigo Date: Wed Mar 11 12:20:25 2009 New Revision: 62850 Modified: pypy/trunk/pypy/translator/platform/test/test_darwin.py Log: Add a skip. Modified: pypy/trunk/pypy/translator/platform/test/test_darwin.py ============================================================================== --- pypy/trunk/pypy/translator/platform/test/test_darwin.py (original) +++ pypy/trunk/pypy/translator/platform/test/test_darwin.py Wed Mar 11 12:20:25 2009 @@ -2,7 +2,10 @@ """ File containing darwin platform tests """ -import py +import py, os +if os.name != 'darwin': + py.test.skip("Darwin only") + from pypy.tool.udir import udir from pypy.translator.platform.darwin import Darwin from pypy.translator.platform.test.test_platform import TestPlatform as BasicTest From arigo at codespeak.net Wed Mar 11 12:31:52 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 12:31:52 +0100 (CET) Subject: [pypy-svn] r62851 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090311113152.28C0E1684D6@codespeak.net> Author: arigo Date: Wed Mar 11 12:31:52 2009 New Revision: 62851 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Log: Another fix for test_ll2ctypes. I don't know in which direction this change was done before, so this is either redoing a lost change, or cancelling an invalid fix. Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Wed Mar 11 12:31:52 2009 @@ -627,12 +627,9 @@ c_tp = get_ctypes_type(T.TO) storage._normalized_ctype = c_tp if normalize and getattr(T.TO, '_arrayfld', None): - try: - c_tp = _ctypes_cache[T.TO] - except KeyError: - c_tp = build_ctypes_struct(T.TO, [], - len(getattr(storage, T.TO._arrayfld).items)) - _ctypes_cache[T.TO] = c_tp + # 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)) From arigo at codespeak.net Wed Mar 11 12:33:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 12:33:07 +0100 (CET) Subject: [pypy-svn] r62852 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090311113307.C41541684F4@codespeak.net> Author: arigo Date: Wed Mar 11 12:33:07 2009 New Revision: 62852 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Log: Add a comment for the previous checkin. Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Wed Mar 11 12:33:07 2009 @@ -630,6 +630,7 @@ # XXX doesn't cache c_tp = build_ctypes_struct(T.TO, [], len(getattr(storage, T.TO._arrayfld).items)) + # make sure you cache according to the len() above! p = ctypes.cast(p, ctypes.POINTER(c_tp)) elif normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) From arigo at codespeak.net Wed Mar 11 12:37:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 12:37:44 +0100 (CET) Subject: [pypy-svn] r62854 - in pypy/trunk/pypy/rpython: . ootypesystem Message-ID: <20090311113744.0CCAD1684F4@codespeak.net> Author: arigo Date: Wed Mar 11 12:37:43 2009 New Revision: 62854 Modified: pypy/trunk/pypy/rpython/llinterp.py pypy/trunk/pypy/rpython/ootypesystem/ooopimpl.py Log: Fix test_lloperation.py. Modified: pypy/trunk/pypy/rpython/llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/llinterp.py (original) +++ pypy/trunk/pypy/rpython/llinterp.py Wed Mar 11 12:37:43 2009 @@ -554,6 +554,15 @@ def op_jit_marker(self, *args): pass + def op_promote_virtualizable(self, *args): + pass + + def op_get_exception_addr(self, *args): + raise NotImplementedError + + def op_get_exc_value_addr(self, *args): + raise NotImplementedError + def op_instrument_count(self, ll_tag, ll_label): pass # xxx for now Modified: pypy/trunk/pypy/rpython/ootypesystem/ooopimpl.py ============================================================================== --- pypy/trunk/pypy/rpython/ootypesystem/ooopimpl.py (original) +++ pypy/trunk/pypy/rpython/ootypesystem/ooopimpl.py Wed Mar 11 12:37:43 2009 @@ -16,6 +16,9 @@ checkinst(inst) return bool(inst) +def op_ooisnull(inst): + return not op_oononnull(inst) + def op_oois(obj1, obj2): if is_inst(obj1): checkinst(obj2) @@ -26,6 +29,9 @@ else: assert False, "oois on something silly" +def op_ooisnot(obj1, obj2): + return not op_oois(obj1, obj2) + def op_instanceof(inst, INST): return ootype.instanceof(inst, INST) From arigo at codespeak.net Wed Mar 11 12:38:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 12:38:45 +0100 (CET) Subject: [pypy-svn] r62855 - pypy/trunk/pypy/jit/backend/x86/test Message-ID: <20090311113845.CC51F1684FF@codespeak.net> Author: arigo Date: Wed Mar 11 12:38:45 2009 New Revision: 62855 Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py Log: Skip failing test. Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py Wed Mar 11 12:38:45 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("XXX fails") from pypy.jit.metainterp.test.test_slist import ListTests from pypy.jit.backend.x86.support import c_meta_interp From cfbolz at codespeak.net Wed Mar 11 13:16:35 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 11 Mar 2009 13:16:35 +0100 (CET) Subject: [pypy-svn] r62856 - in pypy/branch/speedup-globals/pypy/objspace/std: . test Message-ID: <20090311121635.E7EF4168510@codespeak.net> Author: cfbolz Date: Wed Mar 11 13:16:33 2009 New Revision: 62856 Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py Log: fix a corner-case Modified: pypy/branch/speedup-globals/pypy/objspace/std/celldict.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/celldict.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/celldict.py Wed Mar 11 13:16:33 2009 @@ -34,11 +34,14 @@ self.unshadowed_builtins[name] = builtin_impl def invalidate_unshadowed_builtin(self, name): - # XXX what if the builtin was deleted in the meantime? impl = self.unshadowed_builtins[name] - cell = impl.content[name] - w_value = cell.invalidate() - cell = impl.content[name] = ModuleCell(w_value) + try: + cell = impl.content[name] + except KeyError: + pass + else: + w_value = cell.invalidate() + cell = impl.content[name] = ModuleCell(w_value) def setitem(self, w_key, w_value): space = self.space Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py ============================================================================== --- pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py (original) +++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py Wed Mar 11 13:16:33 2009 @@ -123,6 +123,39 @@ finally: __builtins__.len = orig_len + def test_override_builtins2(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + return l(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + __builtin__.l = len + try: + assert not self.is_in_cache(code, glob1, "l") + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 0 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + assert f1() == 0 + mod1.x.append(1) + assert f1() == 1 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + del __builtin__.l + mod1.l = len + mod1.x.append(1) + assert not self.is_in_cache(code, glob1, "l") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + finally: + if hasattr(__builtins__, "l"): + del __builtins__.l + def test_generator(self): import sys, __builtin__ mod1 = type(sys)("abc") From cfbolz at codespeak.net Wed Mar 11 14:17:32 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 11 Mar 2009 14:17:32 +0100 (CET) Subject: [pypy-svn] r62858 - in pypy/branch/pyjitpl5/pypy/translator/backendopt: . test Message-ID: <20090311131732.60E961684D6@codespeak.net> Author: cfbolz Date: Wed Mar 11 14:17:30 2009 New Revision: 62858 Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py Log: Write a simple inlining heuristic that never inlines graphs that have an oopspec attached. Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py Wed Mar 11 14:17:30 2009 @@ -624,6 +624,12 @@ return (0.9999 * measure_median_execution_cost(graph) + count), True +def inlining_heuristic_no_oopspec(graph): + try: + oopspec = graph.func.oopspec + except AttributeError: + return inlining_heuristic(graph) + return (sys.maxint, True) def inlinable_static_callers(graphs): ok_to_call = dict.fromkeys(graphs) Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py Wed Mar 11 14:17:30 2009 @@ -9,6 +9,7 @@ from pypy.translator.backendopt.inline import collect_called_graphs from pypy.translator.backendopt.inline import measure_median_execution_cost from pypy.translator.backendopt.inline import instrument_inline_candidates +from pypy.translator.backendopt.inline import inlining_heuristic_no_oopspec from pypy.translator.backendopt.checkvirtual import check_virtual_methods from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.llinterp import LLInterpreter @@ -92,7 +93,7 @@ return eval_func def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False, - checkvirtual=False, remove_same_as=False): + checkvirtual=False, remove_same_as=False, heuristic=None): t = self.translate(func, sig) if checkvirtual: check_virtual_methods() @@ -114,7 +115,11 @@ for graph in t.graphs: removenoops.remove_same_as(graph) - auto_inlining(t, threshold, call_count_pred=call_count_pred) + if heuristic is not None: + kwargs = {"heuristic": heuristic} + else: + kwargs = {} + auto_inlining(t, threshold, call_count_pred=call_count_pred, **kwargs) sanity_check(t) if option.view: @@ -597,6 +602,24 @@ res = eval_func([]) assert res == 5 + def test_no_oopspec_inliner(self): + def f(): + tot = 0 + for item in [1,2,3]: + tot += item + return tot + + eval_func, t = self.check_auto_inlining( + f, [], heuristic=inlining_heuristic_no_oopspec) + f_graph = graphof(t, f) + called_graphs = collect_called_graphs(f_graph, t, include_oosend=False) + print called_graphs + assert len(called_graphs) == 4 # newlist, setitem, getitem, length + + result = eval_func([]) + assert result == 6 + + class TestInlineOOType(OORtypeMixin, BaseTestInline): From afa at codespeak.net Wed Mar 11 14:55:26 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Mar 2009 14:55:26 +0100 (CET) Subject: [pypy-svn] r62859 - pypy/trunk/pypy/translator/c/test Message-ID: <20090311135526.341C41684F1@codespeak.net> Author: afa Date: Wed Mar 11 14:55:25 2009 New Revision: 62859 Modified: pypy/trunk/pypy/translator/c/test/test_extfunc.py Log: Fix most tests on test_extfunc.py for windows, mostly by moving fd management inside the compiled functions: the C runtimes often differ between CPython and the one used by the compiler. Modified: pypy/trunk/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/trunk/pypy/translator/c/test/test_extfunc.py Wed Mar 11 14:55:25 2009 @@ -41,11 +41,11 @@ tmpfile = str(udir.join('test_os_open.txt')) def does_stuff(): fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777) + os.close(fd) return fd f1 = compile(does_stuff, []) fd = f1() - os.close(fd) assert os.path.exists(tmpfile) def test_failing_os_open(): @@ -163,8 +163,6 @@ res = f() assert res[0] == os.stat(filename).st_mode assert res[1] == os.stat(filename).st_ino - if sys.platform.startswith('win'): - py.test.skip("in-progress - bogus stat().st_time") st_ctime = res[2] if isinstance(st_ctime, float): assert st_ctime == os.stat(filename).st_ctime @@ -179,18 +177,17 @@ if os.environ.get('PYPY_CC', '').startswith('tcc'): py.test.skip("segfault with tcc :-(") filename = str(py.magic.autopath()) - fd = os.open(filename, os.O_RDONLY, 0777) - def call_fstat(fd): + def call_fstat(): + fd = os.open(filename, os.O_RDONLY, 0777) st = os.fstat(fd) + os.close(fd) return (st.st_mode, st[1], st.st_mtime) - f = compile(call_fstat, [int]) + f = compile(call_fstat, []) osstat = os.stat(filename) - st_mode, st_ino, st_mtime = f(fd) - os.close(fd) + st_mode, st_ino, st_mtime = f() assert st_mode == osstat.st_mode - assert st_ino == osstat.st_ino - if sys.platform.startswith('win'): - py.test.skip("in-progress - bogus stat().st_time") + if sys.platform != 'win32': + assert st_ino == osstat.st_ino if isinstance(st_mtime, float): assert st_mtime == osstat.st_mtime else: From afa at codespeak.net Wed Mar 11 17:07:11 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Mar 2009 17:07:11 +0100 (CET) Subject: [pypy-svn] r62860 - pypy/trunk/pypy/rpython/tool Message-ID: <20090311160711.74F5616844C@codespeak.net> Author: afa Date: Wed Mar 11 17:07:09 2009 New Revision: 62860 Modified: pypy/trunk/pypy/rpython/tool/rffi_platform.py Log: Start a better management of external libraries. on Windows there is no standard place to install them. I suggest to take the CPython way: in the root directory (pypy/../.. which is shared by all pypy branches on my disk), extract and build all the needed third-party libraries, following documentation for each one. for example, on my disk: c:\dev\pypy\trunk contains the trunk branch of pypy c:\dev\pypy\zlib-1.2.3 download, untar, and build with 'nmake -f win32\Makefile.msc' c:\dev\pypy\bzip2-1.0.5 download, untar, and build with 'nmake -f makefile.msc' c:\dev\pypy\gc-7.1 download, untar, and build with 'nmake -f NT_THREADS_MAKEFILE' The translation tools are aware of the structure of each project - they may try several ones. You may install the version you wish - the last one (in alphabetical order) is preferred. For the moment this is enabled only on Windows. Modified: pypy/trunk/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/trunk/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/trunk/pypy/rpython/tool/rffi_platform.py Wed Mar 11 17:07:09 2009 @@ -561,20 +561,103 @@ gcv = sysconfig.get_config_vars() return gcv['INCLUDEPY'] -def check_boehm(platform=None, cache={}): - if platform is None: - from pypy.translator.platform import platform +def configure_external_library(name, eci, configurations, + symbol=None, _cache={}): + """try to find the external library. + On Unix, this simply tests and returns the given eci. + + On Windows, various configurations may be tried to compile the + given eci object. These configurations are a list of dicts, + containing: + + - prefix: if an absolute path, will prefix each include and + library directories. If a relative path, the external + directory is searched for directories which names start + with the prefix. The last one in alphabetical order + chosen, and becomes the prefix. + + - include_dir: prefix + include_dir is added to the include directories + + - library_dir: prefix + library_dir is added to the library directories + """ + + if sys.platform != 'win32': + configurations = [] + + key = (name, eci) try: - return cache[platform] + return _cache[key] except KeyError: - class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes=['gc/gc.h'], - platform=platform, + last_error = None + + # Always try the default configuration + if {} not in configurations: + configurations.append({}) + + for configuration in configurations: + prefix = configuration.get('prefix', '') + include_dir = configuration.get('include_dir', '') + library_dir = configuration.get('library_dir', '') + + if prefix and not os.path.isabs(prefix): + import glob + + # XXX make this a global option? + from pypy.tool.autopath import pypydir + external_dir = py.path.local(pypydir).join('..', '..') + + entries = glob.glob(str(external_dir.join(name + '*'))) + if entries: + # Get last version + prefix = sorted(entries)[-1] + else: + continue + + include_dir = os.path.join(prefix, include_dir) + library_dir = os.path.join(prefix, library_dir) + + eci_lib = ExternalCompilationInfo( + include_dirs=include_dir and [include_dir] or [], + library_dirs=library_dir and [library_dir] or [], ) - HAS = Has('GC_init') - cache[platform] = configure(CConfig)['HAS'] - return cache[platform] + eci_lib = eci_lib.merge(eci) + + # verify that this eci can be compiled + try: + verify_eci(eci_lib) + except CompilationError, e: + last_error = e + else: + _cache[key] = eci_lib + return eci_lib + + # Nothing found + if last_error: + raise last_error + else: + raise CompilationError("Library %s is not installed" % (name,)) + +def check_boehm(platform=None): + if platform is None: + from pypy.translator.platform import platform + if sys.platform == 'win32': + library_dir = 'Release' + includes=['gc.h'] + else: + library_dir = '' + includes=['gc/gc.h'] + eci = ExternalCompilationInfo( + platform=platform, + includes=includes, + libraries=['gc'], + ) + try: + return configure_external_library( + 'gc', eci, + [dict(prefix='gc-', include_dir='include', library_dir=library_dir)], + symbol='GC_init') + except CompilationError: + return None if __name__ == '__main__': doc = """Example: From afa at codespeak.net Wed Mar 11 17:13:19 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Mar 2009 17:13:19 +0100 (CET) Subject: [pypy-svn] r62861 - in pypy/trunk/pypy/translator: c platform Message-ID: <20090311161319.DC887168451@codespeak.net> Author: afa Date: Wed Mar 11 17:13:16 2009 New Revision: 62861 Modified: pypy/trunk/pypy/translator/c/gc.py pypy/trunk/pypy/translator/c/genc.py pypy/trunk/pypy/translator/platform/windows.py Log: When translating with --gc=boehm, use the compilation flags we configured before. Modified: pypy/trunk/pypy/translator/c/gc.py ============================================================================== --- pypy/trunk/pypy/translator/c/gc.py (original) +++ pypy/trunk/pypy/translator/c/gc.py Wed Mar 11 17:13:16 2009 @@ -7,6 +7,7 @@ from pypy.rpython.memory.gctransform import \ refcounting, boehm, framework, llvmgcroot, asmgcroot from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.translator.tool.cbuild import ExternalCompilationInfo class BasicGcPolicy(object): requires_stackless = False @@ -36,16 +37,17 @@ def struct_after_definition(self, defnode): return [] - def gc_libraries(self): - return [] + def compilation_info(self): + if not self.db: + return ExternalCompilationInfo() - def pre_pre_gc_code(self): # code that goes before include g_prerequisite.h gct = self.db.gctransformer - yield '/* using %s */' % (gct.__class__.__name__,) - yield '#define MALLOC_ZERO_FILLED %d' % (gct.malloc_zero_filled,) - - def pre_gc_code(self): - return ['typedef void *GC_hidden_pointer;'] + return ExternalCompilationInfo( + pre_include_bits=['/* using %s */' % (gct.__class__.__name__,), + '#define MALLOC_ZERO_FILLED %d' % (gct.malloc_zero_filled,), + ], + post_include_bits=['typedef void *GC_hidden_pointer;'] + ) def gc_startup_code(self): return [] @@ -193,25 +195,26 @@ def rtti_node_factory(self): return BoehmGcRuntimeTypeInfo_OpaqueNode - def gc_libraries(self): - if sys.platform == 'win32': - return ['gc_pypy'] - return ['gc'] + def compilation_info(self): + eci = BasicGcPolicy.compilation_info(self) - def pre_pre_gc_code(self): - for line in BasicGcPolicy.pre_pre_gc_code(self): - yield line + from pypy.rpython.tool.rffi_platform import check_boehm + eci = eci.merge(check_boehm()) + + pre_include_bits = [] if sys.platform == "linux2": - yield "#define _REENTRANT 1" - yield "#define GC_LINUX_THREADS 1" + pre_include_bits += ["#define _REENTRANT 1", + "#define GC_LINUX_THREADS 1"] if sys.platform != "win32": # GC_REDIRECT_TO_LOCAL is not supported on Win32 by gc6.8 - yield "#define GC_REDIRECT_TO_LOCAL 1" - yield '#include ' - yield '#define USING_BOEHM_GC' + pre_include_bits += ["#define GC_REDIRECT_TO_LOCAL 1"] - def pre_gc_code(self): - return [] + eci = eci.merge(ExternalCompilationInfo( + pre_include_bits=pre_include_bits, + post_include_bits=['#define USING_BOEHM_GC'], + )) + + return eci def gc_startup_code(self): if sys.platform == 'win32': @@ -263,7 +266,6 @@ class NoneGcPolicy(BoehmGcPolicy): - gc_libraries = RefcountingGcPolicy.gc_libraries.im_func gc_startup_code = RefcountingGcPolicy.gc_startup_code.im_func Modified: pypy/trunk/pypy/translator/c/genc.py ============================================================================== --- pypy/trunk/pypy/translator/c/genc.py (original) +++ pypy/trunk/pypy/translator/c/genc.py Wed Mar 11 17:13:16 2009 @@ -168,8 +168,7 @@ def collect_compilation_info(self, db): # we need a concrete gcpolicy to do this - self.eci = self.eci.merge(ExternalCompilationInfo( - libraries=db.gcpolicy.gc_libraries())) + self.eci = self.eci.merge(db.gcpolicy.compilation_info()) all = [] for node in self.db.globalcontainers(): @@ -317,6 +316,15 @@ export_symbols.append('malloc_counters') extsymeci = ExternalCompilationInfo(export_symbols=export_symbols) self.eci = self.eci.merge(extsymeci) + + if sys.platform == 'win32': + self.eci = self.eci.merge(ExternalCompilationInfo( + library_dirs = [py.path.local(sys.exec_prefix).join('LIBs'), + py.path.local(sys.executable).dirpath(), + ], + )) + + files = [self.c_source_filename] + self.extrafiles self.translator.platform.compile(files, self.eci, standalone=False) self._compiled = True @@ -772,15 +780,9 @@ print >> fi, '#define Py_BUILD_CORE /* for Windows: avoid pulling libs in */' print >> fi, '#include "pyconfig.h"' - for line in database.gcpolicy.pre_pre_gc_code(): - print >> fi, line - - eci.write_c_header(fi) - print >> fi, '#include "src/g_prerequisite.h"' - for line in database.gcpolicy.pre_gc_code(): - print >> fi, line + eci.write_c_header(fi) fi.close() @@ -830,15 +832,10 @@ print >> fi, '#define %s %s' % (key, value) print >> fi, '#include "pyconfig.h"' - for line in database.gcpolicy.pre_pre_gc_code(): - print >> fi, line - print >> fi, '#include "src/g_prerequisite.h"' - for line in database.gcpolicy.pre_gc_code(): - print >> fi, line - eci.write_c_header(fi) + fi.close() if database.translator is None or database.translator.rtyper is None: Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Wed Mar 11 17:13:16 2009 @@ -119,11 +119,6 @@ return ['%s.lib' % (lib,) for lib in libraries] def _libdirs(self, library_dirs): - if self.add_cpython_dirs: - library_dirs = library_dirs + ( - py.path.local(sys.exec_prefix).join('libs'), - py.path.local(sys.executable).dirpath(), - ) return ['/LIBPATH:%s' % (ldir,) for ldir in library_dirs] def _linkfiles(self, link_files): From arigo at codespeak.net Wed Mar 11 17:14:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 17:14:41 +0100 (CET) Subject: [pypy-svn] r62862 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090311161441.9428116846A@codespeak.net> Author: arigo Date: Wed Mar 11 17:14:41 2009 New Revision: 62862 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_auto_encoding.py - copied, changed from r62149, pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_auto_encoding.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_ri386.py - copied, changed from r62149, pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_ri386.py Log: Copy these two tests from the oo-jit branch. Copied: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_auto_encoding.py (from r62149, pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_auto_encoding.py) ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_auto_encoding.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_auto_encoding.py Wed Mar 11 17:14:41 2009 @@ -1,7 +1,7 @@ import os, random, string, struct import py -from pypy.jit.codegen.i386 import ri386 as i386 -from pypy.jit.codegen.i386.ri386setup import all_instructions +from pypy.jit.backend.x86 import ri386 as i386 +from pypy.jit.backend.x86.ri386setup import all_instructions from pypy.tool.udir import udir INPUTNAME = str(udir.join('checkfile.s')) Copied: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_ri386.py (from r62149, pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_ri386.py) ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_ri386.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_ri386.py Wed Mar 11 17:14:41 2009 @@ -1,5 +1,5 @@ import py -from pypy.jit.codegen.i386.ri386 import * +from pypy.jit.backend.x86.ri386 import * class CodeBuilder(I386CodeBuilder): def __init__(self): From afa at codespeak.net Wed Mar 11 17:21:54 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Mar 2009 17:21:54 +0100 (CET) Subject: [pypy-svn] r62863 - in pypy/trunk/pypy: module/bz2 rlib rpython/tool Message-ID: <20090311162154.68F59168451@codespeak.net> Author: afa Date: Wed Mar 11 17:21:52 2009 New Revision: 62863 Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py pypy/trunk/pypy/rlib/rzlib.py pypy/trunk/pypy/rpython/tool/rffi_platform.py Log: Translation on Windows can now find the bz2 and zlib libraries. Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/trunk/pypy/module/bz2/interp_bz2.py (original) +++ pypy/trunk/pypy/module/bz2/interp_bz2.py Wed Mar 11 17:21:52 2009 @@ -11,11 +11,22 @@ from pypy.rlib.rarithmetic import intmask, r_longlong import sys -class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes = ['stdio.h', 'sys/types.h', 'bzlib.h'], - libraries = ['bz2'], +if sys.platform == "win32": + libname = 'libbz2' +else: + libname = 'bz2' +eci = ExternalCompilationInfo( + includes = ['stdio.h', 'sys/types.h', 'bzlib.h'], + libraries = [libname], ) +eci = platform.configure_external_library( + 'bz2', eci, + [dict(prefix='bzip2-')]) +if not eci: + raise ImportError("Could not find bzip2 library") + +class CConfig: + _compilation_info_ = eci calling_conv = 'c' CHECK_LIBRARY = platform.Has('dump("x", (int)&BZ2_bzCompress)') Modified: pypy/trunk/pypy/rlib/rzlib.py ============================================================================== --- pypy/trunk/pypy/rlib/rzlib.py (original) +++ pypy/trunk/pypy/rlib/rzlib.py Wed Mar 11 17:21:52 2009 @@ -3,11 +3,20 @@ from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo -includes = ['zlib.h'] if sys.platform == "win32": - libraries = ['zlib'] + libname = 'zlib' else: - libraries = ['z'] + libname = 'z' +eci = ExternalCompilationInfo( + libraries=[libname], + includes=['zlib.h'] + ) +eci = rffi_platform.configure_external_library( + libname, eci, + [dict(prefix='zlib-'), + ]) +if not eci: + raise ImportError("Could not find a zlib library") constantnames = ''' @@ -23,9 +32,7 @@ """ Definitions for basic types defined by zlib. """ - _compilation_info_ = ExternalCompilationInfo( - includes = includes - ) + _compilation_info_ = eci # XXX If Z_PREFIX was defined for the libz build, then these types are # named z_uInt, z_uLong, and z_Bytef instead. @@ -67,9 +74,7 @@ Definitions of structure types defined by zlib and based on SimpleCConfig definitions. """ - _compilation_info_ = ExternalCompilationInfo( - includes = includes - ) + _compilation_info_ = eci z_stream = rffi_platform.Struct( 'z_stream', @@ -100,10 +105,7 @@ z_stream_p = lltype.Ptr(z_stream) def zlib_external(*a, **kw): - kw['compilation_info'] = ExternalCompilationInfo( - libraries=libraries, - includes=includes - ) + kw['compilation_info'] = eci return rffi.llexternal(*a, **kw) _crc32 = zlib_external('crc32', [uLong, Bytefp, uInt], uLong) Modified: pypy/trunk/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/trunk/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/trunk/pypy/rpython/tool/rffi_platform.py Wed Mar 11 17:21:52 2009 @@ -606,7 +606,7 @@ from pypy.tool.autopath import pypydir external_dir = py.path.local(pypydir).join('..', '..') - entries = glob.glob(str(external_dir.join(name + '*'))) + entries = glob.glob(str(external_dir.join(prefix + '*'))) if entries: # Get last version prefix = sorted(entries)[-1] From afa at codespeak.net Wed Mar 11 19:58:16 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Mar 2009 19:58:16 +0100 (CET) Subject: [pypy-svn] r62864 - pypy/trunk/dotviewer Message-ID: <20090311185816.6CFDF168465@codespeak.net> Author: afa Date: Wed Mar 11 19:58:14 2009 New Revision: 62864 Modified: pypy/trunk/dotviewer/graphclient.py pypy/trunk/dotviewer/msgstruct.py Log: graphviewer now uses the subprocess module instead of os.popen2. This works on Windows. And no need to hack the file mode any more :-) Modified: pypy/trunk/dotviewer/graphclient.py ============================================================================== --- pypy/trunk/dotviewer/graphclient.py (original) +++ pypy/trunk/dotviewer/graphclient.py Wed Mar 11 19:58:14 2009 @@ -1,4 +1,5 @@ import os, sys, re +import subprocess import msgstruct this_dir = os.path.dirname(os.path.abspath(__file__)) @@ -130,7 +131,9 @@ else: python = sys.executable cmdline = '"%s" -u "%s" --stdio' % (python, GRAPHSERVER) - child_in, child_out = os.popen2(cmdline, 'tb') + p = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, stdin=subprocess.PIPE) + child_in, child_out = p.stdin, p.stdout io = msgstruct.FileIO(child_out, child_in) return io Modified: pypy/trunk/dotviewer/msgstruct.py ============================================================================== --- pypy/trunk/dotviewer/msgstruct.py (original) +++ pypy/trunk/dotviewer/msgstruct.py Wed Mar 11 19:58:14 2009 @@ -84,10 +84,6 @@ class FileIO(IO): def __init__(self, f_in, f_out): - if sys.platform == 'win32': - import msvcrt - msvcrt.setmode(f_in.fileno(), os.O_BINARY) - msvcrt.setmode(f_out.fileno(), os.O_BINARY) self.f_in = f_in self.f_out = f_out From arigo at codespeak.net Wed Mar 11 20:01:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 20:01:26 +0100 (CET) Subject: [pypy-svn] r62865 - pypy/trunk/dotviewer Message-ID: <20090311190126.72E0116846A@codespeak.net> Author: arigo Date: Wed Mar 11 20:01:26 2009 New Revision: 62865 Modified: pypy/trunk/dotviewer/graphclient.py Log: Fix on Linux. Maybe we converge and this works on Windows too? :-) Modified: pypy/trunk/dotviewer/graphclient.py ============================================================================== --- pypy/trunk/dotviewer/graphclient.py (original) +++ pypy/trunk/dotviewer/graphclient.py Wed Mar 11 20:01:26 2009 @@ -130,8 +130,8 @@ python = 'python' else: python = sys.executable - cmdline = '"%s" -u "%s" --stdio' % (python, GRAPHSERVER) - p = subprocess.Popen(cmdline, + args = [python, '-u', GRAPHSERVER, '--stdio'] + p = subprocess.Popen(args, stdout=subprocess.PIPE, stdin=subprocess.PIPE) child_in, child_out = p.stdin, p.stdout io = msgstruct.FileIO(child_out, child_in) From arigo at codespeak.net Wed Mar 11 20:04:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Mar 2009 20:04:02 +0100 (CET) Subject: [pypy-svn] r62866 - pypy/branch/pyjitpl5/dotviewer Message-ID: <20090311190402.D4F79168035@codespeak.net> Author: arigo Date: Wed Mar 11 20:04:02 2009 New Revision: 62866 Modified: pypy/branch/pyjitpl5/dotviewer/graphclient.py pypy/branch/pyjitpl5/dotviewer/msgstruct.py Log: Merge r62864-r62865 from the trunk. Modified: pypy/branch/pyjitpl5/dotviewer/graphclient.py ============================================================================== --- pypy/branch/pyjitpl5/dotviewer/graphclient.py (original) +++ pypy/branch/pyjitpl5/dotviewer/graphclient.py Wed Mar 11 20:04:02 2009 @@ -1,4 +1,5 @@ import os, sys, re +import subprocess import msgstruct this_dir = os.path.dirname(os.path.abspath(__file__)) @@ -129,8 +130,10 @@ python = 'python' else: python = sys.executable - cmdline = '"%s" -u "%s" --stdio' % (python, GRAPHSERVER) - child_in, child_out = os.popen2(cmdline, 'tb') + args = [python, '-u', GRAPHSERVER, '--stdio'] + p = subprocess.Popen(args, + stdout=subprocess.PIPE, stdin=subprocess.PIPE) + child_in, child_out = p.stdin, p.stdout io = msgstruct.FileIO(child_out, child_in) return io Modified: pypy/branch/pyjitpl5/dotviewer/msgstruct.py ============================================================================== --- pypy/branch/pyjitpl5/dotviewer/msgstruct.py (original) +++ pypy/branch/pyjitpl5/dotviewer/msgstruct.py Wed Mar 11 20:04:02 2009 @@ -84,10 +84,6 @@ class FileIO(IO): def __init__(self, f_in, f_out): - if sys.platform == 'win32': - import msvcrt - msvcrt.setmode(f_in.fileno(), os.O_BINARY) - msvcrt.setmode(f_out.fileno(), os.O_BINARY) self.f_in = f_in self.f_out = f_out From fijal at codespeak.net Wed Mar 11 21:54:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 21:54:40 +0100 (CET) Subject: [pypy-svn] r62867 - in pypy/branch: pyjitpl5 pyjitpl5-bck Message-ID: <20090311205440.CB8C1168487@codespeak.net> Author: fijal Date: Wed Mar 11 21:54:39 2009 New Revision: 62867 Added: pypy/branch/pyjitpl5-bck/ - copied from r62866, pypy/branch/pyjitpl5/ Removed: pypy/branch/pyjitpl5/ Log: Move away branch which is more or less broken From fijal at codespeak.net Wed Mar 11 21:55:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Mar 2009 21:55:52 +0100 (CET) Subject: [pypy-svn] r62868 - pypy/branch/pyjitpl5 Message-ID: <20090311205552.0716C168494@codespeak.net> Author: fijal Date: Wed Mar 11 21:55:52 2009 New Revision: 62868 Added: pypy/branch/pyjitpl5/ - copied from r62867, pypy/trunk/ Log: branch again From fijal at codespeak.net Thu Mar 12 09:21:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 09:21:51 +0100 (CET) Subject: [pypy-svn] r62870 - pypy/trunk/pypy/jit/backend/x86/test Message-ID: <20090312082151.5B6AA16848F@codespeak.net> Author: fijal Date: Thu Mar 12 09:21:47 2009 New Revision: 62870 Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py Log: skip only single test Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_slist.py Thu Mar 12 09:21:47 2009 @@ -1,6 +1,5 @@ import py -py.test.skip("XXX fails") from pypy.jit.metainterp.test.test_slist import ListTests from pypy.jit.backend.x86.support import c_meta_interp @@ -12,6 +11,9 @@ def check_loops(self, *args, **kwds): pass + def interp_operations(self, *args, **kwds): + py.test.skip("Uses interp_operations") + class TestSList(Jit386Mixin, ListTests): # for the individual tests see # ====> ../../test/test_slist.py From nshepperd at codespeak.net Thu Mar 12 09:41:59 2009 From: nshepperd at codespeak.net (nshepperd at codespeak.net) Date: Thu, 12 Mar 2009 09:41:59 +0100 (CET) Subject: [pypy-svn] r62871 - pypy/trunk/pypy/translator/tool Message-ID: <20090312084159.F2201168490@codespeak.net> Author: nshepperd Date: Thu Mar 12 09:41:59 2009 New Revision: 62871 Modified: pypy/trunk/pypy/translator/tool/cbuild.py Log: Fix from_config_tool calling py.process.cmdexec with a list as cmd, which changes semantics. Modified: pypy/trunk/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/trunk/pypy/translator/tool/cbuild.py (original) +++ pypy/trunk/pypy/translator/tool/cbuild.py Thu Mar 12 09:41:59 2009 @@ -147,9 +147,9 @@ raise ImportError("cannot find %r" % (execonfigtool,)) # we raise ImportError to be nice to the pypy.config.pypyoption # logic of skipping modules depending on non-installed libs - cflags = py.process.cmdexec([str(path), '--cflags']) + cflags = py.process.cmdexec('"%s" --cflags' % (str(path),)) eci1 = cls.from_compiler_flags(cflags) - libs = py.process.cmdexec([str(path), '--libs']) + libs = py.process.cmdexec('"%s" --libs' % (str(path),)) eci2 = cls.from_linker_flags(libs) return eci1.merge(eci2) from_config_tool = classmethod(from_config_tool) From fijal at codespeak.net Thu Mar 12 09:46:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 09:46:23 +0100 (CET) Subject: [pypy-svn] r62872 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312084623.506AF168490@codespeak.net> Author: fijal Date: Thu Mar 12 09:46:22 2009 New Revision: 62872 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: kill LLDEBUG hack, let's come with something saner Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 12 09:46:22 2009 @@ -24,8 +24,6 @@ for arg in args: assert isinstance(arg, (Box, Const)) -LLDEBUG = False - class arguments(object): def __init__(self, *argtypes, **kwargs): self.result = kwargs.pop("returns", None) @@ -613,8 +611,6 @@ op = ord(self.bytecode[pc]) #print self.metainterp.opcode_names[op] self.pc = pc + 1 - if LLDEBUG: - print "EXECUTE %d %d" % (pc, op) stop = self.metainterp.opcode_implementations[op](self, pc) #self.metainterp.most_recent_mp = None if stop: @@ -671,8 +667,6 @@ if not we_are_translated(): self.metainterp._debug_history.append(['call', argboxes[0], argboxes[1:]]) - elif LLDEBUG: - print "CALL %d" % argboxes[0].getint() # record the operation in the history self.metainterp.history.record(opnum, argboxes, resbox, descr) if resbox is not None: @@ -724,8 +718,6 @@ self._recompute_class_sizes() if not we_are_translated(): self._debug_history.append(['enter', jitcode, None]) - elif LLDEBUG: - print "ENTER %s" % jitcode.name f = MIFrame(self, jitcode) self.framestack.append(f) return f @@ -734,9 +726,6 @@ frame = self.framestack.pop() if not we_are_translated(): self._debug_history.append(['leave', frame.jitcode, None]) - else: - if LLDEBUG: - print "LEAVE %s" % frame.jitcode.name if self.framestack: if resultbox is not None: self.framestack[-1].make_result_box(resultbox) @@ -755,8 +744,6 @@ return True if not we_are_translated(): self._debug_history.append(['leave_exc', frame.jitcode, None]) - elif LLDEBUG: - print "LEAVE_EXC %s" % frame.jitcode.name self.framestack.pop() raise self.ExitFrameWithException(exceptionbox, excvaluebox) @@ -985,8 +972,6 @@ def rebuild_state_after_failure(self, key, newboxes): if not we_are_translated(): self._debug_history.append(['guard_failure', None, None]) - elif LLDEBUG: - print "GUARD_FAILURE" self.framestack = [] nbindex = 0 for jitcode, pc, envlength, exception_target in key: From arigo at codespeak.net Thu Mar 12 10:57:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 10:57:44 +0100 (CET) Subject: [pypy-svn] r62873 - in pypy/branch/pyjitpl5/pypy/translator/backendopt: . test Message-ID: <20090312095744.EB78216849E@codespeak.net> Author: arigo Date: Thu Mar 12 10:57:42 2009 New Revision: 62873 Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py Log: Merge a checkin by cfbolz: Write a simple inlining heuristic that never inlines graphs that have an oopspec attached. Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/backendopt/inline.py Thu Mar 12 10:57:42 2009 @@ -624,6 +624,12 @@ return (0.9999 * measure_median_execution_cost(graph) + count), True +def inlining_heuristic_no_oopspec(graph): + try: + oopspec = graph.func.oopspec + except AttributeError: + return inlining_heuristic(graph) + return (sys.maxint, True) def inlinable_static_callers(graphs): ok_to_call = dict.fromkeys(graphs) Modified: pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/backendopt/test/test_inline.py Thu Mar 12 10:57:42 2009 @@ -9,6 +9,7 @@ from pypy.translator.backendopt.inline import collect_called_graphs from pypy.translator.backendopt.inline import measure_median_execution_cost from pypy.translator.backendopt.inline import instrument_inline_candidates +from pypy.translator.backendopt.inline import inlining_heuristic_no_oopspec from pypy.translator.backendopt.checkvirtual import check_virtual_methods from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.llinterp import LLInterpreter @@ -92,7 +93,7 @@ return eval_func def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False, - checkvirtual=False, remove_same_as=False): + checkvirtual=False, remove_same_as=False, heuristic=None): t = self.translate(func, sig) if checkvirtual: check_virtual_methods() @@ -114,7 +115,11 @@ for graph in t.graphs: removenoops.remove_same_as(graph) - auto_inlining(t, threshold, call_count_pred=call_count_pred) + if heuristic is not None: + kwargs = {"heuristic": heuristic} + else: + kwargs = {} + auto_inlining(t, threshold, call_count_pred=call_count_pred, **kwargs) sanity_check(t) if option.view: @@ -597,6 +602,24 @@ res = eval_func([]) assert res == 5 + def test_no_oopspec_inliner(self): + def f(): + tot = 0 + for item in [1,2,3]: + tot += item + return tot + + eval_func, t = self.check_auto_inlining( + f, [], heuristic=inlining_heuristic_no_oopspec) + f_graph = graphof(t, f) + called_graphs = collect_called_graphs(f_graph, t, include_oosend=False) + print called_graphs + assert len(called_graphs) == 4 # newlist, setitem, getitem, length + + result = eval_func([]) + assert result == 6 + + class TestInlineOOType(OORtypeMixin, BaseTestInline): From arigo at codespeak.net Thu Mar 12 10:58:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 10:58:13 +0100 (CET) Subject: [pypy-svn] r62874 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090312095813.14E6F16849E@codespeak.net> Author: arigo Date: Thu Mar 12 10:58:13 2009 New Revision: 62874 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_auto_encoding.py - copied unchanged from r62862, pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_auto_encoding.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_ri386.py - copied unchanged from r62862, pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_ri386.py Log: Merge a checkin by me: Copy these two tests from the oo-jit branch. From arigo at codespeak.net Thu Mar 12 11:27:42 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 11:27:42 +0100 (CET) Subject: [pypy-svn] r62875 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090312102742.9A9DB168449@codespeak.net> Author: arigo Date: Thu Mar 12 11:27:40 2009 New Revision: 62875 Added: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: A translation target, for trying to translate the JIT with PyPy. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Mar 12 11:27:40 2009 @@ -25,10 +25,10 @@ config.translation.rweakref = False # XXX set_pypy_opt_level(config, level='0') config.objspace.std.multimethods = 'mrd' +multimethod.Installer = multimethod.InstallerVersion2 config.objspace.std.builtinshortcut = True config.objspace.opcodes.CALL_LIKELY_BUILTIN = True config.objspace.std.withrangelist = True -multimethod.Installer = multimethod.InstallerVersion2 print config import sys, pdb Added: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py Thu Mar 12 11:27:40 2009 @@ -0,0 +1,72 @@ +from pypy.config.config import to_optparse, SUPPRESS_USAGE + +take_options = True + + +def readfile(filename): + import os + fd = os.open(filename, os.O_RDONLY, 0) + blocks = [] + while True: + data = os.read(fd, 4096) + if not data: + break + blocks.append(data) + os.close(fd) + return ''.join(blocks) + +def entry_point(args): + from pypy.interpreter.pycode import PyCode + source = readfile('pypyjit_demo.py') + ec = space.getexecutioncontext() + code = ec.compiler.compile(source, '?', 'exec', 0) + assert isinstance(code, PyCode) + code.exec_code(space, w_dict, w_dict) + return 0 + +def opt_parser(config): + parser = to_optparse(config, useoptions=["objspace.*"], + parserkwargs={'usage': SUPPRESS_USAGE}) + return parser + +def handle_config(config, translateconfig): + # set up the objspace optimizations based on the --opt argument + from pypy.config.pypyoption import set_pypy_opt_level + set_pypy_opt_level(config, translateconfig.opt) + +def get_additional_config_options(): + from pypy.config.pypyoption import pypy_optiondescription + return pypy_optiondescription + +def target(driver, args): + from pypy.tool.option import make_objspace + from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy + from pypy.objspace.std import multimethod + global space, w_dict + # + config = driver.config + parser = opt_parser(config) + parser.parse_args(args) + # + config.objspace.compiler = 'ast' + config.objspace.nofaking = True + config.objspace.allworkingmodules = False + config.objspace.usemodules.pypyjit = True + config.objspace.usemodules._weakref = False + config.objspace.usemodules._sre = False + config.translation.rweakref = False # XXX + config.objspace.std.multimethods = 'mrd' + multimethod.Installer = multimethod.InstallerVersion2 + config.objspace.std.builtinshortcut = True + config.objspace.opcodes.CALL_LIKELY_BUILTIN = True + config.objspace.std.withrangelist = True + # + print config + space = make_objspace(config) + w_dict = space.newdict() + return entry_point, None, PyPyAnnotatorPolicy(single_space = space) + +def jitpolicy(driver): + """Returns the JIT policy to use when translating.""" + from pypy.module.pypyjit.portal import PyPyJitPolicy + return PyPyJitPolicy(driver.translator) From arigo at codespeak.net Thu Mar 12 12:09:04 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 12:09:04 +0100 (CET) Subject: [pypy-svn] r62876 - in pypy/branch/pyjitpl5/pypy/rpython/lltypesystem: . test Message-ID: <20090312110904.654FC168499@codespeak.net> Author: arigo Date: Thu Mar 12 12:09:03 2009 New Revision: 62876 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Fix jit/backend/x86/test_send by removing this code. Requires adding a "normalize=False" argument to a test in test_ll2ctypes, which I think is ok (see comment). Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Thu Mar 12 12:09:03 2009 @@ -626,13 +626,7 @@ 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, [], - len(getattr(storage, T.TO._arrayfld).items)) - # make sure you cache according to the len() above! - p = ctypes.cast(p, ctypes.POINTER(c_tp)) - elif normalize and hasattr(storage, '_normalized_ctype'): + if normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) return p Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Mar 12 12:09:03 2009 @@ -120,7 +120,10 @@ a.y[0] = 'x' a.y[1] = 'y' a.y[2] = 'z' - ac = lltype2ctypes(a) + # we need to pass normalize=False, otherwise 'ac' is returned of + # a normalized standard type, which complains about IndexError + # when doing 'ac.contents.y.items[2]'. + ac = lltype2ctypes(a, normalize=False) assert ac.contents.y.length == 3 assert ac.contents.y.items[2] == ord('z') lltype.free(a, flavor='raw') From fijal at codespeak.net Thu Mar 12 12:17:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 12:17:57 +0100 (CET) Subject: [pypy-svn] r62877 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312111757.0C942168487@codespeak.net> Author: fijal Date: Thu Mar 12 12:17:55 2009 New Revision: 62877 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: a port from pyjitpl5-bck branch Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Thu Mar 12 12:17:55 2009 @@ -439,7 +439,7 @@ elif size == WORD: a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) if not ptr: - a[ofs/WORD + field] = args[2].getint() + a[ofs/WORD + field] = int(args[2].getint()) else: p = args[2].getptr(llmemory.GCREF) a[ofs/WORD + field] = self.cast_gcref_to_int(p) From arigo at codespeak.net Thu Mar 12 12:20:53 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 12:20:53 +0100 (CET) Subject: [pypy-svn] r62878 - in pypy/branch/pyjitpl5/pypy/jit: backend/x86 metainterp Message-ID: <20090312112053.0F463168487@codespeak.net> Author: arigo Date: Thu Mar 12 12:20:50 2009 New Revision: 62878 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: getint() should return an int. Improve the previous fix. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Thu Mar 12 12:20:50 2009 @@ -439,7 +439,7 @@ elif size == WORD: a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref) if not ptr: - a[ofs/WORD + field] = int(args[2].getint()) + a[ofs/WORD + field] = args[2].getint() else: p = args[2].getptr(llmemory.GCREF) a[ofs/WORD + field] = self.cast_gcref_to_int(p) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 12 12:20:50 2009 @@ -125,7 +125,10 @@ def __init__(self, value): if not we_are_translated(): - assert isinstance(value, (int, ComputedIntSymbolic)) + if isinstance(value, int): + value = int(value) # bool -> int + else: + assert isinstance(value, ComputedIntSymbolic) self.value = value def clonebox(self): @@ -251,7 +254,10 @@ def __init__(self, value=0): if not we_are_translated(): - assert isinstance(value, (int, ComputedIntSymbolic)) + if isinstance(value, int): + value = int(value) # bool -> int + else: + assert isinstance(value, ComputedIntSymbolic) self.value = value def clonebox(self): From fijal at codespeak.net Thu Mar 12 12:26:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 12:26:34 +0100 (CET) Subject: [pypy-svn] r62879 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090312112634.8E629168487@codespeak.net> Author: fijal Date: Thu Mar 12 12:26:34 2009 New Revision: 62879 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py Log: config fix Modified: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py Thu Mar 12 12:26:34 2009 @@ -54,7 +54,6 @@ config.objspace.usemodules.pypyjit = True config.objspace.usemodules._weakref = False config.objspace.usemodules._sre = False - config.translation.rweakref = False # XXX config.objspace.std.multimethods = 'mrd' multimethod.Installer = multimethod.InstallerVersion2 config.objspace.std.builtinshortcut = True From cfbolz at codespeak.net Thu Mar 12 12:43:41 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 12 Mar 2009 12:43:41 +0100 (CET) Subject: [pypy-svn] r62880 - pypy/trunk/pypy/lang/smalltalk Message-ID: <20090312114341.949CC168487@codespeak.net> Author: cfbolz Date: Thu Mar 12 12:43:40 2009 New Revision: 62880 Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py pypy/trunk/pypy/lang/smalltalk/wrapper.py Log: some tiny cleanups, an XXX Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/primitives.py (original) +++ pypy/trunk/pypy/lang/smalltalk/primitives.py Thu Mar 12 12:43:40 2009 @@ -299,7 +299,7 @@ @expose_primitive(MAKE_POINT, unwrap_spec=[int, int]) def func(interp, x, y): - w_res = interp.space.classtable['w_Point'].as_class_get_shadow(interp.space).new(2) + w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2) point = wrapper.PointWrapper(interp.space, w_res) point.store_x(interp.space, x) point.store_y(interp.space, y) @@ -771,7 +771,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Semaphore']): + interp.space.w_Semaphore): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(interp) return w_rcvr @@ -780,7 +780,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Semaphore']): + interp.space.w_Semaphore): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(interp) return w_rcvr @@ -789,7 +789,7 @@ def func(interp, w_rcvr,): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Process']): + interp.space.w_Process): raise PrimitiveFailedError() wrapper.ProcessWrapper(interp.space, w_rcvr).resume(interp) return w_rcvr @@ -798,7 +798,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Process']): + interp.space.w_Process): raise PrimitiveFailedError() wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(interp) return w_rcvr Modified: pypy/trunk/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/trunk/pypy/lang/smalltalk/wrapper.py Thu Mar 12 12:43:40 2009 @@ -11,12 +11,14 @@ def read(self, index0): try: return self.w_self.fetch(self.space, index0) + # XXX Index error never raised after translation except IndexError: raise WrapperException("Unexpected instance layout. Too small") def write(self, index0, w_new): try: self.w_self.store(self.space, index0, w_new) + # XXX Index error never raised after translation except IndexError: raise WrapperException("Unexpected instance layout. Too small") @@ -51,12 +53,9 @@ class ProcessWrapper(LinkWrapper): suspended_context, store_suspended_context = make_getter_setter(1) + priority = make_int_getter(2) my_list, store_my_list = make_getter_setter(3) - def priority(self): - w_priority = self.read(2) - return self.space.unwrap_int(w_priority) - def put_to_sleep(self): sched = scheduler(self.space) priority = self.priority() From fijal at codespeak.net Thu Mar 12 13:06:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 13:06:34 +0100 (CET) Subject: [pypy-svn] r62881 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090312120634.54991168487@codespeak.net> Author: fijal Date: Thu Mar 12 13:06:32 2009 New Revision: 62881 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: actually use existing infrastructure from fork-before Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Mar 12 13:06:32 2009 @@ -12,6 +12,7 @@ from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem import lltype from pypy.interpreter.pycode import PyCode +from pypy.translator.goal import unixcheckpoint config = get_pypy_config(translating=True) config.translation.backendopt.inline_threshold = 0 @@ -81,23 +82,7 @@ # parent process loop: spawn a child, wait for the child to finish, # print a message, and restart - while True: - child_pid = os.fork() - if child_pid == 0: - break - try: - os.waitpid(child_pid, 0) - except KeyboardInterrupt: - pass - print '-' * 79 - print 'Child process finished, press Enter to restart...' - try: - raw_input() - except KeyboardInterrupt: - x = raw_input("are you sure? (y/n)") - if x == 'y': - raise - # otherwise continue + unixcheckpoint.restartable_point(auto='run') from pypy.jit.tl.pypyjit_child import run_child run_child(globals(), locals()) From fijal at codespeak.net Thu Mar 12 13:07:30 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 13:07:30 +0100 (CET) Subject: [pypy-svn] r62882 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090312120730.10003168487@codespeak.net> Author: fijal Date: Thu Mar 12 13:07:30 2009 New Revision: 62882 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: this is also not needed any more Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Thu Mar 12 13:07:30 2009 @@ -3,7 +3,6 @@ from pypy.jit.metainterp import warmspot from pypy.module.pypyjit.portal import PyPyJitPolicy - # Current output: http://paste.pocoo.org/show/106540/ # # Some optimizations missing: @@ -37,9 +36,5 @@ print 'warmspot.jittify_and_run() started...' policy = PyPyJitPolicy(interp.typer.annotator.translator) option.view = True - try: - warmspot.jittify_and_run(interp, graph, [], policy=policy, - listops=True) - except Exception, e: - print '%s: %s' % (e.__class__, e) - pdb.post_mortem(sys.exc_info()[2]) + warmspot.jittify_and_run(interp, graph, [], policy=policy, + listops=True) From arigo at codespeak.net Thu Mar 12 13:16:51 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 13:16:51 +0100 (CET) Subject: [pypy-svn] r62883 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/x86 backend/x86/test metainterp metainterp/test Message-ID: <20090312121651.1E863168487@codespeak.net> Author: arigo Date: Thu Mar 12 13:16:48 2009 New Revision: 62883 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Merge r62784 from pyjitpl5-bck: use instances of AbstractValue instead of plain integers as descrs. (Cannot run tests so far...) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 12 13:16:48 2009 @@ -520,43 +520,45 @@ # delegating to the builtins do_xxx() (done automatically for simple cases) def op_getarrayitem_gc(self, arraydescr, array, index): - if arraydescr & 1: + if arraydescr.getint() & 1: return do_getarrayitem_gc_ptr(array, index) else: return do_getarrayitem_gc_int(array, index, self.memocast) def op_getfield_gc(self, fielddescr, struct): + fielddescr = fielddescr.getint() if fielddescr & 1: return do_getfield_gc_ptr(struct, fielddescr) else: return do_getfield_gc_int(struct, fielddescr, self.memocast) def op_getfield_raw(self, fielddescr, struct): - if fielddescr & 1: + if fielddescr.getint() & 1: return do_getfield_raw_ptr(struct, fielddescr) else: return do_getfield_raw_int(struct, fielddescr, self.memocast) def op_new_with_vtable(self, size, vtable): - result = do_new(size) + result = do_new(size.getint()) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): - if arraydescr & 1: + if arraydescr.getint() & 1: do_setarrayitem_gc_ptr(array, index, newvalue) else: do_setarrayitem_gc_int(array, index, newvalue, self.memocast) def op_setfield_gc(self, fielddescr, struct, newvalue): + fielddescr = fielddescr.getint() if fielddescr & 1: do_setfield_gc_ptr(struct, fielddescr, newvalue) else: do_setfield_gc_int(struct, fielddescr, newvalue, self.memocast) def op_setfield_raw(self, fielddescr, struct, newvalue): - if fielddescr & 1: + if fielddescr.getint() & 1: do_setfield_raw_ptr(struct, fielddescr, newvalue) else: do_setfield_raw_int(struct, fielddescr, newvalue, self.memocast) @@ -565,12 +567,15 @@ _call_args[:] = args if calldescr == sys.maxint: err_result = None - elif calldescr & 1: + elif calldescr.getint() & 1: err_result = lltype.nullptr(llmemory.GCREF.TO) else: err_result = 0 return _do_call_common(func, self.memocast, err_result) + def op_new_array(self, arraydescr, count): + return do_new_array(arraydescr.getint(), count) + # ____________________________________________________________ def cast_to_int(x, memocast): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 12 13:16:48 2009 @@ -186,7 +186,7 @@ @staticmethod def sizeof(S): - return symbolic.get_size(S) + return history.ConstInt(symbolic.get_size(S)) @staticmethod def numof(S): @@ -202,7 +202,7 @@ bit = 1 else: bit = 0 - return ofs*2 + bit + return history.ConstInt(ofs*2 + bit) @staticmethod def arraydescrof(A): @@ -213,7 +213,7 @@ bit = 1 else: bit = 0 - return size*2 + bit + return history.ConstInt(size*2 + bit) @staticmethod def calldescrof(ARGS, RESULT): @@ -227,6 +227,7 @@ @staticmethod def typefor(fielddesc): + fielddesc = fielddesc.getint() if fielddesc == sys.maxint: return 'void' if fielddesc % 2: @@ -249,6 +250,12 @@ def cast_int_to_adr(self, int): return llimpl.cast_int_to_adr(self.memo_cast, int) + def ofs_from_descr(self, descr): + return descr.getint() + + def repack_descr(self, ofs): + return history.ConstInt(ofs) + # ---------- the backend-dependent operations ---------- def do_arraylen_gc(self, args, arraydescr): @@ -273,9 +280,10 @@ return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, self.memo_cast)) - def do_getfield_gc(self, args, fielddescr): + def do_getfield_gc(self, args, fieldbox): + fielddescr = fieldbox.getint() struct = args[0].getptr_base() - if self.typefor(fielddescr) == 'ptr': + if self.typefor(fieldbox) == 'ptr': return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, fielddescr)) else: @@ -294,18 +302,18 @@ self.memo_cast)) def do_new(self, args, size): - return history.BoxPtr(llimpl.do_new(size)) + return history.BoxPtr(llimpl.do_new(size.getint())) def do_new_with_vtable(self, args, size): vtable = args[0].getint() - result = llimpl.do_new(size) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable, vtable, - self.memo_cast) + result = llimpl.do_new(size.getint()) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.getint(), + vtable, self.memo_cast) return history.BoxPtr(result) def do_new_array(self, args, size): count = args[0].getint() - return history.BoxPtr(llimpl.do_new_array(size, count)) + return history.BoxPtr(llimpl.do_new_array(size.getint(), count)) def do_setarrayitem_gc(self, args, arraydescr): array = args[0].getptr_base() @@ -318,9 +326,10 @@ llimpl.do_setarrayitem_gc_int(array, index, newvalue, self.memo_cast) - def do_setfield_gc(self, args, fielddescr): + def do_setfield_gc(self, args, fieldbox): + fielddescr = fieldbox.getint() struct = args[0].getptr_base() - if self.typefor(fielddescr) == 'ptr': + if self.typefor(fieldbox) == 'ptr': newvalue = args[1].getptr_base() llimpl.do_setfield_gc_ptr(struct, fielddescr, newvalue) else: @@ -329,6 +338,7 @@ self.memo_cast) def do_setfield_raw(self, args, fielddescr): + fielddescr = fielddescr.getint() struct = self.cast_int_to_adr(args[0].getint()) if self.typefor(fielddescr) == 'ptr': newvalue = args[1].getptr_base() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 12 13:16:48 2009 @@ -68,7 +68,7 @@ self.make_sure_mc_exists() op0 = operations[0] op0.position = self.mc.tell() - regalloc = RegAlloc(operations, guard_op) + regalloc = RegAlloc(operations, guard_op, self.cpu.translate_support_code) if not we_are_translated(): self._regalloc = regalloc # for debugging computed_ops = regalloc.computed_ops @@ -405,7 +405,8 @@ def genop_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.cpu.translate_support_code) self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize), lower_byte(val_loc)) @@ -413,7 +414,8 @@ def genop_strlen(self, op, arglocs, resloc): base_loc = arglocs[0] - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.cpu.translate_support_code) self.mc.MOV(resloc, addr_add_const(base_loc, ofs_length)) def genop_arraylen_gc(self, op, arglocs, resloc): @@ -422,7 +424,8 @@ def genop_strgetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.cpu.translate_support_code) self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize)) def genop_merge_point(self, op, locs): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 13:16:48 2009 @@ -99,8 +99,9 @@ raise ValueError("convert_to_imm: got a %s" % c) class RegAlloc(object): - def __init__(self, operations, guard_op=None): + def __init__(self, operations, guard_op=None, translate_support_code=False): # variables that have place in register + self.translate_support_code = translate_support_code self.reg_bindings = newcheckdict() self.stack_bindings = {} # compute longevity of variables @@ -731,16 +732,14 @@ consider_call_pure = consider_call def consider_new(self, op, ignored): - return self._call(op, [imm(op.descr)]) + return self._call(op, [imm(op.descr.getint())]) def consider_new_with_vtable(self, op, ignored): - return self._call(op, [imm(op.descr), self.loc(op.args[0])]) + return self._call(op, [imm(op.descr.getint()), self.loc(op.args[0])]) def consider_newstr(self, op, ignored): - ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] - ofs_items = symbolic.get_field_token(rstr.STR.chars, 'items')[0] - ofs_length = symbolic.get_field_token(rstr.STR.chars, 'length')[0] - return self._malloc_varsize(ofs, ofs_items, ofs_length, 0, op.args[0], + ofs_items, _, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code) + return self._malloc_varsize(0, ofs_items, ofs, 0, op.args[0], op.result) def _malloc_varsize(self, ofs, ofs_items, ofs_length, size, v, res_v): @@ -768,7 +767,7 @@ return res def consider_new_array(self, op, ignored): - size_of_field, basesize = self._unpack_arraydescr(op.descr) + size_of_field, basesize, _ = self._unpack_arraydescr(op.descr) return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[0], op.result) @@ -805,7 +804,7 @@ [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) def consider_setarrayitem_gc(self, op, ignored): - scale, ofs = self._unpack_arraydescr(op.descr) + scale, ofs, _ = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) @@ -825,7 +824,7 @@ consider_getfield_gc_pure = consider_getfield_gc def consider_getarrayitem_gc(self, op, ignored): - scale, ofs = self._unpack_arraydescr(op.descr) + scale, ofs, _ = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars(op.args) @@ -891,7 +890,7 @@ return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] def consider_arraylen_gc(self, op, ignored): - _, ofs = self._unpack_arraydescr(op.descr) + _, ofs, _ = self._unpack_arraydescr(op.descr) base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) result_loc, more_ops = self.force_allocate_reg(op.result, []) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Thu Mar 12 13:16:48 2009 @@ -4,11 +4,11 @@ from pypy.rpython.lltypesystem import lltype, llmemory, ll2ctypes, rffi, rstr from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize +from pypy.rlib.objectmodel import CDefinedIntSymbolic, specialize, Symbolic from pypy.rlib.objectmodel import we_are_translated, keepalive_until_here from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import rclass -from pypy.jit.metainterp import history +from pypy.jit.metainterp import history, codewriter from pypy.jit.metainterp.history import (ResOperation, Box, Const, ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN @@ -23,6 +23,32 @@ PTR = 1 INT = 2 +class ConstDescr3(Const): + def __init__(self, v): + self.v = v + + def _v(self): + l = [] + for i in self.v: + if isinstance(i, Symbolic): + l.append(id(i)) + else: + l.append(i) + return tuple(l) + + + def __hash__(self): + return hash(self._v()) + + def __eq__(self, other): + return self.__class__ is other.__class__ and self._v() == other._v() + + def __ne__(self, other): + return not self == other + + def _getrepr_(self): + return repr(self.v) + class CPU386(object): debug = True @@ -383,7 +409,7 @@ frame[mp.stacklocs[argindex]] = self.convert_box_to_int(valuebox) def sizeof(self, S): - return symbolic.get_size(S) + return ConstInt(symbolic.get_size(S, self.translate_support_code)) numof = sizeof # addresssuffix = str(symbolic.get_size(llmemory.Address)) @@ -405,11 +431,7 @@ def do_getarrayitem_gc(self, args, arraydescr): field = args[1].getint() gcref = args[0].getptr(llmemory.GCREF) - if arraydescr < 0: - ptr = True - else: - ptr = False - shift, ofs = self.unpack_arraydescr(arraydescr) + shift, ofs, ptr = self.unpack_arraydescr(arraydescr) size = 1 << shift if size == 1: return BoxInt(ord(rffi.cast(rffi.CArrayPtr(lltype.Char), gcref) @@ -427,11 +449,7 @@ def do_setarrayitem_gc(self, args, arraydescr): field = args[1].getint() gcref = args[0].getptr(llmemory.GCREF) - if arraydescr < 0: - ptr = True - else: - ptr = False - shift, ofs = self.unpack_arraydescr(arraydescr) + shift, ofs, ptr = self.unpack_arraydescr(arraydescr) size = 1 << shift if size == 1: v = args[2].getint() @@ -447,13 +465,15 @@ raise NotImplementedError("size = %d" % size) def do_strlen(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) gcref = args[0].getptr(llmemory.GCREF) v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] return BoxInt(v) def do_strgetitem(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) gcref = args[0].getptr(llmemory.GCREF) i = args[1].getint() v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] @@ -509,16 +529,16 @@ self._base_do_setfield(fielddescr, args[0].getint(), args[1]) def do_new(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize) + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.getint()) return BoxPtr(self.cast_int_to_gcref(res)) def do_new_with_vtable(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize) + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.getint()) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[0].getint() return BoxPtr(self.cast_int_to_gcref(res)) def do_new_array(self, args, arraydescr): - size_of_field, ofs = self.unpack_arraydescr(arraydescr) + size_of_field, ofs, ptr = self.unpack_arraydescr(arraydescr) num_elem = args[0].getint() size = ofs + (1 << size_of_field) * num_elem res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) @@ -526,7 +546,8 @@ return BoxPtr(self.cast_int_to_gcref(res)) def do_newstr(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) assert itemsize == 1 num_elem = args[0].getint() size = basesize + num_elem @@ -535,7 +556,8 @@ return BoxPtr(self.cast_int_to_gcref(res)) def do_strsetitem(self, args, descr=0): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, + self.translate_support_code) index = args[1].getint() v = args[2].getint() a = args[0].getptr(llmemory.GCREF) @@ -565,73 +587,80 @@ adr = llmemory.cast_ptr_to_adr(x) return CPU386.cast_adr_to_int(adr) - @staticmethod - def arraydescrof(A): + def arraydescrof(self, A): assert isinstance(A, lltype.GcArray) - basesize, itemsize, ofs_length = symbolic.get_array_token(A) + basesize, itemsize, ofs_length = symbolic.get_array_token(A, + self.translate_support_code) assert ofs_length == 0 - counter = 0 - while itemsize != 1: - itemsize >>= 1 - counter += 1 - res = basesize + counter * 0x10000 if isinstance(A.OF, lltype.Ptr): - res = ~res + ptr = True + else: + ptr = False + return ConstDescr3((basesize, itemsize, ptr)) + + def ofs_from_descr(self, descr): + assert isinstance(descr, ConstDescr3) + x = (descr.v[0] << 16) + descr.v[1] + if descr.v[2]: + return ~x + return x + + def repack_descr(self, ofs): + orig_ofs = ofs + if ofs < 0: + ptr = True + ofs = ~ofs + else: + ptr = False + res = ConstDescr3((ofs>>16, ofs & 0xffff, ptr)) + assert self.ofs_from_descr(res) == orig_ofs return res @staticmethod def unpack_arraydescr(arraydescr): - # XXX move it to some saner place, regalloc is using it - if arraydescr < 0: - arraydescr = ~arraydescr - assert arraydescr - size_of_field = arraydescr >> 16 - ofs = arraydescr & 0xffff - return size_of_field, ofs + assert isinstance(arraydescr, ConstDescr3) + basesize, itemsize, ptr = arraydescr.v + counter = 0 + while itemsize != 1: + itemsize >>= 1 + counter += 1 + return counter, basesize, ptr - @staticmethod - def calldescrof(argtypes, resulttype): + def calldescrof(self, argtypes, resulttype): if resulttype is lltype.Void: size = 0 else: - size = symbolic.get_size(resulttype) - res = (len(argtypes) << 4) + size + size = symbolic.get_size(resulttype, self.translate_support_code) if isinstance(resulttype, lltype.Ptr): - return ~res - return res - - @staticmethod - def unpack_calldescr(calldescr): - if calldescr < 0: - calldescr = ~calldescr ptr = True else: ptr = False - return calldescr >> 4, calldescr & 0xf, ptr + return ConstDescr3((len(argtypes), size, ptr)) @staticmethod - def fielddescrof(S, fieldname): - ofs, size = symbolic.get_field_token(S, fieldname) - val = (size << 16) + ofs + def unpack_calldescr(calldescr): + assert isinstance(calldescr, ConstDescr3) + return calldescr.v + + def fielddescrof(self, S, fieldname): + ofs, size = symbolic.get_field_token(S, fieldname, + self.translate_support_code) if (isinstance(getattr(S, fieldname), lltype.Ptr) and getattr(S, fieldname).TO._gckind == 'gc'): - return ~val - return val + ptr = True + else: + ptr = False + return ConstDescr3((ofs, size, ptr)) @staticmethod def unpack_fielddescr(fielddescr): - ptr = False - if fielddescr < 0: - fielddescr = ~fielddescr - ptr = True - ofs = fielddescr & 0xffff - size = fielddescr >> 16 - return ofs, size, ptr + assert isinstance(fielddescr, ConstDescr3) + return fielddescr.v @staticmethod def typefor(fielddesc): - if fielddesc < 0: - return "ptr" + if fieldesc[2]: + return 'ptr' return "int" @staticmethod Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py Thu Mar 12 13:16:48 2009 @@ -1,34 +1,50 @@ import ctypes -from pypy.rpython.lltypesystem import lltype, ll2ctypes +from pypy.rpython.lltypesystem import lltype, ll2ctypes, llmemory from pypy.rlib.objectmodel import specialize @specialize.memo() -def get_field_token(STRUCT, fieldname): +def get_field_token(STRUCT, fieldname, translate_support_code): + if translate_support_code: + return (llmemory.offsetof(STRUCT, fieldname), + get_size(STRUCT, True)) cstruct = ll2ctypes.get_ctypes_type(STRUCT) cfield = getattr(cstruct, fieldname) return (cfield.offset, cfield.size) @specialize.memo() -def get_size(TYPE): +def get_size(TYPE, translate_support_code): + if translate_support_code: + if TYPE._is_varsize(): + return llmemory.sizeof(TYPE, 0) + return llmemory.sizeof(TYPE) ctype = ll2ctypes.get_ctypes_type(TYPE) return ctypes.sizeof(ctype) @specialize.memo() -def get_array_token(T): +def get_array_token(T, translate_support_code): # T can be an array or a var-sized structure - if isinstance(T, lltype.Struct): - assert T._arrayfld is not None, "%r is not variable-sized" % (T,) - cstruct = ll2ctypes.get_ctypes_type(T) - cfield = getattr(cstruct, T._arrayfld) - before_array_part = cfield.offset - T = getattr(T, T._arrayfld) + if translate_support_code: + basesize = llmemory.sizeof(T, 0) + if isinstance(T, lltype.Struct): + itemsize = llmemory.sizeof(getattr(T, T._arrayfld).OF) + ofs_length = llmemory.offsetof(T, T._arrayfld) + else: + itemsize = llmemory.sizeof(T.OF) + ofs_length = 0 else: - before_array_part = 0 - carray = ll2ctypes.get_ctypes_type(T) - assert carray.length.size == 4 - ofs_length = before_array_part + carray.length.offset - basesize = before_array_part + carray.items.offset - carrayitem = ll2ctypes.get_ctypes_type(T.OF) - itemsize = ctypes.sizeof(carrayitem) + if isinstance(T, lltype.Struct): + assert T._arrayfld is not None, "%r is not variable-sized" % (T,) + cstruct = ll2ctypes.get_ctypes_type(T) + cfield = getattr(cstruct, T._arrayfld) + before_array_part = cfield.offset + T = getattr(T, T._arrayfld) + else: + before_array_part = 0 + carray = ll2ctypes.get_ctypes_type(T) + assert carray.length.size == 4 + ofs_length = before_array_part + carray.length.offset + basesize = before_array_part + carray.items.offset + carrayitem = ll2ctypes.get_ctypes_type(T.OF) + itemsize = ctypes.sizeof(carrayitem) return basesize, itemsize, ofs_length Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Thu Mar 12 13:16:48 2009 @@ -204,6 +204,7 @@ (rop.INT_FLOORDIV, [ConstInt(42), BoxInt(10)], 4), (rop.INT_RSHIFT, [ConstInt(3), BoxInt(4)], 3>>4), (rop.INT_RSHIFT, [BoxInt(3), ConstInt(10)], 3>>10), + #(rop.INT_LSHIFT, [BoxInt(3), BoxInt(1)], 3<<1), ]: assert self.execute_operation(op, args, 'int').value == res @@ -235,7 +236,7 @@ try: saved_addr = self.cpu.assembler.malloc_func_addr self.cpu.assembler.malloc_func_addr = addr - ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] + ofs = symbolic.get_field_token(rstr.STR, 'chars', False)[0] res = self.execute_operation(rop.NEWSTR, [ConstInt(7)], 'ptr') assert allocs[0] == 7 + ofs + WORD @@ -252,7 +253,7 @@ # ------------------------------------------------------------ TP = lltype.GcArray(lltype.Signed) - ofs = symbolic.get_field_token(TP, 'length')[0] + ofs = symbolic.get_field_token(TP, 'length', False)[0] descr = self.cpu.arraydescrof(TP) res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)], @@ -274,8 +275,8 @@ def test_stringitems(self): from pypy.rpython.lltypesystem.rstr import STR - ofs = symbolic.get_field_token(STR, 'chars')[0] - ofs_items = symbolic.get_field_token(STR.chars, 'items')[0] + ofs = symbolic.get_field_token(STR, 'chars', False)[0] + ofs_items = symbolic.get_field_token(STR.chars, 'items', False)[0] res = self.execute_operation(rop.NEWSTR, [ConstInt(10)], 'ptr') self.execute_operation(rop.STRSETITEM, [res, ConstInt(2), ConstInt(ord('d'))], 'void') @@ -288,8 +289,8 @@ def test_arrayitems(self): TP = lltype.GcArray(lltype.Signed) - ofs = symbolic.get_field_token(TP, 'length')[0] - itemsofs = symbolic.get_field_token(TP, 'items')[0] + ofs = symbolic.get_field_token(TP, 'length', False)[0] + itemsofs = symbolic.get_field_token(TP, 'items', False)[0] descr = self.cpu.arraydescrof(TP) res = self.execute_operation(rop.NEW_ARRAY, [ConstInt(10)], 'ptr', descr) @@ -540,3 +541,4 @@ # XXX cannot work without rtyper #s = execute(cpu, rop.INT_MUL_OVF, [BoxInt(sys.maxint/2), BoxInt(10)]) #assert cpu.get_exception() + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Thu Mar 12 13:16:48 2009 @@ -1,3 +1,5 @@ +import py +py.test.skip("update me") from pypy.jit.backend.x86.symbolic import * from pypy.jit.backend.x86.runner import CPU386 from pypy.rpython.lltypesystem import lltype, rffi Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 12 13:16:48 2009 @@ -17,7 +17,7 @@ class JitCode(history.AbstractValue): - def __init__(self, name, cfnptr=None, calldescr=0): + def __init__(self, name, cfnptr=None, calldescr=None): self.name = name self.cfnptr = cfnptr self.calldescr = calldescr @@ -34,7 +34,6 @@ dump.dump_bytecode(self, file=file) print >> file - class IndirectCallset(history.AbstractValue): def __init__(self, codewriter, graphs): keys = [] @@ -226,12 +225,15 @@ self.bytecode.dump() else: print repr(self.bytecode) + self.bytecode.dump(open("/tmp/jitcodes/%s" % self.bytecode.name, "w")) def const_position(self, constvalue): """Generate a constant of the given value. Returns its index in the list self.positions[]. """ if constvalue is _we_are_jitted: constvalue = True + if isinstance(constvalue, history.Const): + return self.get_position(constvalue) const = Const._new(constvalue, self.cpu) return self.get_position(const) @@ -525,10 +527,10 @@ # store the vtable as an address -- that's fine, because the # GC doesn't need to follow them self.emit('new_with_vtable', - self.cpu.sizeof(STRUCT), + self.const_position(self.cpu.sizeof(STRUCT)), self.const_position(vtable)) else: - self.emit('new', self.cpu.sizeof(STRUCT)) + self.emit('new', self.const_position(self.cpu.sizeof(STRUCT))) self.register_var(op.result) def serialize_op_malloc_varsize(self, op): @@ -540,7 +542,7 @@ ARRAY = op.args[0].value arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('new_array') - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(op.args[2])) self.register_var(op.result) @@ -567,7 +569,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(offset) + self.emit(self.const_position(offset)) self.register_var(op.result) #self._eventualy_builtin(op.result) @@ -585,7 +587,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(offset) + self.emit(self.const_position(offset)) self.emit(self.var_position(v_value)) def is_typeptr_getset(self, op): @@ -604,7 +606,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('getarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(op.args[1])) self.register_var(op.result) @@ -614,7 +616,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('setarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(op.args[1])) self.emit(self.var_position(op.args[2])) @@ -699,7 +701,7 @@ op.args[1:], op.result) self.emit('residual_call') - self.emit(calldescr) + self.emit(self.const_position(calldescr)) self.emit_varargs([op.args[0]] + non_void_args) self.register_var(op.result) @@ -747,7 +749,7 @@ calldescr, non_void_args = self.codewriter.getcalldescr(c_func, args, op.result) self.emit(opname) - self.emit(calldescr) + self.emit(self.const_position(calldescr)) self.emit_varargs([c_func] + non_void_args) self.register_var(op.result) @@ -771,7 +773,7 @@ v_default.value != TP.TO.OF._defl()): return False # variable or non-null initial value self.emit('new_array') - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(args[0])) self.register_var(op.result) return True @@ -790,7 +792,7 @@ return False self.emit('setarrayitem_gc') self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(index)) self.emit(self.var_position(args[2])) self.register_var(op.result) @@ -800,7 +802,7 @@ oopspec_name == 'list.len_foldable'): self.emit('arraylen_gc') self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.register_var(op.result) return True # @@ -812,7 +814,7 @@ return False self.emit(opname) self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(index)) self.register_var(op.result) return True @@ -837,7 +839,7 @@ else: self.emit('check_neg_index') self.emit(self.var_position(args[0])) - self.emit(arraydescr) + self.emit(self.const_position(arraydescr)) self.emit(self.var_position(args[1])) v_posindex = Variable('posindex') v_posindex.concretetype = lltype.Signed @@ -879,7 +881,7 @@ self.emit('guard_nonvirtualized') self.emit(self.var_position(op.args[0])) self.emit(self.get_position(virtualizabledesc)) - self.emit(guard_field) + self.emit(self.const_position(guard_field)) # ---------- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Thu Mar 12 13:16:48 2009 @@ -13,34 +13,34 @@ # ____________________________________________________________ -def do_int_add(cpu, args, descr=0): +def do_int_add(cpu, args, descr=None): return ConstInt(args[0].getint() + args[1].getint()) -def do_int_sub(cpu, args, descr=0): +def do_int_sub(cpu, args, descr=None): return ConstInt(args[0].getint() - args[1].getint()) -def do_int_mul(cpu, args, descr=0): +def do_int_mul(cpu, args, descr=None): return ConstInt(args[0].getint() * args[1].getint()) -def do_int_floordiv(cpu, args, descr=0): +def do_int_floordiv(cpu, args, descr=None): return ConstInt(args[0].getint() // args[1].getint()) -def do_int_mod(cpu, args, descr=0): +def do_int_mod(cpu, args, descr=None): return ConstInt(args[0].getint() % args[1].getint()) -def do_int_and(cpu, args, descr=0): +def do_int_and(cpu, args, descr=None): return ConstInt(args[0].getint() & args[1].getint()) -def do_int_or(cpu, args, descr=0): +def do_int_or(cpu, args, descr=None): return ConstInt(args[0].getint() | args[1].getint()) -def do_int_xor(cpu, args, descr=0): +def do_int_xor(cpu, args, descr=None): return ConstInt(args[0].getint() ^ args[1].getint()) -def do_int_rshift(cpu, args, descr=0): +def do_int_rshift(cpu, args, descr=None): return ConstInt(args[0].getint() >> args[1].getint()) -def do_int_lshift(cpu, args, descr=0): +def do_int_lshift(cpu, args, descr=None): return ConstInt(args[0].getint() << args[1].getint()) do_uint_add = do_int_add @@ -48,71 +48,71 @@ do_uint_mul = do_int_mul do_uint_lshift = do_int_lshift -def do_uint_rshift(cpu, args, descr=0): +def do_uint_rshift(cpu, args, descr=None): v = r_uint(args[0].getint()) >> r_uint(args[1].getint()) return ConstInt(intmask(v)) # ---------- -def do_int_lt(cpu, args, descr=0): +def do_int_lt(cpu, args, descr=None): return ConstInt(args[0].getint() < args[1].getint()) -def do_int_le(cpu, args, descr=0): +def do_int_le(cpu, args, descr=None): return ConstInt(args[0].getint() <= args[1].getint()) -def do_int_eq(cpu, args, descr=0): +def do_int_eq(cpu, args, descr=None): return ConstInt(args[0].getint() == args[1].getint()) -def do_int_ne(cpu, args, descr=0): +def do_int_ne(cpu, args, descr=None): return ConstInt(args[0].getint() != args[1].getint()) -def do_int_gt(cpu, args, descr=0): +def do_int_gt(cpu, args, descr=None): return ConstInt(args[0].getint() > args[1].getint()) -def do_int_ge(cpu, args, descr=0): +def do_int_ge(cpu, args, descr=None): return ConstInt(args[0].getint() >= args[1].getint()) -def do_uint_lt(cpu, args, descr=0): +def do_uint_lt(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) < r_uint(args[1].getint())) -def do_uint_le(cpu, args, descr=0): +def do_uint_le(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) <= r_uint(args[1].getint())) do_uint_eq = do_int_eq do_uint_ne = do_int_ne -def do_uint_gt(cpu, args, descr=0): +def do_uint_gt(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) > r_uint(args[1].getint())) -def do_uint_ge(cpu, args, descr=0): +def do_uint_ge(cpu, args, descr=None): return ConstInt(r_uint(args[0].getint()) >= r_uint(args[1].getint())) # ---------- -def do_int_is_true(cpu, args, descr=0): +def do_int_is_true(cpu, args, descr=None): return ConstInt(bool(args[0].getint())) do_uint_is_true = do_int_is_true -def do_int_neg(cpu, args, descr=0): +def do_int_neg(cpu, args, descr=None): return ConstInt(-args[0].getint()) -def do_int_invert(cpu, args, descr=0): +def do_int_invert(cpu, args, descr=None): return ConstInt(~args[0].getint()) -def do_bool_not(cpu, args, descr=0): +def do_bool_not(cpu, args, descr=None): return ConstInt(not args[0].getint()) -def do_oononnull(cpu, args, descr=0): +def do_oononnull(cpu, args, descr=None): return ConstInt(bool(args[0].getptr_base())) -def do_ooisnull(cpu, args, descr=0): +def do_ooisnull(cpu, args, descr=None): return ConstInt(not args[0].getptr_base()) -def do_oois(cpu, args, descr=0): +def do_oois(cpu, args, descr=None): return ConstInt(args[0].getptr_base() == args[1].getptr_base()) -def do_ooisnot(cpu, args, descr=0): +def do_ooisnot(cpu, args, descr=None): return ConstInt(args[0].getptr_base() != args[1].getptr_base()) # ---------- @@ -136,7 +136,7 @@ # ---------- -def do_int_add_ovf(cpu, args, descr=0): +def do_int_add_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -146,7 +146,7 @@ z = 0 return BoxInt(z) -def do_int_sub_ovf(cpu, args, descr=0): +def do_int_sub_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -156,7 +156,7 @@ z = 0 return BoxInt(z) -def do_int_mul_ovf(cpu, args, descr=0): +def do_int_mul_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -166,7 +166,7 @@ z = 0 return BoxInt(z) -def do_int_neg_ovf(cpu, args, descr=0): +def do_int_neg_ovf(cpu, args, descr=None): x = args[0].getint() try: z = ovfcheck(-x) @@ -175,7 +175,7 @@ z = 0 return BoxInt(z) -def do_int_mod_ovf(cpu, args, descr=0): +def do_int_mod_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() try: @@ -213,7 +213,7 @@ return cpu._execute_list[opnum] get_execute_function._annspecialcase_ = 'specialize:memo' -def execute(cpu, opnum, argboxes, descr=0): +def execute(cpu, opnum, argboxes, descr=None): func = get_execute_function(cpu, opnum) return func(cpu, argboxes, descr) execute._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 12 13:16:48 2009 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rlib.objectmodel import we_are_translated, r_dict, ComputedIntSymbolic +from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic from pypy.rlib.rarithmetic import intmask from pypy.tool.uid import uid from pypy.conftest import option @@ -109,13 +109,23 @@ return 'Const(%s)' % self._getrepr_() def __eq__(self, other): - return self.__class__ is other.__class__ and self.value == other.value + if self.__class__ is not other.__class__: + return False + if isinstance(self.value, Symbolic): + v = id(self.value) + else: + v = self.value + if isinstance(other.value, Symbolic): + v2 = id(other.value) + else: + v2 = other.value + return v == v2 def __ne__(self, other): return not (self == other) def __hash__(self): - if isinstance(self.value, ComputedIntSymbolic): + if isinstance(self.value, Symbolic): return id(self.value) return self.get_() @@ -128,7 +138,7 @@ if isinstance(value, int): value = int(value) # bool -> int else: - assert isinstance(value, ComputedIntSymbolic) + assert isinstance(value, Symbolic) self.value = value def clonebox(self): @@ -257,7 +267,7 @@ if isinstance(value, int): value = int(value) # bool -> int else: - assert isinstance(value, ComputedIntSymbolic) + assert isinstance(value, Symbolic) self.value = value def clonebox(self): @@ -373,17 +383,17 @@ def __init__(self, cpu): self.cpu = cpu self.operations = [] - def record(self, opnum, argboxes, resbox, descr=0): + def record(self, opnum, argboxes, resbox, descr=None): raise NotImplementedError class History(RunningMatcher): - def record(self, opnum, argboxes, resbox, descr=0): + def record(self, opnum, argboxes, resbox, descr=None): op = ResOperation(opnum, argboxes, resbox, descr) self.operations.append(op) return op class BlackHole(RunningMatcher): - def record(self, opnum, argboxes, resbox, descr=0): + def record(self, opnum, argboxes, resbox, descr=None): return None def mp_eq(greenkey1, greenkey2): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 12 13:16:48 2009 @@ -33,6 +33,11 @@ class CancelInefficientLoop(Exception): pass +def convert_vdesc(cpu, vdesc): + if vdesc: + return [cpu.ofs_from_descr(i) for i in vdesc.virtuals] + return [] + class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate @@ -142,7 +147,7 @@ node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - if self.vdesc and key not in self.vdesc.virtuals: + if self.vdesc is not None and key not in self.vdesc: esc_self = True else: esc_self = False @@ -151,7 +156,7 @@ # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: - if self.vdesc and key not in self.vdesc.virtuals: + if self.vdesc is not None and key not in self.vdesc: esc_self = True else: esc_self = False @@ -162,8 +167,8 @@ for ofs, node in self.origfields.items(): if ofs in other.curfields: node.add_to_dependency_graph(other.curfields[ofs], dep_graph) - if (self.virtualized and self.vdesc and - ofs in self.vdesc.virtuals): + if (self.virtualized and self.vdesc is not None and + ofs in self.vdesc): node.add_to_dependency_graph(other.origfields[ofs], dep_graph) def intersect(self, other, nodes): @@ -255,7 +260,7 @@ # This does "Perfect specialization" as per doc/jitpl5.txt. perfect_specializer = PerfectSpecializer(loop, options) - perfect_specializer.find_nodes() + perfect_specializer.find_nodes(cpu) perfect_specializer.intersect_input_and_output() for old_loop in old_loops: if perfect_specializer.match_exactly(old_loop): @@ -268,7 +273,7 @@ return old_loops[0] perfect_specializer = PerfectSpecializer(bridge, options) - perfect_specializer.find_nodes() + perfect_specializer.find_nodes(cpu) for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): perfect_specializer.adapt_for_match(old_loop.operations) @@ -339,7 +344,7 @@ ## instnode.cursize += 1 ## self.dependency_graph.append((instnode, fieldnode)) - def find_nodes(self): + def find_nodes(self, cpu): # Steps (1) and (2) self.first_escaping_op = True # only catch can have consts @@ -421,19 +426,19 @@ continue elif opnum == rop.SETFIELD_GC: instnode = self.getnode(op.args[0]) - field = op.descr + field = cpu.ofs_from_descr(op.descr) self.find_nodes_setfield(instnode, field, self.getnode(op.args[1])) continue elif opnum == rop.GETFIELD_GC: instnode = self.getnode(op.args[0]) - field = op.descr + field = cpu.ofs_from_descr(op.descr) box = op.result self.find_nodes_getfield(instnode, field, box) continue elif opnum == rop.GETFIELD_GC_PURE: instnode = self.getnode(op.args[0]) - field = op.descr + field = cpu.ofs_from_descr(op.descr) if not instnode.const: box = op.result self.find_nodes_getfield(instnode, field, box) @@ -532,7 +537,7 @@ instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) - instnode.vdesc = op.vdesc + instnode.vdesc = convert_vdesc(cpu, op.vdesc) continue elif op.is_always_pure(): for arg in op.args: @@ -593,14 +598,14 @@ specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes - def expanded_version_of(self, boxlist, oplist): + def expanded_version_of(self, boxlist, oplist, cpu): # oplist is None means at the start newboxlist = [] assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) + specnode.expand_boxlist(self.nodes[box], newboxlist, oplist, cpu) return newboxlist def optimize_guard(self, op, cpu): @@ -718,7 +723,7 @@ # self.ready_results[newoperations[-1].results[0]] = None opnum = op.opnum if opnum == rop.MERGE_POINT: - args = self.expanded_version_of(op.args, None) + args = self.expanded_version_of(op.args, None, cpu) op = ResOperation(rop.MERGE_POINT, args, None) newoperations.append(op) #for arg in op.args: @@ -728,11 +733,11 @@ # for arg in op.args: # self.ready_results[arg] = None elif opnum == rop.JUMP: - args = self.expanded_version_of(op.args, newoperations) + args = self.expanded_version_of(op.args, newoperations, cpu) for arg in args: if arg in self.nodes: assert not self.nodes[arg].virtual - self.cleanup_field_caches(newoperations) + self.cleanup_field_caches(newoperations, cpu) op = ResOperation(rop.JUMP, args, None) newoperations.append(op) continue @@ -792,14 +797,16 @@ continue elif opnum == rop.GETFIELD_GC: instnode = self.nodes[op.args[0]] - if self.optimize_getfield(instnode, op.descr, op.result): + ofs = cpu.ofs_from_descr(op.descr) + if self.optimize_getfield(instnode, ofs, op.result): continue # otherwise we need this getfield, but it does not # invalidate caches elif opnum == rop.GETFIELD_GC_PURE: instnode = self.nodes[op.args[0]] if not instnode.const: - if self.optimize_getfield(instnode, op.descr, op.result): + ofs = cpu.ofs_from_descr(op.descr) + if self.optimize_getfield(instnode, ofs, op.result): continue elif opnum == rop.GETARRAYITEM_GC: instnode = self.nodes[op.args[0]] @@ -880,7 +887,7 @@ elif opnum == rop.SETFIELD_GC: instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[1]] - ofs = op.descr + ofs = cpu.ofs_from_descr(op.descr) self.optimize_setfield(instnode, ofs, valuenode, op.args[1]) continue elif opnum == rop.SETARRAYITEM_GC: @@ -947,7 +954,7 @@ opnum != rop.SETARRAYITEM_GC): # the setfield operations do not clean up caches, although # they have side effects - self.cleanup_field_caches(newoperations) + self.cleanup_field_caches(newoperations, cpu) if op.can_raise(): exception_might_have_happened = True box = op.result @@ -959,7 +966,7 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations - def cleanup_field_caches(self, newoperations): + def cleanup_field_caches(self, newoperations, cpu): # we need to invalidate everything for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): @@ -972,8 +979,9 @@ [node.source, ConstInt(ofs), valuenode.source], None, ld.arraydescr)) else: + descr = cpu.repack_descr(ofs) newoperations.append(ResOperation(rop.SETFIELD_GC, - [node.source, valuenode.source], None, ofs)) + [node.source, valuenode.source], None, descr)) node.dirtyfields = {} node.cleanfields = {} @@ -1046,8 +1054,9 @@ box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) + descr = metainterp.cpu.repack_descr(ofs) metainterp.execute_and_record(rop.SETFIELD_GC, - [box, fieldbox], ofs) + [box, fieldbox], descr) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 12 13:16:48 2009 @@ -311,38 +311,38 @@ except KeyError: pass - @arguments("int") + @arguments("constbox") def opimpl_new(self, size): self.execute(rop.NEW, [], descr=size) - @arguments("int", "constbox") + @arguments("constbox", "constbox") def opimpl_new_with_vtable(self, size, vtablebox): self.execute(rop.NEW_WITH_VTABLE, [vtablebox], descr=size) - @arguments("int", "box") + @arguments("constbox", "box") def opimpl_new_array(self, itemsize, countbox): self.execute(rop.NEW_ARRAY, [countbox], descr=itemsize) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): self.execute(rop.GETARRAYITEM_GC, [arraybox, indexbox], descr=arraydesc) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): self.execute(rop.GETARRAYITEM_GC_PURE, [arraybox, indexbox], descr=arraydesc) - @arguments("box", "int", "box", "box") + @arguments("box", "constbox", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): self.execute(rop.SETARRAYITEM_GC, [arraybox, indexbox, itembox], descr=arraydesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_arraylen_gc(self, arraybox, arraydesc): self.execute(rop.ARRAYLEN_GC, [arraybox], descr=arraydesc) - @arguments("orgpc", "box", "int", "box") + @arguments("orgpc", "box", "constbox", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): negbox = self.metainterp.execute_and_record( rop.INT_LT, [indexbox, ConstInt(0)]) @@ -372,23 +372,23 @@ self.execute(rop.OOISNOT, [box1, box2]) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_gc(self, box, fielddesc): self.execute(rop.GETFIELD_GC, [box], descr=fielddesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_gc_pure(self, box, fielddesc): self.execute(rop.GETFIELD_GC_PURE, [box], descr=fielddesc) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_GC, [box, valuebox], descr=fielddesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_raw(self, box, fielddesc): self.execute(rop.GETFIELD_RAW, [box], descr=fielddesc) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_raw_pure(self, box, fielddesc): self.execute(rop.GETFIELD_RAW_PURE, [box], descr=fielddesc) - @arguments("box", "int", "box") + @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc) @@ -407,11 +407,11 @@ f.setup_call(varargs) return True - @arguments("int", "varargs") + @arguments("constbox", "varargs") def opimpl_residual_call(self, calldescr, varargs): return self.execute_with_exc(rop.CALL, varargs, descr=calldescr) - @arguments("int", "varargs") + @arguments("constbox", "varargs") def opimpl_residual_call_pure(self, calldescr, varargs): self.execute(rop.CALL_PURE, varargs, descr=calldescr) @@ -655,13 +655,13 @@ return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) @specialize.arg(1) - def execute(self, opnum, argboxes, descr=0): + def execute(self, opnum, argboxes, descr=None): resbox = self.metainterp.execute_and_record(opnum, argboxes, descr) if resbox is not None: self.make_result_box(resbox) @specialize.arg(1) - def execute_with_exc(self, opnum, argboxes, descr=0): + def execute_with_exc(self, opnum, argboxes, descr=None): cpu = self.metainterp.cpu resbox = executor.execute(cpu, opnum, argboxes, descr) if not we_are_translated(): @@ -763,7 +763,7 @@ return False return True - def execute_and_record(self, opnum, argboxes, descr=0): + def execute_and_record(self, opnum, argboxes, descr=None): # execute the operation first resbox = executor.execute(self.cpu, opnum, argboxes, descr) # check if the operation can be constant-folded away Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 12 13:16:48 2009 @@ -17,7 +17,8 @@ # for 'guard_nonvirtualizable' vdesc = None - def __init__(self, opnum, args, result, descr=0): + def __init__(self, opnum, args, result, descr=None): + from pypy.jit.metainterp.history import AbstractValue assert isinstance(opnum, int) self.opnum = opnum self.args = list(args) @@ -25,7 +26,8 @@ self.result = result # for 'call', 'new', 'getfield_gc'...: the descr is a number provided # by the backend holding details about the type of the operation - assert isinstance(descr, int) + if descr is not None: + assert isinstance(descr, AbstractValue) self.descr = descr def __repr__(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Thu Mar 12 13:16:48 2009 @@ -4,7 +4,7 @@ class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist, start, cpu): newboxlist.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): @@ -119,15 +119,16 @@ return False return True - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist, start, cpu): for ofs, subspecnode in self.fields: subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start) + subspecnode.expand_boxlist(subinstnode, newboxlist, start, cpu) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: + descr = cpu.repack_descr(ofs) fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox], ofs) + [valuebox], descr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): @@ -136,9 +137,10 @@ class VirtualizedSpecNode(SpecNodeWithFields): - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist, start, cpu): newboxlist.append(instnode.source) - SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) + SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start, + cpu) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) @@ -150,7 +152,7 @@ class DelayedSpecNode(VirtualizedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist): + def expand_boxlist(self, instnode, newboxlist, oplist, cpu): newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) @@ -162,13 +164,14 @@ newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() + descr = cpu.repack_descr(ofs) oplist.append(ResOperation(rop.GETFIELD_GC, - [instnode.source], box, ofs)) + [instnode.source], box, descr)) newboxlist.append(box) class DelayedFixedListSpecNode(DelayedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist): + def expand_boxlist(self, instnode, newboxlist, oplist, cpu): from pypy.jit.metainterp.history import ResOperation, ConstInt from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 12 13:16:48 2009 @@ -70,7 +70,7 @@ # Box._extended_display = saved return True -def ResOperation(opname, args, result, descr=0): +def ResOperation(opname, args, result, descr=None): if opname == 'escape': opnum = -123 # random number not in the list else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Mar 12 13:16:48 2009 @@ -168,7 +168,6 @@ locals().update(B.__dict__) n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v2 = BoxInt(13) - sizebox = ConstInt(cpu.sizeof(NODE)) ops = [ ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], From arigo at codespeak.net Thu Mar 12 13:19:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 13:19:23 +0100 (CET) Subject: [pypy-svn] r62884 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312121923.AAA0C168483@codespeak.net> Author: arigo Date: Thu Mar 12 13:19:23 2009 New Revision: 62884 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: Dump to the udir, instead of at a random hard-coded place. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 12 13:19:23 2009 @@ -7,6 +7,7 @@ from pypy.rlib.jit import _we_are_jitted from pypy.jit.metainterp.history import Const, getkind from pypy.jit.metainterp import heaptracker, support, history +from pypy.tool.udir import udir import py, sys from pypy.tool.ansi_print import ansi_log @@ -225,7 +226,8 @@ self.bytecode.dump() else: print repr(self.bytecode) - self.bytecode.dump(open("/tmp/jitcodes/%s" % self.bytecode.name, "w")) + dir = udir.ensure("jitcodes", dir=1) + self.bytecode.dump(open(str(dir.join(self.bytecode.name)), "w")) def const_position(self, constvalue): """Generate a constant of the given value. From cfbolz at codespeak.net Thu Mar 12 14:55:25 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 12 Mar 2009 14:55:25 +0100 (CET) Subject: [pypy-svn] r62886 - pypy/trunk/pypy/translator/c Message-ID: <20090312135525.F3A9F168490@codespeak.net> Author: cfbolz Date: Thu Mar 12 14:55:25 2009 New Revision: 62886 Modified: pypy/trunk/pypy/translator/c/funcgen.py Log: kill some very old code that seems dead nowadays Modified: pypy/trunk/pypy/translator/c/funcgen.py ============================================================================== --- pypy/trunk/pypy/translator/c/funcgen.py (original) +++ pypy/trunk/pypy/translator/c/funcgen.py Thu Mar 12 14:55:25 2009 @@ -294,19 +294,15 @@ raise TypeError("exitswitch type not supported" " Got %r" % (TYPE,)) - def gen_link(self, link, linklocalvars=None): + def gen_link(self, link): "Generate the code to jump across the given Link." is_alive = {} - linklocalvars = linklocalvars or {} assignments = [] for a1, a2 in zip(link.args, link.target.inputargs): a2type, a2typename = self.lltypes[id(a2)] if a2type is Void: continue - if a1 in linklocalvars: - src = linklocalvars[a1] - else: - src = self.expr(a1) + src = self.expr(a1) dest = LOCALVAR % a2.name assignments.append((a2typename, dest, src)) for line in gen_assignments(assignments): From cfbolz at codespeak.net Thu Mar 12 15:00:37 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 12 Mar 2009 15:00:37 +0100 (CET) Subject: [pypy-svn] r62887 - pypy/trunk/pypy/translator/backendopt Message-ID: <20090312140037.4A606168490@codespeak.net> Author: cfbolz Date: Thu Mar 12 15:00:36 2009 New Revision: 62887 Modified: pypy/trunk/pypy/translator/backendopt/ssa.py Log: Use new interface. Modified: pypy/trunk/pypy/translator/backendopt/ssa.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/ssa.py (original) +++ pypy/trunk/pypy/translator/backendopt/ssa.py Thu Mar 12 15:00:36 2009 @@ -107,9 +107,7 @@ # sanity-check that the same name is never used several times in a block variables_by_name = {} - for block in flatten(graph): - if not isinstance(block, Block): - continue + for block in graph.iterblocks(): vars = [op.result for op in block.operations] for link in block.exits: vars += link.getextravars() From arigo at codespeak.net Thu Mar 12 15:11:20 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 15:11:20 +0100 (CET) Subject: [pypy-svn] r62888 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090312141120.A468A1684A3@codespeak.net> Author: arigo Date: Thu Mar 12 15:11:19 2009 New Revision: 62888 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Uniformize the interface, passing instances of Descr all around and not converting between them and integers in optimize.py. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Mar 12 15:11:19 2009 @@ -135,11 +135,11 @@ return '\n'.join(lines) class Operation(object): - def __init__(self, opnum, descr): + def __init__(self, opnum): self.opnum = opnum self.args = [] self.result = None - self.descr = descr + self.descr = None self.livevars = [] # for guards only def __repr__(self): @@ -220,7 +220,7 @@ assert x == 0 or x == 1 return str(bool(x)) #elif tp == 'fieldname': - # return str(symbolic.TokenToField[x/2][1]) + # return str(symbolic.TokenToField[x...][1]) else: raise NotImplementedError("tp = %s" % tp) @@ -248,9 +248,16 @@ _variables.append(v) return r -def compile_add(loop, opnum, descr): +def compile_add(loop, opnum): loop = _from_opaque(loop) - loop.operations.append(Operation(opnum, descr)) + loop.operations.append(Operation(opnum)) + +def compile_add_descr(loop, ofs, type): + from pypy.jit.backend.llgraph.runner import Descr + loop = _from_opaque(loop) + op = loop.operations[-1] + assert isinstance(type, str) and len(type) == 1 + op.descr = Descr(ofs, type) def compile_add_var(loop, intvar): loop = _from_opaque(loop) @@ -520,61 +527,62 @@ # delegating to the builtins do_xxx() (done automatically for simple cases) def op_getarrayitem_gc(self, arraydescr, array, index): - if arraydescr.getint() & 1: + if arraydescr.type == 'p': return do_getarrayitem_gc_ptr(array, index) else: return do_getarrayitem_gc_int(array, index, self.memocast) def op_getfield_gc(self, fielddescr, struct): - fielddescr = fielddescr.getint() - if fielddescr & 1: - return do_getfield_gc_ptr(struct, fielddescr) + if fielddescr.type == 'p': + return do_getfield_gc_ptr(struct, fielddescr.ofs) else: - return do_getfield_gc_int(struct, fielddescr, self.memocast) + return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast) def op_getfield_raw(self, fielddescr, struct): - if fielddescr.getint() & 1: - return do_getfield_raw_ptr(struct, fielddescr) + if fielddescr.type == 'p': + return do_getfield_raw_ptr(struct, fielddescr.ofs) else: - return do_getfield_raw_int(struct, fielddescr, self.memocast) + return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast) def op_new_with_vtable(self, size, vtable): - result = do_new(size.getint()) + result = do_new(size.ofs) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) return result def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): - if arraydescr.getint() & 1: + if arraydescr.type == 'p': do_setarrayitem_gc_ptr(array, index, newvalue) else: do_setarrayitem_gc_int(array, index, newvalue, self.memocast) def op_setfield_gc(self, fielddescr, struct, newvalue): - fielddescr = fielddescr.getint() - if fielddescr & 1: - do_setfield_gc_ptr(struct, fielddescr, newvalue) + if fielddescr.type == 'p': + do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) else: - do_setfield_gc_int(struct, fielddescr, newvalue, self.memocast) + do_setfield_gc_int(struct, fielddescr.ofs, newvalue, + self.memocast) def op_setfield_raw(self, fielddescr, struct, newvalue): - if fielddescr.getint() & 1: - do_setfield_raw_ptr(struct, fielddescr, newvalue) + if fielddescr.type == 'p': + do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) else: - do_setfield_raw_int(struct, fielddescr, newvalue, self.memocast) + do_setfield_raw_int(struct, fielddescr.ofs, newvalue, + self.memocast) def op_call(self, calldescr, func, *args): _call_args[:] = args - if calldescr == sys.maxint: + if calldescr.type == 'v': err_result = None - elif calldescr.getint() & 1: + elif calldescr.type == 'p': err_result = lltype.nullptr(llmemory.GCREF.TO) else: + assert calldescr.type == 'i' err_result = 0 return _do_call_common(func, self.memocast, err_result) def op_new_array(self, arraydescr, count): - return do_new_array(arraydescr.getint(), count) + return do_new_array(arraydescr.ofs, count) # ____________________________________________________________ @@ -748,26 +756,26 @@ array = array._obj.container return cast_to_ptr(array.getitem(index)) -def do_getfield_gc_int(struct, fielddesc, memocast): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_getfield_gc_int(struct, fieldnum, memocast): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) x = getattr(ptr, fieldname) return cast_to_int(x, memocast) -def do_getfield_gc_ptr(struct, fielddesc): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_getfield_gc_ptr(struct, fieldnum): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) x = getattr(ptr, fieldname) return cast_to_ptr(x) -def do_getfield_raw_int(struct, fielddesc, memocast): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_getfield_raw_int(struct, fieldnum, memocast): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) x = getattr(ptr, fieldname) return cast_to_int(x, memocast) -def do_getfield_raw_ptr(struct, fielddesc): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_getfield_raw_ptr(struct, fieldnum): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) x = getattr(ptr, fieldname) return cast_to_ptr(x) @@ -777,8 +785,8 @@ x = lltype.malloc(TYPE) return cast_to_ptr(x) -def do_new_array(arraydesc, count): - TYPE = symbolic.Size2Type[arraydesc/2] +def do_new_array(arraynum, count): + TYPE = symbolic.Size2Type[arraynum] x = lltype.malloc(TYPE, count) return cast_to_ptr(x) @@ -794,29 +802,29 @@ newvalue = cast_from_ptr(ITEMTYPE, newvalue) array.setitem(index, newvalue) -def do_setfield_gc_int(struct, fielddesc, newvalue, memocast): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_setfield_gc_int(struct, fieldnum, newvalue, memocast): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) setattr(ptr, fieldname, newvalue) -def do_setfield_gc_ptr(struct, fielddesc, newvalue): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_setfield_gc_ptr(struct, fieldnum, newvalue): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_ptr(FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_int(struct, fielddesc, newvalue, memocast): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_setfield_raw_int(struct, fieldnum, newvalue, memocast): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_int(FIELDTYPE, newvalue, memocast) setattr(ptr, fieldname, newvalue) -def do_setfield_raw_ptr(struct, fielddesc, newvalue): - STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] +def do_setfield_raw_ptr(struct, fieldnum, newvalue): + STRUCT, fieldname = symbolic.TokenToField[fieldnum] ptr = llmemory.cast_adr_to_ptr(struct, lltype.Ptr(STRUCT)) FIELDTYPE = getattr(STRUCT, fieldname) newvalue = cast_from_ptr(FIELDTYPE, newvalue) @@ -935,6 +943,7 @@ setannotation(compile_start_int_var, annmodel.SomeInteger()) setannotation(compile_start_ptr_var, annmodel.SomeInteger()) setannotation(compile_add, annmodel.s_None) +setannotation(compile_add_descr, annmodel.s_None) setannotation(compile_add_var, annmodel.s_None) setannotation(compile_add_int_const, annmodel.s_None) setannotation(compile_add_ptr_const, annmodel.s_None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 12 15:11:19 2009 @@ -14,6 +14,40 @@ pass +class Descr(history.AbstractValue): + def __init__(self, ofs, type='?'): + self.ofs = ofs + self.type = type + + def __hash__(self): + return hash((self.ofs, self.type)) + + def __eq__(self, other): + if not isinstance(other, Descr): + return NotImplemented + return self.ofs == other.ofs and self.type == other.type + + def __ne__(self, other): + if not isinstance(other, Descr): + return NotImplemented + return self.ofs != other.ofs or self.type != other.type + + def sort_key(self): + return self.ofs + + def __lt__(self, other): + raise TypeError("cannot use comparison on Descrs") + def __le__(self, other): + raise TypeError("cannot use comparison on Descrs") + def __gt__(self, other): + raise TypeError("cannot use comparison on Descrs") + def __ge__(self, other): + raise TypeError("cannot use comparison on Descrs") + + def __repr__(self): + return '' % (self.ofs, self.type) + + class CPU(object): def __init__(self, rtyper, stats=None, translate_support_code=False, @@ -64,7 +98,9 @@ op._compiled = c op._opindex = j j += 1 - llimpl.compile_add(c, op.opnum, op.descr) + llimpl.compile_add(c, op.opnum) + if op.descr is not None: + llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type) for x in op.args: if isinstance(x, history.Box): llimpl.compile_add_var(c, var2index[x]) @@ -186,7 +222,7 @@ @staticmethod def sizeof(S): - return history.ConstInt(symbolic.get_size(S)) + return Descr(symbolic.get_size(S)) @staticmethod def numof(S): @@ -198,51 +234,19 @@ def fielddescrof(S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname) token = history.getkind(getattr(S, fieldname)) - if token == 'ptr': - bit = 1 - else: - bit = 0 - return history.ConstInt(ofs*2 + bit) + return Descr(ofs, token[0]) @staticmethod def arraydescrof(A): assert isinstance(A, lltype.GcArray) size = symbolic.get_size(A) token = history.getkind(A.OF) - if token == 'ptr': - bit = 1 - else: - bit = 0 - return history.ConstInt(size*2 + bit) + return Descr(size, token[0]) @staticmethod def calldescrof(ARGS, RESULT): - if RESULT is lltype.Void: - return sys.maxint token = history.getkind(RESULT) - if token == 'ptr': - return 1 - else: - return 0 - - @staticmethod - def typefor(fielddesc): - fielddesc = fielddesc.getint() - if fielddesc == sys.maxint: - return 'void' - if fielddesc % 2: - return 'ptr' - return 'int' - - @staticmethod - def itemoffsetof(A): - basesize, itemsize, ofs_length = symbolic.get_array_token(A) - return basesize - - @staticmethod - def arraylengthoffset(A): - basesize, itemsize, ofs_length = symbolic.get_array_token(A) - return ofs_length + return Descr(0, token[0]) def cast_adr_to_int(self, adr): return llimpl.cast_adr_to_int(self.memo_cast, adr) @@ -250,23 +254,17 @@ def cast_int_to_adr(self, int): return llimpl.cast_int_to_adr(self.memo_cast, int) - def ofs_from_descr(self, descr): - return descr.getint() - - def repack_descr(self, ofs): - return history.ConstInt(ofs) - # ---------- the backend-dependent operations ---------- def do_arraylen_gc(self, args, arraydescr): array = args[0].getptr_base() return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array)) - def do_strlen(self, args, descr=0): + def do_strlen(self, args, descr=None): string = args[0].getptr_base() return history.BoxInt(llimpl.do_strlen(0, string)) - def do_strgetitem(self, args, descr=0): + def do_strgetitem(self, args, descr=None): string = args[0].getptr_base() index = args[1].getint() return history.BoxInt(llimpl.do_strgetitem(0, string, index)) @@ -274,51 +272,50 @@ def do_getarrayitem_gc(self, args, arraydescr): array = args[0].getptr_base() index = args[1].getint() - if self.typefor(arraydescr) == 'ptr': + if arraydescr.type == 'p': return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index)) else: return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index, self.memo_cast)) - def do_getfield_gc(self, args, fieldbox): - fielddescr = fieldbox.getint() + def do_getfield_gc(self, args, fielddescr): struct = args[0].getptr_base() - if self.typefor(fieldbox) == 'ptr': + if fielddescr.type == 'p': return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct, - fielddescr)) + fielddescr.ofs)) else: return history.BoxInt(llimpl.do_getfield_gc_int(struct, - fielddescr, + fielddescr.ofs, self.memo_cast)) def do_getfield_raw(self, args, fielddescr): struct = self.cast_int_to_adr(args[0].getint()) - if self.typefor(fielddescr) == 'ptr': + if fielddescr.type == 'p': return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct, - fielddescr)) + fielddescr.ofs)) else: return history.BoxInt(llimpl.do_getfield_raw_int(struct, - fielddescr, + fielddescr.ofs, self.memo_cast)) def do_new(self, args, size): - return history.BoxPtr(llimpl.do_new(size.getint())) + return history.BoxPtr(llimpl.do_new(size.ofs)) def do_new_with_vtable(self, args, size): vtable = args[0].getint() - result = llimpl.do_new(size.getint()) - llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.getint(), + result = llimpl.do_new(size.ofs) + llimpl.do_setfield_gc_int(result, self.fielddescrof_vtable.ofs, vtable, self.memo_cast) return history.BoxPtr(result) def do_new_array(self, args, size): count = args[0].getint() - return history.BoxPtr(llimpl.do_new_array(size.getint(), count)) + return history.BoxPtr(llimpl.do_new_array(size.ofs, count)) def do_setarrayitem_gc(self, args, arraydescr): array = args[0].getptr_base() index = args[1].getint() - if self.typefor(arraydescr) == 'ptr': + if arraydescr.type == 'p': newvalue = args[2].getptr_base() llimpl.do_setarrayitem_gc_ptr(array, index, newvalue) else: @@ -326,33 +323,31 @@ llimpl.do_setarrayitem_gc_int(array, index, newvalue, self.memo_cast) - def do_setfield_gc(self, args, fieldbox): - fielddescr = fieldbox.getint() + def do_setfield_gc(self, args, fielddescr): struct = args[0].getptr_base() - if self.typefor(fieldbox) == 'ptr': + if fielddescr.type == 'p': newvalue = args[1].getptr_base() - llimpl.do_setfield_gc_ptr(struct, fielddescr, newvalue) + llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue) else: newvalue = args[1].getint() - llimpl.do_setfield_gc_int(struct, fielddescr, newvalue, + llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue, self.memo_cast) def do_setfield_raw(self, args, fielddescr): - fielddescr = fielddescr.getint() struct = self.cast_int_to_adr(args[0].getint()) - if self.typefor(fielddescr) == 'ptr': + if fielddescr.type == 'p': newvalue = args[1].getptr_base() - llimpl.do_setfield_raw_ptr(struct, fielddescr, newvalue) + llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue) else: newvalue = args[1].getint() - llimpl.do_setfield_raw_int(struct, fielddescr, newvalue, + llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue, self.memo_cast) - def do_newstr(self, args, descr=0): + def do_newstr(self, args, descr=None): length = args[0].getint() return history.BoxPtr(llimpl.do_newstr(0, length)) - def do_strsetitem(self, args, descr=0): + def do_strsetitem(self, args, descr=None): string = args[0].getptr_base() index = args[1].getint() newvalue = args[2].getint() @@ -366,12 +361,11 @@ llimpl.do_call_pushptr(arg.getptr_base()) else: llimpl.do_call_pushint(arg.getint()) - restype = self.typefor(calldescr) - if restype == 'ptr': + if calldescr.type == 'p': return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast)) - elif restype == 'int': + elif calldescr.type == 'i': return history.BoxInt(llimpl.do_call_int(func, self.memo_cast)) - else: # restype == 'void' + else: # calldescr.type == 'v' # void llimpl.do_call_void(func, self.memo_cast) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 12 15:11:19 2009 @@ -234,8 +234,6 @@ Returns its index in the list self.positions[]. """ if constvalue is _we_are_jitted: constvalue = True - if isinstance(constvalue, history.Const): - return self.get_position(constvalue) const = Const._new(constvalue, self.cpu) return self.get_position(const) @@ -529,10 +527,10 @@ # store the vtable as an address -- that's fine, because the # GC doesn't need to follow them self.emit('new_with_vtable', - self.const_position(self.cpu.sizeof(STRUCT)), + self.get_position(self.cpu.sizeof(STRUCT)), self.const_position(vtable)) else: - self.emit('new', self.const_position(self.cpu.sizeof(STRUCT))) + self.emit('new', self.get_position(self.cpu.sizeof(STRUCT))) self.register_var(op.result) def serialize_op_malloc_varsize(self, op): @@ -544,7 +542,7 @@ ARRAY = op.args[0].value arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('new_array') - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(op.args[2])) self.register_var(op.result) @@ -571,7 +569,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(self.const_position(offset)) + self.emit(self.get_position(offset)) self.register_var(op.result) #self._eventualy_builtin(op.result) @@ -589,7 +587,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(self.const_position(offset)) + self.emit(self.get_position(offset)) self.emit(self.var_position(v_value)) def is_typeptr_getset(self, op): @@ -608,7 +606,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('getarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(op.args[1])) self.register_var(op.result) @@ -618,7 +616,7 @@ arraydescr = self.cpu.arraydescrof(ARRAY) self.emit('setarrayitem_gc') self.emit(self.var_position(op.args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(op.args[1])) self.emit(self.var_position(op.args[2])) @@ -703,7 +701,7 @@ op.args[1:], op.result) self.emit('residual_call') - self.emit(self.const_position(calldescr)) + self.emit(self.get_position(calldescr)) self.emit_varargs([op.args[0]] + non_void_args) self.register_var(op.result) @@ -751,7 +749,7 @@ calldescr, non_void_args = self.codewriter.getcalldescr(c_func, args, op.result) self.emit(opname) - self.emit(self.const_position(calldescr)) + self.emit(self.get_position(calldescr)) self.emit_varargs([c_func] + non_void_args) self.register_var(op.result) @@ -775,7 +773,7 @@ v_default.value != TP.TO.OF._defl()): return False # variable or non-null initial value self.emit('new_array') - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(args[0])) self.register_var(op.result) return True @@ -794,7 +792,7 @@ return False self.emit('setarrayitem_gc') self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(index)) self.emit(self.var_position(args[2])) self.register_var(op.result) @@ -804,7 +802,7 @@ oopspec_name == 'list.len_foldable'): self.emit('arraylen_gc') self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.register_var(op.result) return True # @@ -816,7 +814,7 @@ return False self.emit(opname) self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(index)) self.register_var(op.result) return True @@ -841,7 +839,7 @@ else: self.emit('check_neg_index') self.emit(self.var_position(args[0])) - self.emit(self.const_position(arraydescr)) + self.emit(self.get_position(arraydescr)) self.emit(self.var_position(args[1])) v_posindex = Variable('posindex') v_posindex.concretetype = lltype.Signed @@ -883,7 +881,7 @@ self.emit('guard_nonvirtualized') self.emit(self.var_position(op.args[0])) self.emit(self.get_position(virtualizabledesc)) - self.emit(self.const_position(guard_field)) + self.emit(self.get_position(guard_field)) # ---------- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 12 15:11:19 2009 @@ -161,6 +161,8 @@ def _getrepr_(self): return self.value + sort_key = getint + CONST_FALSE = ConstInt(0) CONST_TRUE = ConstInt(1) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 12 15:11:19 2009 @@ -33,11 +33,6 @@ class CancelInefficientLoop(Exception): pass -def convert_vdesc(cpu, vdesc): - if vdesc: - return [cpu.ofs_from_descr(i) for i in vdesc.virtuals] - return [] - class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate @@ -188,7 +183,6 @@ return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: - fields = [] if self is other: d = self.origfields.copy() @@ -196,7 +190,7 @@ else: d = other.curfields lst = d.keys() - sort_integers(lst) + sort_descrs(lst) for ofs in lst: node = d[ofs] if ofs not in self.origfields: @@ -213,7 +207,7 @@ if not other.virtualized and self.expanded_fields: fields = [] lst = self.expanded_fields.keys() - sort_integers(lst) + sort_descrs(lst) for ofs in lst: specnode = SpecNodeWithBox(self.origfields[ofs].source) fields.append((ofs, specnode)) @@ -225,7 +219,7 @@ d = self.origfields.copy() d.update(other.curfields) offsets = d.keys() - sort_integers(offsets) + sort_descrs(offsets) fields = [] for ofs in offsets: if ofs in self.origfields and ofs in other.curfields: @@ -259,33 +253,34 @@ return None # This does "Perfect specialization" as per doc/jitpl5.txt. - perfect_specializer = PerfectSpecializer(loop, options) - perfect_specializer.find_nodes(cpu) + perfect_specializer = PerfectSpecializer(loop, options, cpu) + perfect_specializer.find_nodes() perfect_specializer.intersect_input_and_output() for old_loop in old_loops: if perfect_specializer.match_exactly(old_loop): return old_loop - perfect_specializer.optimize_loop(cpu) + perfect_specializer.optimize_loop() return None def optimize_bridge(options, old_loops, bridge, cpu=None): if not options.specialize: # for tests only return old_loops[0] - perfect_specializer = PerfectSpecializer(bridge, options) - perfect_specializer.find_nodes(cpu) + perfect_specializer = PerfectSpecializer(bridge, options, cpu) + perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): perfect_specializer.adapt_for_match(old_loop.operations) - perfect_specializer.optimize_loop(cpu) + perfect_specializer.optimize_loop() return old_loop return None # no loop matches class PerfectSpecializer(object): - def __init__(self, loop, options=Options()): + def __init__(self, loop, options=Options(), cpu=None): self.loop = loop self.options = options + self.cpu = cpu self.nodes = {} self.dependency_graph = [] @@ -304,10 +299,12 @@ return self.nodes[box].source def find_nodes_setfield(self, instnode, ofs, fieldnode): + assert isinstance(ofs, AbstractValue) instnode.curfields[ofs] = fieldnode self.dependency_graph.append((instnode, fieldnode)) def find_nodes_getfield(self, instnode, field, box): + assert isinstance(field, AbstractValue) if field in instnode.curfields: fieldnode = instnode.curfields[field] elif field in instnode.origfields: @@ -328,23 +325,14 @@ instnode.cls = InstanceNode(FixedList(op.descr)) fieldbox = op.args[1] if self.getnode(fieldbox).const: - item = self.getsource(fieldbox).getint() - assert item >= 0 # XXX + item = self.getsource(fieldbox) self.find_nodes_getfield(instnode, item, op.result) else: instnode.escaped = True self.nodes[op.result] = InstanceNode(op.result, escaped=True) - -## def find_nodes_insert(self, instnode, field, fieldnode): -## for ofs, node in instnode.curfields.items(): -## if ofs >= field: -## instnode.curfields[ofs + 1] = node -## instnode.curfields[field] = fieldnode -## instnode.cursize += 1 -## self.dependency_graph.append((instnode, fieldnode)) - def find_nodes(self, cpu): + def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True # only catch can have consts @@ -375,32 +363,6 @@ else: instnode.escaped = True continue -## elif opname == 'newlist': -## box = op.results[0] -## instnode = InstanceNode(box, escaped=False) -## self.nodes[box] = instnode -## self.first_escaping_op = False -## if (isinstance(op.args[1], ConstInt) or -## self.nodes[op.args[1]].const): -## size = self.getsource(op.args[1]).getint() -## instnode.cursize = size -## instnode.origsize = size -## # XXX following guard_builtin will set the -## # correct class, otherwise it's a mess -## continue -## elif opname == 'guard_builtin': -## instnode = self.nodes[op.args[0]] -## # all builtins have equal classes -## instnode.cls = InstanceNode(op.args[1]) -## continue -## elif opname == 'guard_len': -## instnode = self.nodes[op.args[0]] -## if instnode.cursize == -1: -## instnode = self.nodes[op.args[0]] -## size = op.args[1].getint() -## instnode.cursize = size -## instnode.origsize = size -## continue elif opnum == rop.GETARRAYITEM_GC: self.find_nodes_getarrayitem(op) continue @@ -415,8 +377,7 @@ instnode.cls = InstanceNode(FixedList(op.descr)) fieldbox = op.args[1] if self.getnode(fieldbox).const: - item = self.getsource(fieldbox).getint() - assert item >= 0 # XXX + item = self.getsource(fieldbox) self.find_nodes_setfield(instnode, item, self.getnode(op.args[2])) else: @@ -426,98 +387,23 @@ continue elif opnum == rop.SETFIELD_GC: instnode = self.getnode(op.args[0]) - field = cpu.ofs_from_descr(op.descr) + field = op.descr self.find_nodes_setfield(instnode, field, self.getnode(op.args[1])) continue elif opnum == rop.GETFIELD_GC: instnode = self.getnode(op.args[0]) - field = cpu.ofs_from_descr(op.descr) + field = op.descr box = op.result self.find_nodes_getfield(instnode, field, box) continue elif opnum == rop.GETFIELD_GC_PURE: instnode = self.getnode(op.args[0]) - field = cpu.ofs_from_descr(op.descr) + field = op.descr if not instnode.const: box = op.result self.find_nodes_getfield(instnode, field, box) continue -## elif opname == 'getitem': -## instnode = self.getnode(op.args[1]) -## fieldbox = op.args[2] -## if (isinstance(fieldbox, ConstInt) or -## self.nodes[op.args[2]].const): -## field = self.getsource(fieldbox).getint() -## if field < 0: -## field = instnode.cursize + field -## box = op.results[0] -## self.find_nodes_getfield(instnode, field, box) -## continue -## else: -## instnode.escaped = True -## self.nodes[op.results[0]] = InstanceNode(op.results[0], -## escaped=True) -## continue -## elif opname == 'append': -## instnode = self.getnode(op.args[1]) -## assert isinstance(instnode.cls.source, ListDescr) -## if instnode.cursize != -1: -## field = instnode.cursize -## instnode.cursize += 1 -## self.find_nodes_setfield(instnode, field, -## self.getnode(op.args[2])) -## continue -## elif opname == 'insert': -## instnode = self.getnode(op.args[1]) -## assert isinstance(instnode.cls.source, ListDescr) -## if instnode.cursize != -1: -## fieldbox = self.getsource(op.args[2]) -## assert isinstance(fieldbox, Const) or fieldbox.const -## field = fieldbox.getint() -## if field < 0: -## field = instnode.cursize + field -## self.find_nodes_insert(instnode, field, -## self.getnode(op.args[3])) -## continue -## elif opname == 'pop': -## instnode = self.getnode(op.args[1]) -## assert isinstance(instnode.cls.source, ListDescr) -## if instnode.cursize != -1: -## instnode.cursize -= 1 -## field = instnode.cursize -## self.find_nodes_getfield(instnode, field, op.results[0]) -## if field in instnode.curfields: -## del instnode.curfields[field] -## continue -## self.nodes[op.results[0]] = InstanceNode(op.results[0], -## escaped=True) -## self.dependency_graph.append((instnode, -## self.nodes[op.results[0]])) -## continue -## elif opname == 'len' or opname == 'listnonzero': -## instnode = self.getnode(op.args[1]) -## if not instnode.escaped: -## assert instnode.cursize != -1 -## lgtbox = op.results[0].constbox() -## self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) -## continue -## elif opname == 'setitem': -## instnode = self.getnode(op.args[1]) -## fieldbox = op.args[2] -## if (isinstance(fieldbox, ConstInt) -## or self.nodes[op.args[2]].const): -## field = self.getsource(fieldbox).getint() -## if field < 0: -## field = instnode.cursize + field -## assert field < instnode.cursize -## self.find_nodes_setfield(instnode, field, -## self.getnode(op.args[3])) -## continue -## else: -## self.dependency_graph.append((instnode, -## self.getnode(op.args[3]))) -## instnode.escaped = True elif opnum == rop.GUARD_CLASS: instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -537,7 +423,8 @@ instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) - instnode.vdesc = convert_vdesc(cpu, op.vdesc) + if op.vdesc: + instnode.vdesc = op.vdesc.virtuals continue elif op.is_always_pure(): for arg in op.args: @@ -598,17 +485,17 @@ specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes - def expanded_version_of(self, boxlist, oplist, cpu): + def expanded_version_of(self, boxlist, oplist): # oplist is None means at the start newboxlist = [] assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist, oplist, cpu) + specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) return newboxlist - def optimize_guard(self, op, cpu): + def optimize_guard(self, op): liveboxes = [] storage = AllocationStorage() memo = {} @@ -617,7 +504,7 @@ op = op.clone() for box in old_boxes: indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo, cpu)) + liveboxes, memo, self.cpu)) rev_boxes = {} for i in range(len(liveboxes)): box = liveboxes[i] @@ -668,6 +555,7 @@ return op def optimize_getfield(self, instnode, ofs, box): + assert isinstance(ofs, AbstractValue) if instnode.virtual or instnode.virtualized: ## if ofs < 0: ## ofs = instnode.cursize + ofs @@ -681,6 +569,7 @@ return False def optimize_setfield(self, instnode, ofs, valuenode, valuebox): + assert isinstance(ofs, AbstractValue) if instnode.virtual or instnode.virtualized: ## if ofs < 0: ## ofs = instnode.cursize + ofs @@ -699,11 +588,9 @@ ## instnode.curfields[field] = valuenode ## instnode.cursize += 1 - def optimize_loop(self, cpu): - #self.ready_results = {} + def optimize_loop(self): newoperations = [] exception_might_have_happened = False - #ops_so_far = [] mp = self.loop.operations[0] if mp.opnum == rop.MERGE_POINT: assert len(mp.args) == len(self.specnodes) @@ -717,61 +604,36 @@ assert not self.nodes[box].virtual for op in self.loop.operations: - #ops_so_far.append(op) - - #if newoperations and newoperations[-1].results: - # self.ready_results[newoperations[-1].results[0]] = None opnum = op.opnum if opnum == rop.MERGE_POINT: - args = self.expanded_version_of(op.args, None, cpu) + args = self.expanded_version_of(op.args, None) op = ResOperation(rop.MERGE_POINT, args, None) newoperations.append(op) - #for arg in op.args: - # self.ready_results[arg] = None continue - #elif opname == 'catch': - # for arg in op.args: - # self.ready_results[arg] = None elif opnum == rop.JUMP: - args = self.expanded_version_of(op.args, newoperations, cpu) + args = self.expanded_version_of(op.args, newoperations) for arg in args: if arg in self.nodes: assert not self.nodes[arg].virtual - self.cleanup_field_caches(newoperations, cpu) + self.cleanup_field_caches(newoperations) op = ResOperation(rop.JUMP, args, None) newoperations.append(op) continue -## elif opnum == rop.ARRAYLEN_GC: -## instnode = self.nodes[op.args[0]] - -## elif opname == 'guard_builtin': -## instnode = self.nodes[op.args[0]] -## if instnode.cls is None: -## instnode.cls = InstanceNode(op.args[1]) -## continue -## elif opname == 'guard_len': -## # it should be completely gone, because if it escapes -## # we don't virtualize it anymore -## instnode = self.nodes[op.args[0]] -## if not instnode.escaped and instnode.cursize == -1: -## instnode = self.nodes[op.args[0]] -## instnode.cursize = op.args[1].getint() -## continue elif opnum == rop.GUARD_NO_EXCEPTION: if not exception_might_have_happened: continue exception_might_have_happened = False - newoperations.append(self.optimize_guard(op, cpu)) + newoperations.append(self.optimize_guard(op)) continue elif opnum == rop.GUARD_EXCEPTION: - newoperations.append(self.optimize_guard(op, cpu)) + newoperations.append(self.optimize_guard(op)) continue elif (opnum == rop.GUARD_TRUE or opnum == rop.GUARD_FALSE): instnode = self.nodes[op.args[0]] if instnode.const: continue - newoperations.append(self.optimize_guard(op, cpu)) + newoperations.append(self.optimize_guard(op)) continue elif opnum == rop.GUARD_CLASS: instnode = self.nodes[op.args[0]] @@ -779,7 +641,7 @@ assert op.args[1].equals(instnode.cls.source) continue instnode.cls = InstanceNode(op.args[1], const=True) - newoperations.append(self.optimize_guard(op, cpu)) + newoperations.append(self.optimize_guard(op)) continue elif opnum == rop.GUARD_VALUE: instnode = self.nodes[op.args[0]] @@ -787,50 +649,38 @@ if instnode.const: continue instnode.const = True - newoperations.append(self.optimize_guard(op, cpu)) + newoperations.append(self.optimize_guard(op)) continue elif opnum == rop.GUARD_NONVIRTUALIZED: instnode = self.nodes[op.args[0]] if instnode.virtualized or instnode.virtual: continue - newoperations.append(self.optimize_guard(op, cpu)) + newoperations.append(self.optimize_guard(op)) continue elif opnum == rop.GETFIELD_GC: instnode = self.nodes[op.args[0]] - ofs = cpu.ofs_from_descr(op.descr) - if self.optimize_getfield(instnode, ofs, op.result): + if self.optimize_getfield(instnode, op.descr, op.result): continue # otherwise we need this getfield, but it does not # invalidate caches elif opnum == rop.GETFIELD_GC_PURE: instnode = self.nodes[op.args[0]] if not instnode.const: - ofs = cpu.ofs_from_descr(op.descr) - if self.optimize_getfield(instnode, ofs, op.result): + if self.optimize_getfield(instnode, op.descr, op.result): continue elif opnum == rop.GETARRAYITEM_GC: instnode = self.nodes[op.args[0]] ofsbox = self.getsource(op.args[1]) if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() - if self.optimize_getfield(instnode, ofs, op.result): + if self.optimize_getfield(instnode, ofsbox, op.result): continue elif opnum == rop.GETARRAYITEM_GC_PURE: instnode = self.nodes[op.args[0]] ofsbox = self.getsource(op.args[1]) if not instnode.const: if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() - if self.optimize_getfield(instnode, ofs, op.result): + if self.optimize_getfield(instnode, ofsbox, op.result): continue - -## elif opname == 'getitem': -## instnode = self.nodes[op.args[1]] -## ofsbox = self.getsource(op.args[2]) -## if isinstance(ofsbox, ConstInt): -## ofs = ofsbox.getint() -## if self.optimize_getfield(instnode, ofs, op.results[0]): -## continue elif opnum == rop.NEW_WITH_VTABLE: # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.result] @@ -844,50 +694,10 @@ instnode.virtual = True instnode.cursize = op.args[0].getint() continue -## elif opname == 'newlist': -## instnode = self.nodes[op.results[0]] -## assert isinstance(instnode.cls.source, ListDescr) -## if not instnode.escaped: -## instnode.virtual = True -## valuesource = self.getsource(op.args[2]) -## instnode.cursize = op.args[1].getint() -## curfields = {} -## for i in range(instnode.cursize): -## curfields[i] = InstanceNode(valuesource, -## const=True) -## instnode.curfields = curfields -## continue -## elif opname == 'append': -## instnode = self.nodes[op.args[1]] -## valuenode = self.getnode(op.args[2]) -## if not instnode.escaped: -## ofs = instnode.cursize -## instnode.cursize += 1 -## self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) -## continue -## elif opname == 'insert': -## instnode = self.nodes[op.args[1]] -## if not instnode.escaped: -## ofs = self.getsource(op.args[2]).getint() -## valuenode = self.nodes[op.args[3]] -## self.optimize_insert(instnode, ofs, valuenode, op.args[3]) -## continue -## elif opname == 'pop': -## instnode = self.nodes[op.args[1]] -## if not instnode.escaped: -## instnode.cursize -= 1 -## ofs = instnode.cursize -## if self.optimize_getfield(instnode, ofs, op.results[0]): -## del instnode.curfields[ofs] -## continue -## elif opname == 'len' or opname == 'listnonzero': -## instnode = self.nodes[op.args[1]] -## if instnode.virtual: -## continue elif opnum == rop.SETFIELD_GC: instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[1]] - ofs = cpu.ofs_from_descr(op.descr) + ofs = op.descr self.optimize_setfield(instnode, ofs, valuenode, op.args[1]) continue elif opnum == rop.SETARRAYITEM_GC: @@ -896,18 +706,10 @@ instnode.cls = InstanceNode(FixedList(op.descr)) ofsbox = self.getsource(op.args[1]) if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() valuenode = self.getnode(op.args[2]) - self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) + self.optimize_setfield(instnode, ofsbox, valuenode, + op.args[2]) continue -## elif opname == 'setitem': -## instnode = self.nodes[op.args[1]] -## valuenode = self.getnode(op.args[3]) -## ofsbox = self.getsource(op.args[2]) -## if isinstance(ofsbox, ConstInt): -## ofs = ofsbox.getint() -## self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) -## continue elif (opnum == rop.OOISNULL or opnum == rop.OONONNULL): instnode = self.getnode(op.args[0]) @@ -954,7 +756,7 @@ opnum != rop.SETARRAYITEM_GC): # the setfield operations do not clean up caches, although # they have side effects - self.cleanup_field_caches(newoperations, cpu) + self.cleanup_field_caches(newoperations) if op.can_raise(): exception_might_have_happened = True box = op.result @@ -966,7 +768,7 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations - def cleanup_field_caches(self, newoperations, cpu): + def cleanup_field_caches(self, newoperations): # we need to invalidate everything for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): @@ -976,12 +778,11 @@ ld = node.cls.source assert isinstance(ld, FixedList) newoperations.append(ResOperation(rop.SETARRAYITEM_GC, - [node.source, ConstInt(ofs), valuenode.source], + [node.source, ofs, valuenode.source], None, ld.arraydescr)) else: - descr = cpu.repack_descr(ofs) newoperations.append(ResOperation(rop.SETFIELD_GC, - [node.source, valuenode.source], None, descr)) + [node.source, valuenode.source], None, ofs)) node.dirtyfields = {} node.cleanfields = {} @@ -1054,16 +855,15 @@ box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) - descr = metainterp.cpu.repack_descr(ofs) metainterp.execute_and_record(rop.SETFIELD_GC, - [box, fieldbox], descr) + [box, fieldbox], ofs) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_arglist) box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) metainterp.execute_and_record(rop.SETARRAYITEM_GC, - [box, ConstInt(ofs), itembox], ad) + [box, ofs, itembox], ad) ## if storage.setitems: ## #history.execute_and_record('guard_no_exception', [], 'void', False) ## # XXX this needs to check for exceptions somehow @@ -1082,14 +882,15 @@ def partition(array, left, right): - pivot = array[right] + last_item = array[right] + pivot = last_item.sort_key() storeindex = left for i in range(left, right): - if array[i] <= pivot: + if array[i].sort_key() <= pivot: array[i], array[storeindex] = array[storeindex], array[i] storeindex += 1 # Move pivot to its final place - array[storeindex], array[right] = pivot, array[storeindex] + array[storeindex], array[right] = last_item, array[storeindex] return storeindex def quicksort(array, left, right): @@ -1099,5 +900,5 @@ quicksort(array, left, pivotnewindex - 1) quicksort(array, pivotnewindex + 1, right) -def sort_integers(lst): +def sort_descrs(lst): quicksort(lst, 0, len(lst)-1) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 12 15:11:19 2009 @@ -512,14 +512,14 @@ ## 'len', [builtin.len_func, box], 'int') ## self.generate_guard(pc, "guard_len", box, [intbox]) - @arguments("orgpc", "box", "virtualizabledesc", "int") + @arguments("orgpc", "box", "virtualizabledesc", "constbox") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) op = self.generate_guard(pc, rop.GUARD_NONVIRTUALIZED, box, [clsbox]) if op: op.vdesc = vdesc - op.descr = guard_field + op.setdescr(guard_field) @arguments("box") def opimpl_keepalive(self, box): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 12 15:11:19 2009 @@ -18,15 +18,20 @@ vdesc = None def __init__(self, opnum, args, result, descr=None): - from pypy.jit.metainterp.history import AbstractValue assert isinstance(opnum, int) self.opnum = opnum self.args = list(args) assert not isinstance(result, list) self.result = result + self.setdescr(descr) + + def setdescr(self, descr): # for 'call', 'new', 'getfield_gc'...: the descr is a number provided - # by the backend holding details about the type of the operation + # by the backend holding details about the type of the operation -- + # actually an instance of a class, typically Descr, that inherits + # from AbstractValue if descr is not None: + from pypy.jit.metainterp.history import AbstractValue assert isinstance(descr, AbstractValue) self.descr = descr Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Thu Mar 12 15:11:19 2009 @@ -1,10 +1,9 @@ from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.history import ConstInt from pypy.jit.metainterp import executor class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist, start, cpu): + def expand_boxlist(self, instnode, newboxlist, start): newboxlist.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): @@ -119,16 +118,15 @@ return False return True - def expand_boxlist(self, instnode, newboxlist, start, cpu): + def expand_boxlist(self, instnode, newboxlist, start): for ofs, subspecnode in self.fields: subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start, cpu) + subspecnode.expand_boxlist(subinstnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: - descr = cpu.repack_descr(ofs) fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox], descr) + [valuebox], ofs) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): @@ -137,10 +135,9 @@ class VirtualizedSpecNode(SpecNodeWithFields): - def expand_boxlist(self, instnode, newboxlist, start, cpu): + def expand_boxlist(self, instnode, newboxlist, start): newboxlist.append(instnode.source) - SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start, - cpu) + SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) @@ -152,7 +149,7 @@ class DelayedSpecNode(VirtualizedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist, cpu): + def expand_boxlist(self, instnode, newboxlist, oplist): newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) @@ -164,15 +161,14 @@ newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() - descr = cpu.repack_descr(ofs) oplist.append(ResOperation(rop.GETFIELD_GC, - [instnode.source], box, descr)) + [instnode.source], box, ofs)) newboxlist.append(box) class DelayedFixedListSpecNode(DelayedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist, cpu): - from pypy.jit.metainterp.history import ResOperation, ConstInt + def expand_boxlist(self, instnode, newboxlist, oplist): + from pypy.jit.metainterp.history import ResOperation from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList @@ -191,7 +187,7 @@ else: box = subspecnode.box.clonebox() oplist.append(ResOperation(rop.GETARRAYITEM_GC, - [instnode.source, ConstInt(ofs)], box, arraydescr)) + [instnode.source, ofs], box, arraydescr)) newboxlist.append(box) def extract_runtime_data(self, cpu, valuebox, resultlist): @@ -204,7 +200,7 @@ arraydescr = cls.arraydescr for ofs, subspecnode in self.fields: fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ConstInt(ofs)], arraydescr) + [valuebox, ofs], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualizableSpecNode(VirtualizedSpecNode): @@ -244,7 +240,6 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop - from pypy.jit.metainterp.history import ConstInt from pypy.jit.metainterp.optimize import FixedList for ofs, subspecnode in self.fields: @@ -252,5 +247,5 @@ assert isinstance(cls, FixedList) arraydescr = cls.arraydescr fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ConstInt(ofs)], arraydescr) + [valuebox, ofs], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Thu Mar 12 15:11:19 2009 @@ -33,7 +33,7 @@ spec.find_nodes() node = spec.nodes[A.l] assert isinstance(node.cls.source, FixedList) - assert node.expanded_fields.keys() == [0] + assert node.expanded_fields.keys() == [ConstInt(0)] def test_A_intersect(): spec = PerfectSpecializer(Loop(A.ops)) @@ -45,7 +45,7 @@ spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation(rop.MERGE_POINT, [A.l, A.e0], None), ResOperation(rop.SETARRAYITEM_GC, [A.l, ConstInt(0), A.e0], None, A.ad), @@ -74,7 +74,7 @@ spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation(rop.MERGE_POINT, [B.l, B.e0], None), ResOperation(rop.INT_ADD, [B.e0, ConstInt(1)], B.e1), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 12 15:11:19 2009 @@ -133,7 +133,7 @@ spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [A.sum, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), @@ -181,7 +181,7 @@ spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [B.sum, B.n1], None), # guard_class is gone @@ -236,7 +236,7 @@ spec = PerfectSpecializer(Loop(C.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone @@ -295,7 +295,7 @@ spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [E.sum, E.v], None), # guard_class is gone @@ -327,7 +327,7 @@ spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() guard_op = spec.loop.operations[-2] v_sum_b = BoxInt(13) v_v_b = BoxInt(14) @@ -385,7 +385,7 @@ spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [F.sum, F.v, F.n3], None), ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), @@ -417,7 +417,7 @@ spec = PerfectSpecializer(Loop(F2.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, F2.ops) # ____________________________________________________________ @@ -447,7 +447,7 @@ spec = PerfectSpecializer(Loop(G.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [G.sum, G.v], None), # guard_class is gone @@ -577,7 +577,7 @@ spec = PerfectSpecializer(Loop(K0.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K0.sum, K0.n1, K0.v], None), @@ -611,7 +611,7 @@ spec = PerfectSpecializer(Loop(K1.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K1.sum, K1.n1, K1.v], None), @@ -644,7 +644,7 @@ spec = PerfectSpecializer(Loop(K.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [K.sum, K.n1, K.v], None), ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), @@ -675,7 +675,7 @@ spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [L.sum, L.n1, L.v], None), ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), @@ -706,7 +706,7 @@ spec = PerfectSpecializer(Loop(M.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [M.sum, M.n1, M.v], None), @@ -737,7 +737,7 @@ spec = PerfectSpecializer(Loop(N.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] equaloplists(spec.loop.operations, [ ResOperation('merge_point', [N.sum, N.n1, N.v], None), @@ -766,7 +766,7 @@ spec = PerfectSpecializer(Loop(O1.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O1.n1), @@ -796,7 +796,7 @@ spec = PerfectSpecializer(Loop(O2.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O2.n1), @@ -828,7 +828,7 @@ spec = PerfectSpecializer(Loop(O3.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [], None), ResOperation('escape', [], O3.n1), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Mar 12 15:11:19 2009 @@ -118,7 +118,7 @@ spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() - spec.optimize_loop(None) + spec.optimize_loop() equaloplists(spec.loop.operations, [ ResOperation('merge_point', [A.sum, A.fr, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), From arigo at codespeak.net Thu Mar 12 15:59:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 15:59:03 +0100 (CET) Subject: [pypy-svn] r62889 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp Message-ID: <20090312145903.58D4B1684B9@codespeak.net> Author: arigo Date: Thu Mar 12 15:59:02 2009 New Revision: 62889 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Log: Add an abstract class, AbstractDescr, inheriting from AbstractValue. Allows us to do asserts in metainterp. Fix all places found by these asserts. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 12 15:59:02 2009 @@ -14,7 +14,7 @@ pass -class Descr(history.AbstractValue): +class Descr(history.AbstractDescr): def __init__(self, ofs, type='?'): self.ofs = ofs self.type = type Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Thu Mar 12 15:59:02 2009 @@ -3,7 +3,7 @@ import py from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask -from pypy.jit.metainterp.history import BoxInt, ConstInt +from pypy.jit.metainterp.history import BoxInt, ConstInt, check_descr from pypy.jit.metainterp.resoperation import rop @@ -214,6 +214,7 @@ get_execute_function._annspecialcase_ = 'specialize:memo' def execute(cpu, opnum, argboxes, descr=None): + check_descr(descr) func = get_execute_function(cpu, opnum) return func(cpu, argboxes, descr) execute._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 12 15:59:02 2009 @@ -1,4 +1,5 @@ +from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic from pypy.rlib.rarithmetic import intmask @@ -76,6 +77,11 @@ def equals(self, other): raise NotImplementedError + +class AbstractDescr(AbstractValue): + pass + + class Const(AbstractValue): __slots__ = () @@ -476,3 +482,25 @@ self.listops = listops def _freeze_(self): return True + +# ---------------------------------------------------------------- + +def check_descr(x): + """Check that 'x' is None or an instance of AbstractDescr. + Explodes if the annotator only thinks it is an instance of AbstractValue. + """ + +class Entry(ExtRegistryEntry): + _about_ = check_descr + + def compute_result_annotation(self, s_x): + from pypy.annotation import model as annmodel + if not annmodel.s_None.contains(s_x): + assert isinstance(s_x, annmodel.SomeInstance) + # the following assert fails if we somehow did not manage + # to ensure that the 'descr' field of ResOperation is really + # an instance of AbstractDescr, a subclass of AbstractValue. + assert issubclass(s_x.classdef.classdesc.pyobj, AbstractDescr) + + def specialize_call(self, hop): + hop.exception_cannot_occur() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 12 15:59:02 2009 @@ -1,7 +1,7 @@ from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, - ResOperation) -from pypy.jit.metainterp.history import Options, AbstractValue, ConstPtr + ResOperation, AbstractDescr, + Options, AbstractValue, ConstPtr) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, #FixedListSpecNode, VirtualInstanceSpecNode, @@ -781,6 +781,7 @@ [node.source, ofs, valuenode.source], None, ld.arraydescr)) else: + assert isinstance(ofs, AbstractDescr) newoperations.append(ResOperation(rop.SETFIELD_GC, [node.source, valuenode.source], None, ofs)) node.dirtyfields = {} @@ -855,6 +856,7 @@ box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) + assert isinstance(ofs, AbstractDescr) metainterp.execute_and_record(rop.SETFIELD_GC, [box, fieldbox], ofs) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 12 15:59:02 2009 @@ -65,6 +65,10 @@ args += (self.load_varargs(), ) elif argspec == "constargs": args += (self.load_constargs(), ) + elif argspec == "descr": + descr = self.load_const_arg() + assert isinstance(descr, history.AbstractDescr) + args += (descr, ) elif argspec == "bytecode": bytecode = self.load_const_arg() assert isinstance(bytecode, codewriter.JitCode) @@ -311,38 +315,38 @@ except KeyError: pass - @arguments("constbox") + @arguments("descr") def opimpl_new(self, size): self.execute(rop.NEW, [], descr=size) - @arguments("constbox", "constbox") + @arguments("descr", "constbox") def opimpl_new_with_vtable(self, size, vtablebox): self.execute(rop.NEW_WITH_VTABLE, [vtablebox], descr=size) - @arguments("constbox", "box") + @arguments("descr", "box") def opimpl_new_array(self, itemsize, countbox): self.execute(rop.NEW_ARRAY, [countbox], descr=itemsize) - @arguments("box", "constbox", "box") + @arguments("box", "descr", "box") def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): self.execute(rop.GETARRAYITEM_GC, [arraybox, indexbox], descr=arraydesc) - @arguments("box", "constbox", "box") + @arguments("box", "descr", "box") def opimpl_getarrayitem_gc_pure(self, arraybox, arraydesc, indexbox): self.execute(rop.GETARRAYITEM_GC_PURE, [arraybox, indexbox], descr=arraydesc) - @arguments("box", "constbox", "box", "box") + @arguments("box", "descr", "box", "box") def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): self.execute(rop.SETARRAYITEM_GC, [arraybox, indexbox, itembox], descr=arraydesc) - @arguments("box", "constbox") + @arguments("box", "descr") def opimpl_arraylen_gc(self, arraybox, arraydesc): self.execute(rop.ARRAYLEN_GC, [arraybox], descr=arraydesc) - @arguments("orgpc", "box", "constbox", "box") + @arguments("orgpc", "box", "descr", "box") def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox): negbox = self.metainterp.execute_and_record( rop.INT_LT, [indexbox, ConstInt(0)]) @@ -372,23 +376,23 @@ self.execute(rop.OOISNOT, [box1, box2]) - @arguments("box", "constbox") + @arguments("box", "descr") def opimpl_getfield_gc(self, box, fielddesc): self.execute(rop.GETFIELD_GC, [box], descr=fielddesc) - @arguments("box", "constbox") + @arguments("box", "descr") def opimpl_getfield_gc_pure(self, box, fielddesc): self.execute(rop.GETFIELD_GC_PURE, [box], descr=fielddesc) - @arguments("box", "constbox", "box") + @arguments("box", "descr", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_GC, [box, valuebox], descr=fielddesc) - @arguments("box", "constbox") + @arguments("box", "descr") def opimpl_getfield_raw(self, box, fielddesc): self.execute(rop.GETFIELD_RAW, [box], descr=fielddesc) - @arguments("box", "constbox") + @arguments("box", "descr") def opimpl_getfield_raw_pure(self, box, fielddesc): self.execute(rop.GETFIELD_RAW_PURE, [box], descr=fielddesc) - @arguments("box", "constbox", "box") + @arguments("box", "descr", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc) @@ -407,11 +411,11 @@ f.setup_call(varargs) return True - @arguments("constbox", "varargs") + @arguments("descr", "varargs") def opimpl_residual_call(self, calldescr, varargs): return self.execute_with_exc(rop.CALL, varargs, descr=calldescr) - @arguments("constbox", "varargs") + @arguments("descr", "varargs") def opimpl_residual_call_pure(self, calldescr, varargs): self.execute(rop.CALL_PURE, varargs, descr=calldescr) @@ -512,7 +516,7 @@ ## 'len', [builtin.len_func, box], 'int') ## self.generate_guard(pc, "guard_len", box, [intbox]) - @arguments("orgpc", "box", "virtualizabledesc", "constbox") + @arguments("orgpc", "box", "virtualizabledesc", "descr") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) op = self.generate_guard(pc, rop.GUARD_NONVIRTUALIZED, box, @@ -663,6 +667,7 @@ @specialize.arg(1) def execute_with_exc(self, opnum, argboxes, descr=None): cpu = self.metainterp.cpu + history.check_descr(descr) resbox = executor.execute(cpu, opnum, argboxes, descr) if not we_are_translated(): self.metainterp._debug_history.append(['call', @@ -765,6 +770,7 @@ def execute_and_record(self, opnum, argboxes, descr=None): # execute the operation first + history.check_descr(descr) resbox = executor.execute(self.cpu, opnum, argboxes, descr) # check if the operation can be constant-folded away canfold = False Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 12 15:59:02 2009 @@ -29,10 +29,9 @@ # for 'call', 'new', 'getfield_gc'...: the descr is a number provided # by the backend holding details about the type of the operation -- # actually an instance of a class, typically Descr, that inherits - # from AbstractValue - if descr is not None: - from pypy.jit.metainterp.history import AbstractValue - assert isinstance(descr, AbstractValue) + # from AbstractDescr + from pypy.jit.metainterp.history import check_descr + check_descr(descr) self.descr = descr def __repr__(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Thu Mar 12 15:59:02 2009 @@ -125,6 +125,8 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: + from pypy.jit.metainterp.history import AbstractDescr + assert isinstance(ofs, AbstractDescr) fieldbox = executor.execute(cpu, rop.GETFIELD_GC, [valuebox], ofs) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) @@ -150,6 +152,7 @@ class DelayedSpecNode(VirtualizedSpecNode): def expand_boxlist(self, instnode, newboxlist, oplist): + from pypy.jit.metainterp.history import AbstractDescr newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) @@ -161,6 +164,7 @@ newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() + assert isinstance(ofs, AbstractDescr) oplist.append(ResOperation(rop.GETFIELD_GC, [instnode.source], box, ofs)) newboxlist.append(box) @@ -193,11 +197,13 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList + from pypy.jit.metainterp.history import check_descr resultlist.append(valuebox) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr + check_descr(arraydescr) for ofs, subspecnode in self.fields: fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, [valuebox, ofs], arraydescr) @@ -241,11 +247,12 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList - + from pypy.jit.metainterp.history import check_descr + cls = self.known_class + assert isinstance(cls, FixedList) + arraydescr = cls.arraydescr + check_descr(arraydescr) for ofs, subspecnode in self.fields: - cls = self.known_class - assert isinstance(cls, FixedList) - arraydescr = cls.arraydescr fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, [valuebox, ofs], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) From arigo at codespeak.net Thu Mar 12 16:06:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 16:06:49 +0100 (CET) Subject: [pypy-svn] r62890 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312150649.F18731684B9@codespeak.net> Author: arigo Date: Thu Mar 12 16:06:49 2009 New Revision: 62890 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Start fixing the x86 backend for the previous checkin. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 16:06:49 2009 @@ -732,10 +732,10 @@ consider_call_pure = consider_call def consider_new(self, op, ignored): - return self._call(op, [imm(op.descr.getint())]) + return self._call(op, [imm(op.descr.v[0])]) def consider_new_with_vtable(self, op, ignored): - return self._call(op, [imm(op.descr.getint()), self.loc(op.args[0])]) + return self._call(op, [imm(op.descr.v[0]), self.loc(op.args[0])]) def consider_newstr(self, op, ignored): ofs_items, _, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Thu Mar 12 16:06:49 2009 @@ -10,7 +10,7 @@ from pypy.rpython.lltypesystem import rclass from pypy.jit.metainterp import history, codewriter from pypy.jit.metainterp.history import (ResOperation, Box, Const, - ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) + ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr, AbstractDescr) from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname @@ -23,8 +23,9 @@ PTR = 1 INT = 2 -class ConstDescr3(Const): +class ConstDescr3(AbstractDescr): def __init__(self, v): + # XXX don't use a tuple! that's yet another indirection... self.v = v def _v(self): @@ -409,7 +410,8 @@ frame[mp.stacklocs[argindex]] = self.convert_box_to_int(valuebox) def sizeof(self, S): - return ConstInt(symbolic.get_size(S, self.translate_support_code)) + size = symbolic.get_size(S, self.translate_support_code) + return ConstDescr3((size, 0, False)) numof = sizeof # addresssuffix = str(symbolic.get_size(llmemory.Address)) @@ -529,11 +531,11 @@ self._base_do_setfield(fielddescr, args[0].getint(), args[1]) def do_new(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.getint()) + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.v[0]) return BoxPtr(self.cast_int_to_gcref(res)) def do_new_with_vtable(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.getint()) + res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.v[0]) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[0].getint() return BoxPtr(self.cast_int_to_gcref(res)) @@ -598,24 +600,6 @@ ptr = False return ConstDescr3((basesize, itemsize, ptr)) - def ofs_from_descr(self, descr): - assert isinstance(descr, ConstDescr3) - x = (descr.v[0] << 16) + descr.v[1] - if descr.v[2]: - return ~x - return x - - def repack_descr(self, ofs): - orig_ofs = ofs - if ofs < 0: - ptr = True - ofs = ~ofs - else: - ptr = False - res = ConstDescr3((ofs>>16, ofs & 0xffff, ptr)) - assert self.ofs_from_descr(res) == orig_ofs - return res - @staticmethod def unpack_arraydescr(arraydescr): assert isinstance(arraydescr, ConstDescr3) @@ -658,12 +642,6 @@ return fielddescr.v @staticmethod - def typefor(fielddesc): - if fieldesc[2]: - return 'ptr' - return "int" - - @staticmethod def cast_int_to_adr(x): return llmemory.cast_ptr_to_adr(rffi.cast(llmemory.GCREF, x)) From arigo at codespeak.net Thu Mar 12 16:13:52 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 16:13:52 +0100 (CET) Subject: [pypy-svn] r62891 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312151352.96C511684B9@codespeak.net> Author: arigo Date: Thu Mar 12 16:13:51 2009 New Revision: 62891 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Finish fixing the x86 backend for the previous checkin. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Thu Mar 12 16:13:51 2009 @@ -37,6 +37,8 @@ l.append(i) return tuple(l) + def sort_key(self): + return self.v[0] # the ofs field for fielddescrs def __hash__(self): return hash(self._v()) From fijal at codespeak.net Thu Mar 12 16:33:24 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 16:33:24 +0100 (CET) Subject: [pypy-svn] r62892 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312153324.AEF2F16847A@codespeak.net> Author: fijal Date: Thu Mar 12 16:33:23 2009 New Revision: 62892 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: avoid rtyping warning Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Mar 12 16:33:23 2009 @@ -77,6 +77,8 @@ def equals(self, other): raise NotImplementedError + def sort_key(self): + raise NotImplementedError class AbstractDescr(AbstractValue): pass From fijal at codespeak.net Thu Mar 12 16:41:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 16:41:19 +0100 (CET) Subject: [pypy-svn] r62893 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312154119.C4D8116847C@codespeak.net> Author: fijal Date: Thu Mar 12 16:41:19 2009 New Revision: 62893 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py Log: port another fix from bck branch - return size of field instead of the whole structure. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/symbolic.py Thu Mar 12 16:41:19 2009 @@ -6,7 +6,7 @@ def get_field_token(STRUCT, fieldname, translate_support_code): if translate_support_code: return (llmemory.offsetof(STRUCT, fieldname), - get_size(STRUCT, True)) + get_size(getattr(STRUCT, fieldname), True)) cstruct = ll2ctypes.get_ctypes_type(STRUCT) cfield = getattr(cstruct, fieldname) return (cfield.offset, cfield.size) From fijal at codespeak.net Thu Mar 12 17:21:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 17:21:19 +0100 (CET) Subject: [pypy-svn] r62894 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090312162119.5AE351684B4@codespeak.net> Author: fijal Date: Thu Mar 12 17:21:15 2009 New Revision: 62894 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: a test that fails for obscure reasons Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Thu Mar 12 17:21:15 2009 @@ -5,6 +5,7 @@ from pypy.jit.metainterp import support, codewriter, pyjitpl, history from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy from pypy import conftest +from pypy.rlib.rarithmetic import ovfcheck def get_metainterp(func, values, CPUClass, type_system, policy, listops=False): @@ -300,6 +301,16 @@ res = self.interp_operations(f, [5]) assert res == 17 + def test_mod_ovf(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y']) + def f(n, x, y): + while n > 0: + myjitdriver.can_enter_jit(x=x, y=y, n=n) + myjitdriver.jit_merge_point(x=x, y=y, n=n) + n -= ovfcheck(x % y) + return n + res = self.meta_interp(f, [20, 1, 2]) + assert res == 0 class TestOOtype(BasicTests, OOJitMixin): pass From fijal at codespeak.net Thu Mar 12 17:25:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 17:25:35 +0100 (CET) Subject: [pypy-svn] r62895 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090312162535.46FB61684B5@codespeak.net> Author: fijal Date: Thu Mar 12 17:25:34 2009 New Revision: 62895 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py Log: skip only selected tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_slist.py Thu Mar 12 17:25:34 2009 @@ -1,6 +1,5 @@ import py -py.test.skip("XXX fails") from pypy.jit.metainterp.test.test_slist import ListTests from pypy.jit.backend.x86.support import c_meta_interp @@ -12,6 +11,9 @@ def check_loops(self, *args, **kwds): pass + def interp_operations(self, *args, **kwds): + py.test.skip("using interp_operations") + class TestSList(Jit386Mixin, ListTests): # for the individual tests see # ====> ../../test/test_slist.py From fijal at codespeak.net Thu Mar 12 18:26:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 18:26:20 +0100 (CET) Subject: [pypy-svn] r62896 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312172620.E8CE41684CD@codespeak.net> Author: fijal Date: Thu Mar 12 18:26:17 2009 New Revision: 62896 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Log: Use r_dicts in place of regular dicts and remove some old code. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 12 18:26:17 2009 @@ -3,22 +3,18 @@ ResOperation, AbstractDescr, Options, AbstractValue, ConstPtr) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, - #FixedListSpecNode, VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, DelayedSpecNode, SpecNodeWithBox, DelayedFixedListSpecNode, - #DelayedListSpecNode, VirtualFixedListSpecNode, - #VirtualListSpecNode, ) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype, llmemory -#from pypy.jit.metainterp.codewriter import ListDescr - +from pypy.rlib.objectmodel import r_dict class FixedList(AbstractValue): def __init__(self, arraydescr): @@ -105,6 +101,18 @@ liveboxes.append(box) return res +def av_eq(self, other): + return self.sort_key() == other.sort_key() + +def av_hash(self): + return self.sort_key() + +def av_list_in(lst, key): + for l in lst: + if key.sort_key() == l.sort_key(): + return True + return False + class InstanceNode(object): def __init__(self, source, escaped=True, startbox=False, const=False): if isinstance(source, Const): @@ -117,11 +125,11 @@ self.const = const self.nonzero = False # NB. never set to True so far self.cls = None - self.origfields = {} - self.curfields = {} - self.cleanfields = {} - self.dirtyfields = {} - self.expanded_fields = {} + self.origfields = r_dict(av_eq, av_hash) + self.curfields = r_dict(av_eq, av_hash) + self.cleanfields = r_dict(av_eq, av_hash) + self.dirtyfields = r_dict(av_eq, av_hash) + self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables @@ -142,7 +150,7 @@ node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - if self.vdesc is not None and key not in self.vdesc: + if self.vdesc is not None and not av_list_in(self.vdesc, key): esc_self = True else: esc_self = False @@ -151,7 +159,7 @@ # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: - if self.vdesc is not None and key not in self.vdesc: + if self.vdesc is not None and not av_list_in(self.vdesc, key): esc_self = True else: esc_self = False @@ -163,7 +171,7 @@ if ofs in other.curfields: node.add_to_dependency_graph(other.curfields[ofs], dep_graph) if (self.virtualized and self.vdesc is not None and - ofs in self.vdesc): + av_list_in(self.vdesc, ofs)): node.add_to_dependency_graph(other.origfields[ofs], dep_graph) def intersect(self, other, nodes): @@ -545,7 +553,6 @@ instnode = self.nodes[box] assert not instnode.virtual box = instnode.source - #assert isinstance(box, Const) or box in self.ready_results newboxes.append(box) return newboxes @@ -557,8 +564,6 @@ def optimize_getfield(self, instnode, ofs, box): assert isinstance(ofs, AbstractValue) if instnode.virtual or instnode.virtualized: -## if ofs < 0: -## ofs = instnode.cursize + ofs assert ofs in instnode.curfields return True # this means field is never actually elif ofs in instnode.cleanfields: @@ -571,8 +576,6 @@ def optimize_setfield(self, instnode, ofs, valuenode, valuebox): assert isinstance(ofs, AbstractValue) if instnode.virtual or instnode.virtualized: -## if ofs < 0: -## ofs = instnode.cursize + ofs instnode.curfields[ofs] = valuenode else: assert not valuenode.virtual @@ -580,14 +583,6 @@ instnode.dirtyfields[ofs] = self.nodes[valuebox] # we never perform this operation here, note -## def optimize_insert(self, instnode, field, valuenode, valuebox): -## assert instnode.virtual -## for ofs, node in instnode.curfields.items(): -## if ofs >= field: -## instnode.curfields[ofs + 1] = node -## instnode.curfields[field] = valuenode -## instnode.cursize += 1 - def optimize_loop(self): newoperations = [] exception_might_have_happened = False @@ -784,8 +779,8 @@ assert isinstance(ofs, AbstractDescr) newoperations.append(ResOperation(rop.SETFIELD_GC, [node.source, valuenode.source], None, ofs)) - node.dirtyfields = {} - node.cleanfields = {} + node.dirtyfields = r_dict(av_eq, av_hash) + node.cleanfields = r_dict(av_eq, av_hash) def match_exactly(self, old_loop): old_operations = old_loop.operations @@ -866,11 +861,6 @@ boxes_from_frame, index_in_alloc) metainterp.execute_and_record(rop.SETARRAYITEM_GC, [box, ofs, itembox], ad) -## if storage.setitems: -## #history.execute_and_record('guard_no_exception', [], 'void', False) -## # XXX this needs to check for exceptions somehow -## # create guard_no_excpetion somehow, needs tests -## pass newboxes = [] for index in storage.indices: if index < 0: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Thu Mar 12 18:26:17 2009 @@ -83,8 +83,11 @@ self.fields = fields def mutate_nodes(self, instnode): + from pypy.jit.metainterp.optimize import av_eq, av_hash + from pypy.rlib.objectmodel import r_dict + FixedClassSpecNode.mutate_nodes(self, instnode) - curfields = {} + curfields = r_dict(av_eq, av_hash) for ofs, subspecnode in self.fields: subinstnode = instnode.origfields[ofs] # should really be there From fijal at codespeak.net Thu Mar 12 18:35:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 18:35:19 +0100 (CET) Subject: [pypy-svn] r62897 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312173519.690C71684AA@codespeak.net> Author: fijal Date: Thu Mar 12 18:35:19 2009 New Revision: 62897 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: a bit of debugging info in case we're translated Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 12 18:35:19 2009 @@ -85,6 +85,14 @@ print pprint.pprint(computed_ops) print + if self.verbose and we_are_translated(): + print + for op in operations: + args = ",".join([str(arg.get_()) for arg in op.args]) + llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) + if op.result is not None: + llop.debug_print(lltype.Void, " => %s" % str(op.result.get_())) + print for i in range(len(computed_ops)): op = computed_ops[i] if not we_are_translated(): From arigo at codespeak.net Thu Mar 12 18:40:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 18:40:17 +0100 (CET) Subject: [pypy-svn] r62898 - in pypy/branch/pyjitpl5/pypy/translator: . test Message-ID: <20090312174017.08ADA1684C8@codespeak.net> Author: arigo Date: Thu Mar 12 18:40:17 2009 New Revision: 62898 Modified: pypy/branch/pyjitpl5/pypy/translator/simplify.py pypy/branch/pyjitpl5/pypy/translator/test/test_simplify.py Log: Attempt to rewrite from scratch transform_ovfcheck(). Hopefully I've written enough tests to cover all cases... The point is that test_remove_ovfcheck_bug() used to crash. Modified: pypy/branch/pyjitpl5/pypy/translator/simplify.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/simplify.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/simplify.py Thu Mar 12 18:40:17 2009 @@ -101,124 +101,51 @@ """The special function calls ovfcheck and ovfcheck_lshift need to be translated into primitive operations. ovfcheck is called directly after an operation that should be turned into an overflow-checked - version. It is considered a syntax error if the resulting -ovf - is not defined in baseobjspace.py . + version. It is considered a syntax error if the resulting _ovf + is not defined in objspace/flow/objspace.py. ovfcheck_lshift is special because there is no preceding operation. Instead, it will be replaced by an OP_LSHIFT_OVF operation. - - The exception handling of the original operation is completely - ignored. Only exception handlers for the ovfcheck function call - are taken into account. This gives us the best possible control - over situations where we want exact contol over certain operations. - Example: - - try: - array1[idx-1] = ovfcheck(array1[idx-1] + array2[idx+1]) - except OverflowError: - ... - - assuming two integer arrays, we are only checking the element addition - for overflows, but the indexing is not checked. """ - # General assumption: - # empty blocks have been eliminated. - # ovfcheck can appear in the same block with its operation. - # this is the case if no exception handling was provided. - # Otherwise, we have a block ending in the operation, - # followed by a block with a single ovfcheck call. from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift - from pypy.objspace.flow.objspace import op_appendices from pypy.objspace.flow.objspace import implicit_exceptions covf = Constant(ovfcheck) covfls = Constant(ovfcheck_lshift) - appendix = op_appendices[OverflowError] - renaming = {} - seen_ovfblocks = {} - - # get all blocks - blocks = {} - def visit(block): - if isinstance(block, Block): - blocks[block] = True - traverse(visit, graph) - def is_ovfcheck(bl): - ops = bl.operations - return (ops and ops[-1].opname == "simple_call" - and ops[-1].args[0] == covf) - def is_ovfshiftcheck(bl): - ops = bl.operations - return (ops and ops[-1].opname == "simple_call" - and ops[-1].args[0] == covfls) - def is_single(bl): - return is_ovfcheck(bl) and len(bl.operations) > 1 - def is_paired(bl): - if bl.exits: - ovfblock = bl.exits[0].target - return (bl.exits and is_ovfcheck(ovfblock) and - len(ovfblock.operations) == 1) - def rename(v): - return renaming.get(v, v) - def remove_last_op(bl): - delop = bl.operations.pop() - assert delop.opname == "simple_call" - assert len(delop.args) == 2 - renaming[delop.result] = rename(delop.args[1]) - for exit in bl.exits: - exit.args = [rename(a) for a in exit.args] - - def check_syntax(ovfblock, block=None): - """check whether ovfblock is reachable more than once - or if they cheated about the argument""" - if block: - link = block.exits[0] - for lprev, ltarg in zip(link.args, ovfblock.inputargs): - renaming[ltarg] = rename(lprev) - arg = ovfblock.operations[0].args[-1] - res = block.operations[-1].result - opname = block.operations[-1].opname - else: - arg = ovfblock.operations[-1].args[-1] - res = ovfblock.operations[-2].result - opname = ovfblock.operations[-2].opname - if rename(arg) != rename(res) or ovfblock in seen_ovfblocks: - raise SyntaxError("ovfcheck in %s: The checked operation %s" - " is misplaced" % (graph.name, opname)) - exlis = implicit_exceptions.get("%s_%s" % (opname, appendix), []) + def check_syntax(opname): + exlis = implicit_exceptions.get("%s_ovf" % (opname,), []) if OverflowError not in exlis: - raise SyntaxError("ovfcheck in %s: Operation %s has no" - " overflow variant" % (graph.name, opname)) + raise Exception("ovfcheck in %s: Operation %s has no" + " overflow variant" % (graph.name, opname)) - blocks_to_join = False - for block in blocks: - if is_ovfshiftcheck(block): - # ovfcheck_lshift: - # simply rewrite the operation - op = block.operations[-1] - op.opname = "lshift" # augmented later - op.args = op.args[1:] - elif is_single(block): - # remove the call to ovfcheck and keep the exceptions - check_syntax(block) - remove_last_op(block) - seen_ovfblocks[block] = True - elif is_paired(block): - # remove the block's exception links - link = block.exits[0] - ovfblock = link.target - check_syntax(ovfblock, block) - block.recloseblock(link) - block.exitswitch = None - # remove the ovfcheck call from the None target - remove_last_op(ovfblock) - seen_ovfblocks[ovfblock] = True - blocks_to_join = True - else: - continue - op = block.operations[-1] - op.opname = "%s_%s" % (op.opname, appendix) - if blocks_to_join: - join_blocks(graph) + for block in graph.iterblocks(): + for i in range(len(block.operations)-1, -1, -1): + op = block.operations[i] + if op.opname != 'simple_call': + continue + if op.args[0] == covf: + if i == 0: + # hard case: ovfcheck() on an operation that occurs + # in the previous block, like 'floordiv'. The generic + # exception handling around the ovfcheck() is enough + # to cover all cases; kill the one around the previous op. + entrymap = mkentrymap(graph) + links = entrymap[block] + assert len(links) == 1 + prevblock = links[0].prevblock + assert prevblock.exits[0].target is block + prevblock.exitswitch = None + prevblock.exits = (links[0],) + join_blocks(graph) # merge the two blocks together + transform_ovfcheck(graph) # ...and try again + return + op1 = block.operations[i-1] + check_syntax(op1.opname) + op1.opname += '_ovf' + del block.operations[i] + block.renamevariables({op.result: op1.result}) + elif op.args[0] == covfls: + op.opname = 'lshift_ovf' + del op.args[0] def simplify_exceptions(graph): """The exception handling caused by non-implicit exceptions Modified: pypy/branch/pyjitpl5/pypy/translator/test/test_simplify.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/test/test_simplify.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/test/test_simplify.py Thu Mar 12 18:40:17 2009 @@ -15,6 +15,82 @@ t.view() return graphof(t, func), t +def test_remove_ovfcheck_1(): + # check that ovfcheck() is handled + from pypy.rlib.rarithmetic import ovfcheck + def f(x): + try: + return ovfcheck(x*2) + except OverflowError: + return -42 + graph, _ = translate(f, [int]) + assert len(graph.startblock.operations) == 1 + assert graph.startblock.operations[0].opname == 'int_mul_ovf' + assert len(graph.startblock.exits) == 2 + assert [link.target.operations for link in graph.startblock.exits] == \ + [(), ()] + +def test_remove_ovfcheck_bug(): + # check that ovfcheck() is correctly handled even if there is no + # try:except: immediately around it + from pypy.rlib.rarithmetic import ovfcheck + def f(x): + return ovfcheck(x*2) - 1 + graph, _ = translate(f, [int]) + assert len(graph.startblock.operations) == 2 + assert graph.startblock.operations[0].opname == 'int_mul_ovf' + assert graph.startblock.operations[1].opname == 'int_sub' + +def test_remove_ovfcheck_lshift(): + # check that ovfcheck_lshift() is handled + from pypy.rlib.rarithmetic import ovfcheck_lshift + def f(x): + try: + return ovfcheck_lshift(x, 2) + except OverflowError: + return -42 + graph, _ = translate(f, [int]) + assert len(graph.startblock.operations) == 1 + assert graph.startblock.operations[0].opname == 'int_lshift_ovf_val' + assert len(graph.startblock.operations[0].args) == 2 + assert len(graph.startblock.exits) == 3 + assert [link.target.operations for link in graph.startblock.exits] == \ + [(), (), ()] + +def test_remove_ovfcheck_floordiv(): + # check that ovfcheck() is handled even if the operation raises + # and catches another exception too, here ZeroDivisionError + from pypy.rlib.rarithmetic import ovfcheck + def f(x, y): + try: + return ovfcheck(x // y) + except OverflowError: + return -42 + except ZeroDivisionError: + return -43 + graph, _ = translate(f, [int, int]) + assert len(graph.startblock.operations) == 1 + assert graph.startblock.operations[0].opname == 'int_floordiv_ovf_zer' + assert len(graph.startblock.exits) == 3 + assert [link.target.operations for link in graph.startblock.exits[1:]] == \ + [(), ()] + +def test_remove_ovfcheck_floordiv_2(): + # check that ovfcheck() is handled even if the operation raises + # and catches only another exception, here ZeroDivisionError + from pypy.rlib.rarithmetic import ovfcheck + def f(x, y): + try: + return ovfcheck(x // y) + except ZeroDivisionError: + return -43 + graph, _ = translate(f, [int, int]) + assert len(graph.startblock.operations) == 1 + assert graph.startblock.operations[0].opname == 'int_floordiv_ovf_zer' + assert len(graph.startblock.exits) == 3 + assert [link.target.operations for link in graph.startblock.exits[1:]] == \ + [(), ()] + def test_remove_direct_call_without_side_effects(): def f(x): return x + 123 From arigo at codespeak.net Thu Mar 12 18:57:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Mar 2009 18:57:30 +0100 (CET) Subject: [pypy-svn] r62899 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312175730.40A0A1684CD@codespeak.net> Author: arigo Date: Thu Mar 12 18:57:30 2009 New Revision: 62899 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Add comment. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 12 18:57:30 2009 @@ -108,6 +108,8 @@ return self.sort_key() def av_list_in(lst, key): + # lst is a list of about 2 elements in the typical case, so no + # point in making a dict lookup for l in lst: if key.sort_key() == l.sort_key(): return True From fijal at codespeak.net Thu Mar 12 19:01:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 19:01:23 +0100 (CET) Subject: [pypy-svn] r62900 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312180123.DEEDE1684CD@codespeak.net> Author: fijal Date: Thu Mar 12 19:01:23 2009 New Revision: 62900 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: int_mod_ovf and friends Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 12 19:01:23 2009 @@ -219,9 +219,13 @@ getattr(self.mc, asmop)(arglocs[0], arglocs[1]) return genop_binary - def _binaryop_ovf(asmop, can_swap=False): + def _binaryop_ovf(asmop, can_swap=False, is_mod=False): def genop_binary_ovf(self, op, guard_op, arglocs, result_loc): - getattr(self.mc, asmop)(arglocs[0], arglocs[1]) + if is_mod: + self.mc.CDQ() + self.mc.IDIV(ecx) + else: + getattr(self.mc, asmop)(arglocs[0], arglocs[1]) index = self.cpu.make_guard_index(guard_op) recovery_code_addr = self.mc2.tell() stacklocs = guard_op.stacklocs @@ -271,6 +275,8 @@ genop_int_sub = _binaryop("SUB") genop_int_mul = _binaryop("IMUL", True) genop_int_and = _binaryop("AND", True) + genop_int_or = _binaryop("OR", True) + genop_int_xor = _binaryop("XOR", True) genop_uint_add = genop_int_add genop_uint_sub = genop_int_sub @@ -280,6 +286,7 @@ genop_int_mul_ovf = _binaryop_ovf("IMUL", True) genop_int_sub_ovf = _binaryop_ovf("SUB") genop_int_add_ovf = _binaryop_ovf("ADD", True) + genop_int_mod_ovf = _binaryop_ovf("IDIV", is_mod=True) genop_int_lt = _cmpop("L", "G") genop_int_le = _cmpop("LE", "GE") Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 19:01:23 2009 @@ -611,6 +611,8 @@ consider_int_mul = _consider_binop consider_int_sub = _consider_binop consider_int_and = _consider_binop + consider_int_or = _consider_binop + consider_int_xor = _consider_binop consider_uint_add = _consider_binop consider_uint_mul = _consider_binop consider_uint_sub = _consider_binop @@ -653,6 +655,19 @@ self.eventually_free_vars(op.args + [tmpvar]) return ops0 + ops1 + ops2 + ops3 + [Perform(op, [eax, ecx], edx)] + def consider_int_mod_ovf(self, op, guard_op): + l0, ops0 = self.make_sure_var_in_reg(op.args[0], [], eax) + l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) + l2, ops2 = self.force_allocate_reg(op.result, [], edx) + tmpvar = TempBox() + _, ops3 = self.force_allocate_reg(tmpvar, [], eax) + assert (l0, l1, l2) == (eax, ecx, edx) + locs = self._locs_from_liveboxes(guard_op) + self.eventually_free_vars(guard_op.liveboxes) + self.eventually_free_vars(op.args + [tmpvar]) + return (ops0 + ops1 + ops2 + ops3 + + [PerformWithGuard(op, guard_op, [eax, ecx] + locs, edx)]) + def consider_int_floordiv(self, op, ignored): tmpvar = TempBox() l0, ops0 = self.force_result_in_reg(op.result, op.args[0], [], eax) From fijal at codespeak.net Thu Mar 12 19:10:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 19:10:29 +0100 (CET) Subject: [pypy-svn] r62901 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312181029.93A311684A9@codespeak.net> Author: fijal Date: Thu Mar 12 19:10:28 2009 New Revision: 62901 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: a hack for dead code. probably requires proper fix Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 12 19:10:28 2009 @@ -116,6 +116,17 @@ fnptr = self.rtyper.getcallable(graph) cfnptr = history.ConstAddr(llmemory.cast_ptr_to_adr(fnptr), self.cpu) FUNC = lltype.typeOf(fnptr).TO + # + # these functions come from somewhere and are never called. make sure + # we never store a pointer to them since they make C explode, + # need to find out where they come from + for ARG in FUNC.ARGS: + if isinstance(ARG, lltype.Ptr) and ARG.TO == lltype.PyObject: + return () + if (isinstance(FUNC.RESULT, lltype.Ptr) and + FUNC.RESULT.TO == lltype.PyObject): + return () + # NON_VOID_ARGS = [ARG for ARG in FUNC.ARGS if ARG is not lltype.Void] calldescr = self.cpu.calldescrof(NON_VOID_ARGS, FUNC.RESULT) return (cfnptr, calldescr) From fijal at codespeak.net Thu Mar 12 19:42:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 19:42:20 +0100 (CET) Subject: [pypy-svn] r62902 - pypy/branch/pyjitpl5/pypy/objspace/std Message-ID: <20090312184220.D5DA3168481@codespeak.net> Author: fijal Date: Thu Mar 12 19:42:19 2009 New Revision: 62902 Modified: pypy/branch/pyjitpl5/pypy/objspace/std/multimethod.py Log: kill hint in multimethods Modified: pypy/branch/pyjitpl5/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/objspace/std/multimethod.py (original) +++ pypy/branch/pyjitpl5/pypy/objspace/std/multimethod.py Thu Mar 12 19:42:19 2009 @@ -884,9 +884,9 @@ attrname = self.mrdtable.attrname exprfn = "%d" % master_index for n in range(self.multimethod.arity-1): - exprfn = "hint(indexarray.items, deepfreeze=True)[%s + arg%d.%s]" % (exprfn, n, attrname) + exprfn = "indexarray.items[%s + arg%d.%s]" % (exprfn, n, attrname) n = self.multimethod.arity-1 - exprfn = "hint(funcarray.items, deepfreeze=True)[(%s + arg%d.%s) & mmmask]" % (exprfn, n, + exprfn = "funcarray.items[(%s + arg%d.%s) & mmmask]" % (exprfn, n, attrname) expr = Call(exprfn, self.fnargs) entry = self.build_funcentry([self.prefix, '0_perform_call'], @@ -930,8 +930,6 @@ bodylines.append(' pass') bodylines.append('return %s' % expr(calllist[-1])) - from pypy.rlib.jit import hint - miniglobals['hint'] = hint miniglobals['__name__'] = __name__ entry = FuncEntry(bodylines, miniglobals, fallback) key = entry.key() From fijal at codespeak.net Thu Mar 12 19:50:07 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 19:50:07 +0100 (CET) Subject: [pypy-svn] r62903 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312185007.E2D651684AA@codespeak.net> Author: fijal Date: Thu Mar 12 19:50:07 2009 New Revision: 62903 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: *sigh* enable listops here Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Thu Mar 12 19:50:07 2009 @@ -25,6 +25,7 @@ from pypy.jit.backend.detect_cpu import getcpuclass warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=getcpuclass(), translate_support_code=True, + listops=True, **kwds) warmrunnerdesc.finish() From fijal at codespeak.net Thu Mar 12 20:32:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 20:32:03 +0100 (CET) Subject: [pypy-svn] r62904 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090312193203.BF43E16849E@codespeak.net> Author: fijal Date: Thu Mar 12 20:32:01 2009 New Revision: 62904 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: implement an optimization that lets guard ops store the result of comparison in processor flags, if possible Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 12 20:32:01 2009 @@ -262,6 +262,24 @@ getattr(self.mc, 'SET' + cond)(lower_byte(result_loc)) return genop_cmp + def _cmpop_guard(cond, rev_cond, false_cond, false_rev_cond): + def genop_cmp_guard(self, op, guard_op, arglocs, result_loc): + if isinstance(op.args[0], Const): + self.mc.CMP(arglocs[1], arglocs[0]) + if guard_op.opnum == rop.GUARD_FALSE: + name = 'J' + rev_cond + else: + name = 'J' + false_rev_cond + else: + self.mc.CMP(arglocs[0], arglocs[1]) + if guard_op.opnum == rop.GUARD_FALSE: + name = 'J' + cond + else: + name = 'J' + false_cond + self.implement_guard(guard_op, getattr(self.mc, name), arglocs[2:]) + return genop_cmp_guard + + def call(self, addr, args, res): for i in range(len(args)): arg = args[i] @@ -283,10 +301,10 @@ genop_uint_mul = genop_int_mul xxx_genop_uint_and = genop_int_and - genop_int_mul_ovf = _binaryop_ovf("IMUL", True) - genop_int_sub_ovf = _binaryop_ovf("SUB") - genop_int_add_ovf = _binaryop_ovf("ADD", True) - genop_int_mod_ovf = _binaryop_ovf("IDIV", is_mod=True) + genop_guard_int_mul_ovf = _binaryop_ovf("IMUL", True) + genop_guard_int_sub_ovf = _binaryop_ovf("SUB") + genop_guard_int_add_ovf = _binaryop_ovf("ADD", True) + genop_guard_int_mod_ovf = _binaryop_ovf("IDIV", is_mod=True) genop_int_lt = _cmpop("L", "G") genop_int_le = _cmpop("LE", "GE") @@ -300,6 +318,18 @@ genop_uint_le = _cmpop("BE", "AE") genop_uint_ge = _cmpop("AE", "BE") + genop_guard_int_lt = _cmpop_guard("L", "G", "GE", "LE") + genop_guard_int_le = _cmpop_guard("LE", "GE", "G", "L") + genop_guard_int_eq = _cmpop_guard("E", "NE", "NE", "E") + genop_guard_int_ne = _cmpop_guard("NE", "E", "E", "NE") + genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE") + genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G") + + genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE") + genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE") + genop_guard_uint_le = _cmpop_guard("BE", "AE", "A", "B") + genop_guard_uint_ge = _cmpop_guard("AE", "BE", "B", "A") + # for now all chars are being considered ints, although we should make # a difference at some point xxx_genop_char_eq = genop_int_eq @@ -391,7 +421,7 @@ genop_getfield_raw = genop_getfield_gc genop_getarrayitem_gc_pure = genop_getarrayitem_gc - def genop_setfield_gc(self, op, arglocs): + def genop_discard_setfield_gc(self, op, arglocs): base_loc, ofs_loc, size_loc, value_loc = arglocs assert isinstance(size_loc, IMM32) size = size_loc.value @@ -405,7 +435,7 @@ else: raise NotImplementedError("Addr size %d" % size) - def genop_setarrayitem_gc(self, op, arglocs): + def genop_discard_setarrayitem_gc(self, op, arglocs): base_loc, ofs_loc, value_loc, scale_loc, baseofs = arglocs assert isinstance(baseofs, IMM32) assert isinstance(scale_loc, IMM32) @@ -418,14 +448,14 @@ else: raise NotImplementedError("scale = %d" % scale_loc.value) - def genop_strsetitem(self, op, arglocs): + def genop_discard_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, self.cpu.translate_support_code) self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize), lower_byte(val_loc)) - genop_setfield_raw = genop_setfield_gc + genop_discard_setfield_raw = genop_discard_setfield_gc def genop_strlen(self, op, arglocs, resloc): base_loc = arglocs[0] @@ -443,13 +473,13 @@ self.cpu.translate_support_code) self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize)) - def genop_merge_point(self, op, locs): + def genop_discard_merge_point(self, op, locs): op.position = self.mc.tell() op.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(op) - genop_catch = genop_merge_point + genop_discard_catch = genop_discard_merge_point - def genop_return(self, op, locs): + def genop_discard_return(self, op, locs): if op.args: loc = locs[0] if loc is not eax: @@ -467,16 +497,16 @@ self.mc.MOV(heap(self._exception_addr), imm(0)) self.mc.RET() - def genop_jump(self, op, locs): + def genop_discard_jump(self, op, locs): targetmp = op.jump_target self.mc.JMP(rel32(targetmp.position)) - def genop_guard_true(self, op, locs): + def genop_discard_guard_true(self, op, locs): loc = locs[0] self.mc.TEST(loc, loc) self.implement_guard(op, self.mc.JZ, locs[1:]) - def genop_guard_no_exception(self, op, locs): + def genop_discard_guard_no_exception(self, op, locs): loc = locs[0] self.mc.MOV(loc, heap(self._exception_addr)) self.mc.TEST(loc, loc) @@ -492,23 +522,23 @@ self.mc.MOV(resloc, addr_add(imm(self._exception_addr), imm(WORD))) self.mc.MOV(heap(self._exception_addr), imm(0)) - def genop_guard_false(self, op, locs): + def genop_discard_guard_false(self, op, locs): loc = locs[0] self.mc.TEST(loc, loc) self.implement_guard(op, self.mc.JNZ, locs[1:]) - def genop_guard_value(self, op, locs): + def genop_discard_guard_value(self, op, locs): arg0 = locs[0] arg1 = locs[1] self.mc.CMP(arg0, arg1) self.implement_guard(op, self.mc.JNE, locs[2:]) - def genop_guard_class(self, op, locs): + def genop_discard_guard_class(self, op, locs): offset = 0 # XXX for now, the vtable ptr is at the start of the obj self.mc.CMP(mem(locs[0], offset), locs[1]) self.implement_guard(op, self.mc.JNE, locs[2:]) - #def genop_guard_nonvirtualized(self, op): + #def genop_discard_guard_nonvirtualized(self, op): # STRUCT = op.args[0].concretetype.TO # offset, size = symbolic.get_field_token(STRUCT, 'vable_rti') # assert size == WORD @@ -605,18 +635,21 @@ genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST for name, value in Assembler386.__dict__.iteritems(): - if name.startswith('genop_'): - opname = name[len('genop_'):] + if name.startswith('genop_discard_'): + opname = name[len('genop_discard_'):] if opname == 'return': num = RETURN else: num = getattr(rop, opname.upper()) - if value.func_code.co_argcount == 3: - genop_discard_list[num] = value - elif value.func_code.co_argcount == 5: - genop_guard_list[num] = value - else: - genop_list[num] = value + genop_discard_list[num] = value + elif name.startswith('genop_guard_') and name != 'genop_guard_exception': + opname = name[len('genop_guard_'):] + num = getattr(rop, opname.upper()) + genop_guard_list[num] = value + elif name.startswith('genop_'): + opname = name[len('genop_'):] + num = getattr(rop, opname.upper()) + genop_list[num] = value def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0): if isinstance(reg_or_imm1, IMM32): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 20:32:01 2009 @@ -206,6 +206,16 @@ self.longevity[v][0] <= self.position): assert not v in self.dirty_stack + def can_optimize_cmp_op(self, op, i, operations): + if not op.is_comparison(): + return False + if (operations[i + 1].opnum != rop.GUARD_TRUE and + operations[i + 1].opnum != rop.GUARD_FALSE): + return False + if self.longevity[op.result][1] > i + 1: + return False + return True + def walk_operations(self, operations, loop_consts): # first pass - walk along the operations in order to find # load/store places @@ -225,10 +235,15 @@ assert operations[i + 1].opnum == rop.GUARD_NO_EXCEPTION new_ops += oplist[op.opnum](self, op, operations[i + 1]) i += 1 + elif self.can_optimize_cmp_op(op, i, operations): + new_ops += oplist[op.opnum](self, op, operations[i + 1]) + i += 1 else: new_ops += oplist[op.opnum](self, op, None) self.eventually_free_var(op.result) self._check_invariants() + else: + self.eventually_free_vars(op.args) i += 1 return new_ops @@ -621,6 +636,7 @@ def _consider_binop_ovf(self, op, guard_op): loc, argloc, ops = self._consider_binop_part(op, None) locs = self._locs_from_liveboxes(guard_op) + self.position += 1 self.eventually_free_vars(guard_op.liveboxes) return ops + [PerformWithGuard(op, guard_op, [loc, argloc] + locs, loc)] @@ -663,8 +679,9 @@ _, ops3 = self.force_allocate_reg(tmpvar, [], eax) assert (l0, l1, l2) == (eax, ecx, edx) locs = self._locs_from_liveboxes(guard_op) - self.eventually_free_vars(guard_op.liveboxes) self.eventually_free_vars(op.args + [tmpvar]) + self.position += 1 + self.eventually_free_vars(guard_op.liveboxes) return (ops0 + ops1 + ops2 + ops3 + [PerformWithGuard(op, guard_op, [eax, ecx] + locs, edx)]) @@ -678,7 +695,7 @@ self.eventually_free_vars(op.args + [tmpvar]) return ops0 + ops1 + ops2 + [Perform(op, [eax, ecx], eax)] - def _consider_compop(self, op, ignored): + def _consider_compop(self, op, guard_op): vx = op.args[0] vy = op.args[1] arglocs = [self.loc(vx), self.loc(vy)] @@ -689,8 +706,15 @@ arglocs[0], ops0 = self.force_allocate_reg(vx, []) self.eventually_free_var(vx) self.eventually_free_var(vy) - loc, ops = self.force_allocate_reg(op.result, op.args) - return ops0 + ops + [Perform(op, arglocs, loc)] + if guard_op is None: + loc, ops = self.force_allocate_reg(op.result, op.args) + return ops0 + ops + [Perform(op, arglocs, loc)] + else: + locs = self._locs_from_liveboxes(guard_op) + self.position += 1 + self.eventually_free_var(op.result) + self.eventually_free_vars(guard_op.liveboxes) + return ops0 + [PerformWithGuard(op, guard_op, arglocs + locs, None)] consider_int_lt = _consider_compop consider_int_gt = _consider_compop Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 12 20:32:01 2009 @@ -8,6 +8,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.backend.x86.test.test_runner import FakeMetaInterp, FakeStats from pypy.jit.metainterp.resoperation import rop +from pypy.jit.backend.x86.regalloc import RETURN def test_simple_loop(): meta_interp = FakeMetaInterp() @@ -127,7 +128,6 @@ assert meta_interp.recordedvalues == [0, 1, 3, 2, 0] def test_bool_optimizations(): - py.test.skip("Not yet") meta_interp = FakeMetaInterp() cpu = CPU(rtyper=None, stats=FakeStats()) cpu.set_meta_interp(meta_interp) @@ -143,9 +143,35 @@ ops[2].liveboxes = [res] cpu.compile_operations(ops) - res = cpu.execute_operations_in_new_frame('foo', ops[0], - [arg0, arg1], 'int') + res = cpu.execute_operations_in_new_frame('foo', ops, + [arg0, arg1]) assert len(cpu.assembler._regalloc.computed_ops) == 2 assert meta_interp.gf # er, what to check here, assembler??? + +def test_bool_cannot_optimize(): + meta_interp = FakeMetaInterp() + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.set_meta_interp(meta_interp) + arg0 = BoxInt(3) + arg1 = BoxInt(4) + res = BoxInt(0) + r = BoxInt(1) + ops = [ + ResOperation(rop.MERGE_POINT, [arg0, arg1], None), + ResOperation(rop.INT_GT, [arg0, arg1], res), + ResOperation(rop.GUARD_TRUE, [res], None), + # we should never get here + ResOperation(rop.INT_ADD, [res, ConstInt(0)], r), + ResOperation(RETURN, [r], None), + ] + ops[2].liveboxes = [res] + + cpu.compile_operations(ops) + res = cpu.execute_operations_in_new_frame('foo', ops, + [arg0, arg1]) + + assert len(cpu.assembler._regalloc.computed_ops) == 5 + assert meta_interp.gf + # er, what to check here, assembler??? From fijal at codespeak.net Thu Mar 12 20:40:55 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 20:40:55 +0100 (CET) Subject: [pypy-svn] r62905 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090312194055.8B7941684AA@codespeak.net> Author: fijal Date: Thu Mar 12 20:40:54 2009 New Revision: 62905 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: oops, forgotten checkin Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 12 20:40:54 2009 @@ -76,6 +76,9 @@ def is_ovf(self): return rop._OVF_FIRST <= self.opnum <= rop._OVF_LAST + def is_comparison(self): + return rop._COMPARISON_FIRST <= self.opnum <= rop._COMPARISON_LAST + # ____________________________________________________________ From fijal at codespeak.net Thu Mar 12 20:41:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 20:41:10 +0100 (CET) Subject: [pypy-svn] r62906 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090312194110.2E0E31684B9@codespeak.net> Author: fijal Date: Thu Mar 12 20:41:08 2009 New Revision: 62906 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: a bit of fixes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 12 20:41:08 2009 @@ -268,15 +268,21 @@ self.mc.CMP(arglocs[1], arglocs[0]) if guard_op.opnum == rop.GUARD_FALSE: name = 'J' + rev_cond + self.implement_guard(guard_op, getattr(self.mc, name), + arglocs[2:]) else: name = 'J' + false_rev_cond + self.implement_guard(guard_op, getattr(self.mc, name), + arglocs[2:]) else: self.mc.CMP(arglocs[0], arglocs[1]) if guard_op.opnum == rop.GUARD_FALSE: - name = 'J' + cond + self.implement_guard(guard_op, getattr(self.mc, 'J' + cond), + arglocs[2:]) else: name = 'J' + false_cond - self.implement_guard(guard_op, getattr(self.mc, name), arglocs[2:]) + self.implement_guard(guard_op, getattr(self.mc, name), + arglocs[2:]) return genop_cmp_guard Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 20:41:08 2009 @@ -212,6 +212,8 @@ if (operations[i + 1].opnum != rop.GUARD_TRUE and operations[i + 1].opnum != rop.GUARD_FALSE): return False + if operations[i + 1].args[0] is not op.result: + return False if self.longevity[op.result][1] > i + 1: return False return True Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 12 20:41:08 2009 @@ -117,15 +117,15 @@ ResOperation(rop.JUMP, [x, z, y, i0], None), ] operations[-1].jump_target = operations[0] - operations[3].liveboxes = [v0, x, y, z, i0] + operations[3].liveboxes = [x, y, z, i0] cpu.compile_operations(operations) res = cpu.execute_operations_in_new_frame('foo', operations, [BoxInt(1), BoxInt(2), BoxInt(3), BoxInt(10)]) - assert res.value == 0 - assert meta_interp.recordedvalues == [0, 1, 3, 2, 0] + assert res.value == 1 + assert meta_interp.recordedvalues == [1, 3, 2, 0] def test_bool_optimizations(): meta_interp = FakeMetaInterp() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Thu Mar 12 20:41:08 2009 @@ -144,13 +144,13 @@ ] startmp = operations[0] operations[-1].jump_target = startmp - operations[-2].liveboxes = [t, u, z] + operations[-2].liveboxes = [t, z] cpu.compile_operations(operations) res = self.cpu.execute_operations_in_new_frame('foo', operations, [BoxInt(0), BoxInt(10)]) assert res.value == 0 gf = cpu.metainterp.gf - assert cpu.metainterp.recordedvalues == [0, True, 55] + assert cpu.metainterp.recordedvalues == [0, 55] assert gf.guard_op is operations[-2] def test_passing_guards(self): From fijal at codespeak.net Thu Mar 12 21:17:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 21:17:54 +0100 (CET) Subject: [pypy-svn] r62907 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090312201754.B0F521684BD@codespeak.net> Author: fijal Date: Thu Mar 12 21:17:51 2009 New Revision: 62907 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: cool, an exploding test Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 12 21:17:51 2009 @@ -3,12 +3,14 @@ """ import py -from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt +from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ + BoxPtr, ConstPtr from pypy.jit.backend.x86.runner import CPU, GuardFailed from pypy.rpython.lltypesystem import lltype from pypy.jit.backend.x86.test.test_runner import FakeMetaInterp, FakeStats from pypy.jit.metainterp.resoperation import rop from pypy.jit.backend.x86.regalloc import RETURN +from pypy.rpython.lltypesystem import lltype, llmemory def test_simple_loop(): meta_interp = FakeMetaInterp() @@ -175,3 +177,111 @@ assert len(cpu.assembler._regalloc.computed_ops) == 5 assert meta_interp.gf # er, what to check here, assembler??? + +def test_bug_1(): + meta_interp = FakeMetaInterp() + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.set_meta_interp(meta_interp) + TP = lltype.GcStruct('x', ('y', lltype.Ptr(lltype.GcStruct('y')))) + + p0 = BoxPtr() + p1 = BoxPtr() + i2 = BoxInt(1000) + i3 = BoxInt(0) + i4 = BoxInt(1) + i5 = BoxInt(3) + p6 = BoxPtr() + p7 = BoxPtr() + i8 = BoxInt(3) + i9 = BoxInt(3) + i10 = BoxInt(1) + i11 = BoxInt(37) + p12 = BoxPtr() + p13 = BoxPtr() + i14 = BoxInt() + i15 = BoxInt() + i16 = BoxInt() + i17 = BoxInt() + i18 = BoxInt() + i19 = BoxInt() + i20 = BoxInt() + i21 = BoxInt() + p22 = BoxPtr() + i23 = BoxInt() + none_ptr = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, + lltype.nullptr(TP))) + const_code = none_ptr + const_ptr = none_ptr + stuff = lltype.malloc(TP) + stuff_2 = lltype.malloc(TP.y.TO) + stuff.y = stuff_2 + p12 = const_code.clonebox() + const_name = none_ptr + ops = [ + ResOperation(rop.MERGE_POINT, [p0, p1, i2, i3, i4, i5, p6, p7, i8, + i9, i10, i11, p12, p13], None), + ResOperation(rop.GUARD_VALUE, [i10, ConstInt(1)], None), + ResOperation(rop.OOISNULL, [p1], i14), + ResOperation(rop.GUARD_TRUE, [i14], None), + ResOperation(rop.INT_LT, [i5, ConstInt(0)], i15), + ResOperation(rop.GUARD_FALSE, [i15], None), + ResOperation(rop.INT_GE, [i5, i2], i16), + ResOperation(rop.GUARD_FALSE, [i16], None), + ResOperation(rop.INT_LT, [i5, ConstInt(0)], i17), + ResOperation(rop.GUARD_FALSE, [i17], None), + ResOperation(rop.INT_MUL, [i5, i4], i18), + ResOperation(rop.INT_ADD, [i3, i18], i19), + ResOperation(rop.INT_ADD, [i5, ConstInt(1)], i20), + ResOperation(rop.INT_ADD_OVF, [i8, i19], i21), + ResOperation(rop.GUARD_NO_EXCEPTION, [], None), + ResOperation(rop.GETFIELD_GC, [const_ptr], p22), + ResOperation(rop.OOISNULL, [p22], i23), + ResOperation(rop.GUARD_FALSE, [i23], None), + ResOperation(rop.GUARD_VALUE, [p12, const_code], None), + ResOperation(rop.JUMP, [p0, p1, i2, i3, i4, i20, none_ptr, none_ptr, + i21, i19, ConstInt(1), ConstInt(37), p12, p22], + None) + ] + ops[-5].descr = cpu.fielddescrof(TP, 'y') + ops[1].liveboxes = [ConstInt(21), const_code, p0, i11, i5, i2, i3, i4, p1, + p6, p7, i8, i9, i10, p12, p13, const_name] + ops[3].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, i3, + i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, + const_name, const_name, ConstInt(21), + const_name, ConstInt(24), ConstInt(16), ConstInt(16), + ConstInt(24), ConstInt(346), ConstInt(0)] + ops[5].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, i3, + i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, + const_name, const_name, ConstInt(21), const_name, + ConstInt(24), ConstInt(16), ConstInt(16), + ConstInt(24), ConstInt(346), ConstInt(1)] + ops[7].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, + i3, i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, + const_name, const_name, ConstInt(21), const_name, + ConstInt(24), ConstInt(16), ConstInt(16), + ConstInt(24), ConstInt(346), ConstInt(1)] + ops[9].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, + i3, i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, + const_name, const_name, ConstInt(21), const_name, + ConstInt(24), ConstInt(16), ConstInt(16), + ConstInt(24), ConstInt(346), ConstInt(1)] + ops[14].liveboxes = [ConstInt(33), const_code, p0, ConstInt(33), i20, + i2, i3, i4, p1, none_ptr, none_ptr, i8, i19, + ConstInt(1), p12, p13, const_name, const_name, + ConstInt(33), const_name, ConstInt(34), + ConstInt(0), ConstInt(347), i21] + ops[17].liveboxes = [ConstInt(37), const_code, p0, ConstInt(37), i20, i2, + i3, i4, p1, none_ptr, none_ptr, i21, i19, + ConstInt(1), p12, p13, const_name, const_name, + ConstInt(37), const_name, ConstInt(40), ConstInt(21), + ConstInt(21), p22, ConstInt(1)] + ops[-2].liveboxes = [ConstInt(37), const_code, p0, ConstInt(37), i20, i2, + i3, i4, p1, none_ptr, none_ptr, i21, i19, + ConstInt(1), p12, p13, const_name, const_name, + ConstInt(37), const_name, ConstInt(40), ConstInt(21), + ConstInt(21), p22] + + ops[-1].jump_target = ops[0] + cpu.compile_operations(ops) + args = p0, p1, i2, i3, i4, i5, p6, p7, i8, i9, i10, i11, p12, p31 + res = cpu.execute_operations_in_new_frame('foo', ops, args) From fijal at codespeak.net Thu Mar 12 21:38:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 21:38:33 +0100 (CET) Subject: [pypy-svn] r62908 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090312203833.93A5116842E@codespeak.net> Author: fijal Date: Thu Mar 12 21:38:31 2009 New Revision: 62908 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: a partial fix. test segfault so far Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 21:38:31 2009 @@ -950,6 +950,8 @@ ops = [] laterops = [] middle_ops = [] + reloaded = [] + middle_busy_regs = [] for i in range(len(op.args)): arg = op.args[i] mp = op.jump_target @@ -961,7 +963,7 @@ if not isinstance(res, REG): ops.append(Store(arg, self.loc(arg), self.stack_bindings[arg])) elif res is self.reg_bindings[arg]: - pass + middle_busy_regs.append(res) else: # register, but wrong # we're going to need it (otherwise it'll be dead), so @@ -985,10 +987,32 @@ if isinstance(res, REG): laterops.append(Load(arg, self.loc(arg), res)) else: - if not we_are_translated(): - assert repr(res) == repr(self.loc(arg)) + if self.loc(arg).position != res.position: + reloaded.append((arg, self.loc(arg), res)) elif isinstance(arg, Const): laterops.append(Load(arg, self.loc(arg), res)) + if reloaded: + self.eventually_free_vars(op.args) + middleops = [] + # XXX performance + free_reg = None + last_middle_op = None + for reg in REGS: + if reg not in middle_busy_regs: + free_reg = reg + break + if free_reg is None: + # a very rare case + v = self.reg_bindings.keys()[0] + free_reg = self.reg_bindings[v] + ops.append(Store(v, self.loc(v), self.stack_loc(v))) + last_middle_op = Load(v, self.stack_loc(v), self.loc(v)) + for v, from_l, to_l in reloaded: + middleops.append(Load(v, from_l, free_reg)) + middleops.append(Store(v, free_reg, to_l)) + if last_middle_op is not None: + middleops.append(last_middle_op) + return ops + middleops + laterops + [PerformDiscard(op, [])] self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 12 21:38:31 2009 @@ -183,6 +183,8 @@ cpu = CPU(rtyper=None, stats=FakeStats()) cpu.set_meta_interp(meta_interp) TP = lltype.GcStruct('x', ('y', lltype.Ptr(lltype.GcStruct('y')))) + cpu.assembler._ovf_error_vtable = llmemory.cast_ptr_to_adr(lltype.nullptr(TP)) + cpu.assembler._ovf_error_inst = cpu.assembler._ovf_error_vtable p0 = BoxPtr() p1 = BoxPtr() @@ -283,5 +285,5 @@ ops[-1].jump_target = ops[0] cpu.compile_operations(ops) - args = p0, p1, i2, i3, i4, i5, p6, p7, i8, i9, i10, i11, p12, p31 + args = [p0, p1, i2, i3, i4, i5, p6, p7, i8, i9, i10, i11, p12, p13] res = cpu.execute_operations_in_new_frame('foo', ops, args) From fijal at codespeak.net Thu Mar 12 21:54:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 21:54:19 +0100 (CET) Subject: [pypy-svn] r62909 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090312205419.74D92168054@codespeak.net> Author: fijal Date: Thu Mar 12 21:54:16 2009 New Revision: 62909 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: fix tests. now it passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 12 21:54:16 2009 @@ -213,10 +213,11 @@ none_ptr = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(TP))) const_code = none_ptr - const_ptr = none_ptr stuff = lltype.malloc(TP) stuff_2 = lltype.malloc(TP.y.TO) stuff.y = stuff_2 + const_ptr = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, + stuff)) p12 = const_code.clonebox() const_name = none_ptr ops = [ Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Thu Mar 12 21:54:16 2009 @@ -18,9 +18,13 @@ def handle_guard_failure(self, gf): assert isinstance(gf, GuardFailed) self.gf = gf - self.recordedvalues = [ - gf.cpu.getvaluebox(gf.frame, gf.guard_op, i).value - for i in range(len(gf.guard_op.liveboxes))] + j = 0 + self.recordedvalues = [] + for box in guard_op.liveboxes: + if isinstance(box, Box): + value = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j).value + self.recordedvalues.append(value) + j += 1 if len(gf.guard_op.liveboxes) > 0: gf.make_ready_for_return(gf.cpu.getvaluebox(gf.frame, gf.guard_op, 0)) else: From fijal at codespeak.net Thu Mar 12 21:58:24 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 21:58:24 +0100 (CET) Subject: [pypy-svn] r62910 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090312205824.0CDBA1684A9@codespeak.net> Author: fijal Date: Thu Mar 12 21:58:24 2009 New Revision: 62910 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: a typo in test + fix translation Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 21:58:24 2009 @@ -987,7 +987,10 @@ if isinstance(res, REG): laterops.append(Load(arg, self.loc(arg), res)) else: - if self.loc(arg).position != res.position: + arg0 = self.loc(arg) + assert isinstance(arg0, MODRM) + assert isinstance(res, MODRM) + if arg0.position != res.position: reloaded.append((arg, self.loc(arg), res)) elif isinstance(arg, Const): laterops.append(Load(arg, self.loc(arg), res)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Thu Mar 12 21:58:24 2009 @@ -20,7 +20,7 @@ self.gf = gf j = 0 self.recordedvalues = [] - for box in guard_op.liveboxes: + for box in gf.guard_op.liveboxes: if isinstance(box, Box): value = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j).value self.recordedvalues.append(value) From fijal at codespeak.net Thu Mar 12 22:54:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Mar 2009 22:54:03 +0100 (CET) Subject: [pypy-svn] r62911 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312215403.D165916847C@codespeak.net> Author: fijal Date: Thu Mar 12 22:54:00 2009 New Revision: 62911 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: apparently, imm is fine for comparison. Also fix what happens if return_constant receives imm_fine=True, but selected_reg=None Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 22:54:00 2009 @@ -319,18 +319,19 @@ loc = self.free_regs.pop() return loc, [Load(v, convert_to_imm(v), loc)] v_to_spill = self.pick_variable_to_spill(v, forbidden_vars, selected_reg) + loc = self.loc(v_to_spill) if v_to_spill not in self.stack_bindings or v_to_spill in self.dirty_stack: newloc = self.stack_loc(v_to_spill) try: del self.dirty_stack[v_to_spill] except KeyError: pass - ops = [Store(v_to_spill, selected_reg, newloc)] + ops = [Store(v_to_spill, loc, newloc)] else: ops = [] del self.reg_bindings[v_to_spill] self.free_regs.append(selected_reg) - return selected_reg, ops+[Load(v, convert_to_imm(v), selected_reg)] + return selected_reg, ops+[Load(v, convert_to_imm(v), loc)] return convert_to_imm(v), [] def force_allocate_reg(self, v, forbidden_vars, selected_reg=None): @@ -490,7 +491,7 @@ for i in range(len(op.args)): arg = op.args[i] assert not isinstance(arg, Const) - reg = None + reg = None loc = stack_pos(i) self.stack_bindings[arg] = loc if arg not in self.loop_consts: @@ -583,7 +584,7 @@ def consider_guard_value(self, op, ignored): x = self.loc(op.args[0]) if not (isinstance(x, REG) or isinstance(op.args[1], Const)): - x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) + x, ops = self.make_sure_var_in_reg(op.args[0], []) else: ops = [] y = self.loc(op.args[1]) From fijal at codespeak.net Fri Mar 13 00:12:25 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 00:12:25 +0100 (CET) Subject: [pypy-svn] r62913 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090312231225.597A2168499@codespeak.net> Author: fijal Date: Fri Mar 13 00:12:24 2009 New Revision: 62913 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: oops, this is failed to implement Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 13 00:12:24 2009 @@ -393,7 +393,7 @@ prev_loc = self.loc(v) loc, ops = self.force_allocate_reg(v, forbidden_vars, selected_reg) if prev_loc is loc: - return loc, [] + return loc, ops return loc, ops + [Load(v, prev_loc, loc)] def reallocate_from_to(self, from_v, to_v): @@ -584,7 +584,7 @@ def consider_guard_value(self, op, ignored): x = self.loc(op.args[0]) if not (isinstance(x, REG) or isinstance(op.args[1], Const)): - x, ops = self.make_sure_var_in_reg(op.args[0], []) + x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) else: ops = [] y = self.loc(op.args[1]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Mar 13 00:12:24 2009 @@ -288,3 +288,4 @@ cpu.compile_operations(ops) args = [p0, p1, i2, i3, i4, i5, p6, p7, i8, i9, i10, i11, p12, p13] res = cpu.execute_operations_in_new_frame('foo', ops, args) + assert meta_interp.recordedvalues[1:3] == [1000, 1000] From afa at codespeak.net Fri Mar 13 00:16:59 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Mar 2009 00:16:59 +0100 (CET) Subject: [pypy-svn] r62914 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090312231659.EB1D01684AA@codespeak.net> Author: afa Date: Fri Mar 13 00:16:56 2009 New Revision: 62914 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Log: Now that py.test use plugins, this option is not always defined, specially when running bin/py.py Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Fri Mar 13 00:16:56 2009 @@ -574,7 +574,7 @@ return 0 return res - if conftest.option.usepdb: + if getattr(conftest.option, 'usepdb', False): callback_original = callback def callback(*cargs): try: From fijal at codespeak.net Fri Mar 13 00:17:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 00:17:28 +0100 (CET) Subject: [pypy-svn] r62915 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090312231728.6B5A91684AA@codespeak.net> Author: fijal Date: Fri Mar 13 00:17:27 2009 New Revision: 62915 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: shuffle test around until it explodes :) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 13 00:17:27 2009 @@ -330,8 +330,8 @@ else: ops = [] del self.reg_bindings[v_to_spill] - self.free_regs.append(selected_reg) - return selected_reg, ops+[Load(v, convert_to_imm(v), loc)] + self.free_regs.append(loc) + return loc, ops+[Load(v, convert_to_imm(v), loc)] return convert_to_imm(v), [] def force_allocate_reg(self, v, forbidden_vars, selected_reg=None): @@ -641,6 +641,7 @@ locs = self._locs_from_liveboxes(guard_op) self.position += 1 self.eventually_free_vars(guard_op.liveboxes) + self.eventually_free_var(guard_op.result) return ops + [PerformWithGuard(op, guard_op, [loc, argloc] + locs, loc)] consider_int_mul_ovf = _consider_binop_ovf Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Mar 13 00:17:27 2009 @@ -223,7 +223,7 @@ ops = [ ResOperation(rop.MERGE_POINT, [p0, p1, i2, i3, i4, i5, p6, p7, i8, i9, i10, i11, p12, p13], None), - ResOperation(rop.GUARD_VALUE, [i10, ConstInt(1)], None), + ResOperation(rop.GUARD_VALUE, [ConstInt(1), i10], None), ResOperation(rop.OOISNULL, [p1], i14), ResOperation(rop.GUARD_TRUE, [i14], None), ResOperation(rop.INT_LT, [i5, ConstInt(0)], i15), From fijal at codespeak.net Fri Mar 13 00:38:59 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 00:38:59 +0100 (CET) Subject: [pypy-svn] r62916 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312233859.1C5761684BC@codespeak.net> Author: fijal Date: Fri Mar 13 00:38:57 2009 New Revision: 62916 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: improve debugging output Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 00:38:57 2009 @@ -1,7 +1,8 @@ import sys import ctypes from pypy.jit.backend.x86 import symbolic -from pypy.jit.metainterp.history import Const, ConstInt, Box +from pypy.jit.metainterp.history import Const, ConstInt, Box, ConstPtr, BoxPtr,\ + BoxInt from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory from pypy.rpython.lltypesystem.rclass import OBJECT from pypy.rpython.lltypesystem.lloperation import llop @@ -19,6 +20,18 @@ # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on the stack +def repr_of_arg(arg): + if isinstance(arg, ConstInt): + return "ci(%d)" % arg.value + elif isinstance(arg, ConstPtr): + return "cp(%d)" % arg.get_() + elif isinstance(arg, BoxInt): + return "bi(%d)" % arg.value + elif isinstance(arg, BoxPtr): + return "bp(%d)" % arg.get_() + else: + raise NotImplementedError + class Assembler386(object): MC_SIZE = 1024*1024 # 1MB, but assumed infinite for now generic_return_addr = 0 @@ -88,10 +101,10 @@ if self.verbose and we_are_translated(): print for op in operations: - args = ",".join([str(arg.get_()) for arg in op.args]) + args = ",".join([repr_of_arg(arg) for arg in op.args]) llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) if op.result is not None: - llop.debug_print(lltype.Void, " => %s" % str(op.result.get_())) + llop.debug_print(lltype.Void, " => %s" % repr_of_arg(op.result)) print for i in range(len(computed_ops)): op = computed_ops[i] From fijal at codespeak.net Fri Mar 13 00:56:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 00:56:09 +0100 (CET) Subject: [pypy-svn] r62917 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090312235609.8E89416848F@codespeak.net> Author: fijal Date: Fri Mar 13 00:56:09 2009 New Revision: 62917 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: add unique identifiers Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 00:56:09 2009 @@ -20,15 +20,20 @@ # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on the stack -def repr_of_arg(arg): +def repr_of_arg(memo, arg): + try: + mv = memo[arg] + except KeyError: + mv = len(memo) + memo[arg] = mv if isinstance(arg, ConstInt): - return "ci(%d)" % arg.value + return "ci(%d,%d)" % (mv, arg.value) elif isinstance(arg, ConstPtr): - return "cp(%d)" % arg.get_() + return "cp(%d,%d)" % (mv, arg.get_()) elif isinstance(arg, BoxInt): - return "bi(%d)" % arg.value + return "bi(%d,%d)" % (mv, arg.value) elif isinstance(arg, BoxPtr): - return "bp(%d)" % arg.get_() + return "bp(%d,%d)" % (mv, arg.get_()) else: raise NotImplementedError @@ -100,11 +105,12 @@ print if self.verbose and we_are_translated(): print + memo = {} for op in operations: - args = ",".join([repr_of_arg(arg) for arg in op.args]) + args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) if op.result is not None: - llop.debug_print(lltype.Void, " => %s" % repr_of_arg(op.result)) + llop.debug_print(lltype.Void, " => %s" % repr_of_arg(memo, op.result)) print for i in range(len(computed_ops)): op = computed_ops[i] From fijal at codespeak.net Fri Mar 13 01:14:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 01:14:03 +0100 (CET) Subject: [pypy-svn] r62918 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313001403.F01DE168064@codespeak.net> Author: fijal Date: Fri Mar 13 01:14:03 2009 New Revision: 62918 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py (contents, props changed) Log: a parser for output + a simple input Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp Fri Mar 13 01:14:03 2009 @@ -0,0 +1,12 @@ +merge_point bp(0,135638976),bi(1,210),bi(2,4),bi(3,1),bi(4,1),bi(5,2),bi(6,6) +guard_value bi(5,2),ci(7,2) +int_le bi(2,4),ci(8,1) + => bi(9,0) +int_is_true bi(9,0) + => bi(10,0) +guard_false bi(10,0) +int_mul bi(1,210),bi(2,4) + => bi(11,840) +int_sub bi(2,4),ci(12,1) + => bi(13,3) +jump bp(0,135638976),bi(11,840),bi(13,3),ci(14,1),ci(8,1),ci(15,2),bi(6,6) Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Fri Mar 13 01:14:03 2009 @@ -0,0 +1,95 @@ +#!/usr/bin/env python +""" A simple parser for debug output from x86 backend. used to derive +new tests from crashes +""" + +import sys, py, re + +class Parser(object): + def __init__(self): + self.boxes = {} + self.box_creations = [] + self.operations = [] + + def parse_name(self, name): + if name == 'bp': + return 'BoxPtr' + elif name == 'bi': + return 'BoxInt' + elif name == 'ci': + return 'ConstInt' + elif name == 'cp': + return 'ConstPtr' + raise NotImplementedError + + def register_box(self, id, name, val): + try: + return self.boxes[id] + except KeyError: + result = name.lower() + '_' + str(id) + self.boxes[id] = result + if name.endswith('Ptr'): + val = 'ptr_%d' % id + self.box_creations.append('%s = %s(%s)' % (result, name, val)) + return result + + def parse_args(self, args): + res = [] + for arg in args: + m = re.match('(\w\w)\((\d+),(\d+)\)', arg) + name = self.parse_name(m.group(1)) + id = int(m.group(2)) + val = int(m.group(3)) + unique_box = self.register_box(id, name, val) + res.append(unique_box) + return res + + def parse(self, fname): + def pairs(lst): + res = [] + for i in range(0, len(lst), 2): + res.append(lst[i] + ',' + lst[i + 1]) + return res + + operations = [] + data = py.path.local(fname).read() + lines = data.split("\n") + i = 0 + while i < len(lines): + line = lines[i] + if line: + opname, args = line.split(' ') + parsed_args = self.parse_args(pairs(args.split(","))) + if i + 1 < len(lines) and lines[i + 1].startswith(' =>'): + i += 1 + box = lines[i][5:] + [res] = self.parse_args([box]) + else: + res = None + self.operations.append((opname, parsed_args, res)) + i += 1 + + def output(self): + for box in self.box_creations: + print box + print "ops = [" + for name, args, res in self.operations: + print " " * 4 + "rop.ResOperation(%s, [%s], %s)" % (name.upper(), ", ".join(args), res) + print "]" + print "ops[-1].jump_target = ops[0]" + +if __name__ == '__main__': + if len(sys.argv) != 2: + print __doc__ + sys.exit(1) + parser = Parser() + parser.parse(sys.argv[1]) + parser.output() + +def test_loopparser(): + parser = Parser() + parser.parse(py.magic.autopath().join('..', 'inp')) + assert len(parser.operations) == 8 + assert parser.operations[1] == ('guard_value', ['boxint_5', 'constint_7'], + None) + assert len(parser.box_creations) == 8 From fijal at codespeak.net Fri Mar 13 01:20:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 01:20:22 +0100 (CET) Subject: [pypy-svn] r62919 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313002022.1D7101684B4@codespeak.net> Author: fijal Date: Fri Mar 13 01:20:19 2009 New Revision: 62919 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Log: minor fixes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Fri Mar 13 01:20:19 2009 @@ -10,6 +10,7 @@ self.boxes = {} self.box_creations = [] self.operations = [] + self.unique_ptrs = {} def parse_name(self, name): if name == 'bp': @@ -22,6 +23,13 @@ return 'ConstPtr' raise NotImplementedError + def _get_unique_ptr(self, val): + try: + return self.unique_ptrs[val] + except KeyError: + self.unique_ptrs[val] = len(self.unique_ptrs) + return len(self.unique_ptrs) - 1 + def register_box(self, id, name, val): try: return self.boxes[id] @@ -29,7 +37,7 @@ result = name.lower() + '_' + str(id) self.boxes[id] = result if name.endswith('Ptr'): - val = 'ptr_%d' % id + val = 'ptr_%d' % self._get_unique_ptr(val) self.box_creations.append('%s = %s(%s)' % (result, name, val)) return result @@ -59,7 +67,10 @@ line = lines[i] if line: opname, args = line.split(' ') - parsed_args = self.parse_args(pairs(args.split(","))) + if args: + parsed_args = self.parse_args(pairs(args.split(","))) + else: + parsed_args = [] if i + 1 < len(lines) and lines[i + 1].startswith(' =>'): i += 1 box = lines[i][5:] @@ -93,3 +104,4 @@ assert parser.operations[1] == ('guard_value', ['boxint_5', 'constint_7'], None) assert len(parser.box_creations) == 8 + From fijal at codespeak.net Fri Mar 13 01:29:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 01:29:17 +0100 (CET) Subject: [pypy-svn] r62920 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090313002917.AA23C1684B4@codespeak.net> Author: fijal Date: Fri Mar 13 01:29:15 2009 New Revision: 62920 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: a hanging test. success! Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Mar 13 01:29:15 2009 @@ -289,3 +289,86 @@ args = [p0, p1, i2, i3, i4, i5, p6, p7, i8, i9, i10, i11, p12, p13] res = cpu.execute_operations_in_new_frame('foo', ops, args) assert meta_interp.recordedvalues[1:3] == [1000, 1000] + +def test_bug_2(): + meta_interp = FakeMetaInterp() + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.set_meta_interp(meta_interp) + TP = lltype.GcStruct('x', ('y', lltype.Ptr(lltype.GcStruct('y')))) + cpu.assembler._ovf_error_vtable = llmemory.cast_ptr_to_adr(lltype.nullptr(TP)) + cpu.assembler._ovf_error_inst = cpu.assembler._ovf_error_vtable + ptr_0 = lltype.malloc(TP) + ptr_0.y = lltype.malloc(TP.y.TO) + ptr_1 = lltype.nullptr(TP) + ptr_2 = lltype.nullptr(TP) + ptr_3 = ptr_0 + ptr_4 = ptr_0 + boxptr_0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_0)) + boxint_1 = BoxInt(780) + boxint_2 = BoxInt(40) + boxint_3 = BoxInt(37) + boxptr_4 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_1)) + boxint_5 = BoxInt(40) + boxint_6 = BoxInt(1000) + boxint_7 = BoxInt(0) + boxint_8 = BoxInt(1) + boxptr_9 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + boxptr_10 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + boxptr_11 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + boxint_12 = BoxInt(1) + boxptr_13 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_3)) + constint_14 = ConstInt(1) + boxint_15 = BoxInt(1) + constint_16 = ConstInt(0) + boxint_17 = BoxInt(0) + boxint_18 = BoxInt(0) + boxint_19 = BoxInt(0) + boxint_20 = BoxInt(40) + boxint_21 = BoxInt(40) + constint_22 = ConstInt(1) + boxint_23 = BoxInt(41) + boxint_24 = BoxInt(820) + constptr_25 = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_4)) + boxptr_26 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_3)) + boxint_27 = BoxInt(0) + constptr_28 = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_1)) + constint_29 = ConstInt(37) + constptr_30 = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + constint_31 = ConstInt(1) + ops = [ + ResOperation(rop.MERGE_POINT, [boxptr_0, boxint_1, boxint_2, boxint_3, boxptr_4, boxint_5, boxint_6, boxint_7, boxint_8, boxptr_9, boxptr_10, boxptr_11, boxint_12, boxptr_13], None), + ResOperation(rop.GUARD_VALUE, [boxint_12, constint_14], None), + ResOperation(rop.OOISNULL, [boxptr_9], boxint_15), + ResOperation(rop.GUARD_TRUE, [boxint_15], None), + ResOperation(rop.INT_LT, [boxint_5, constint_16], boxint_17), + ResOperation(rop.GUARD_FALSE, [boxint_17], None), + ResOperation(rop.INT_GE, [boxint_5, boxint_6], boxint_18), + ResOperation(rop.GUARD_FALSE, [boxint_18], None), + ResOperation(rop.INT_LT, [boxint_5, constint_16], boxint_19), + ResOperation(rop.GUARD_FALSE, [boxint_19], None), + ResOperation(rop.INT_MUL, [boxint_5, boxint_8], boxint_20), + ResOperation(rop.INT_ADD, [boxint_7, boxint_20], boxint_21), + ResOperation(rop.INT_ADD, [boxint_5, constint_22], boxint_23), + ResOperation(rop.INT_ADD_OVF, [boxint_1, boxint_21], boxint_24), + ResOperation(rop.GUARD_NO_EXCEPTION, [], None), + ResOperation(rop.GETFIELD_GC, [constptr_25], boxptr_26), + ResOperation(rop.OOISNULL, [boxptr_26], boxint_27), + ResOperation(rop.GUARD_FALSE, [boxint_27], None), + ResOperation(rop.GUARD_VALUE, [boxptr_4, constptr_28], None), + ResOperation(rop.JUMP, [boxptr_0, boxint_24, boxint_21, constint_29, boxptr_4, boxint_23, boxint_6, boxint_7, boxint_8, boxptr_9, constptr_30, constptr_30, constint_31, boxptr_26], None), + ] + ops[-1].jump_target = ops[0] + ops[-1].jump_target = ops[0] + ops[1].liveboxes = [] + ops[3].liveboxes = [] + ops[5].liveboxes = [] + ops[7].liveboxes = [] + ops[9].liveboxes = [] + ops[-2].liveboxes = [] + ops[-3].liveboxes = [] + ops[-6].liveboxes = [] + ops[-5].descr = cpu.fielddescrof(TP, 'y') + args = [boxptr_0, boxint_1, boxint_2, boxint_3, boxptr_4, boxint_5, boxint_6, boxint_7, boxint_8, boxptr_9, boxptr_10, boxptr_11, boxint_12, boxptr_13] + cpu.compile_operations(ops) + res = cpu.execute_operations_in_new_frame('foo', ops, args) + From fijal at codespeak.net Fri Mar 13 01:29:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 01:29:26 +0100 (CET) Subject: [pypy-svn] r62921 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313002926.E941E168064@codespeak.net> Author: fijal Date: Fri Mar 13 01:29:26 2009 New Revision: 62921 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Log: some minor fixes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Fri Mar 13 01:29:26 2009 @@ -30,6 +30,9 @@ self.unique_ptrs[val] = len(self.unique_ptrs) return len(self.unique_ptrs) - 1 + def get_ptr_val(self, val): + return 'lltype.cast_opaque_ptr(llmemory.GCREF, ptr_%d)' % self._get_unique_ptr(val) + def register_box(self, id, name, val): try: return self.boxes[id] @@ -37,7 +40,7 @@ result = name.lower() + '_' + str(id) self.boxes[id] = result if name.endswith('Ptr'): - val = 'ptr_%d' % self._get_unique_ptr(val) + val = self.get_ptr_val(val) self.box_creations.append('%s = %s(%s)' % (result, name, val)) return result @@ -82,12 +85,13 @@ def output(self): for box in self.box_creations: - print box - print "ops = [" + print " " * 4 + box + print " " * 4 + "ops = [" for name, args, res in self.operations: - print " " * 4 + "rop.ResOperation(%s, [%s], %s)" % (name.upper(), ", ".join(args), res) - print "]" - print "ops[-1].jump_target = ops[0]" + print " " * 8 + "ResOperation(rop.%s, [%s], %s)," % (name.upper(), ", ".join(args), res) + print " " * 4 + "]" + print " " * 4 + "ops[-1].jump_target = ops[0]" + print " " * 4 + "cpu.compile_operations(ops)" if __name__ == '__main__': if len(sys.argv) != 2: From fijal at codespeak.net Fri Mar 13 01:35:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 01:35:00 +0100 (CET) Subject: [pypy-svn] r62922 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313003500.7792D1684BF@codespeak.net> Author: fijal Date: Fri Mar 13 01:35:00 2009 New Revision: 62922 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: a trivial fix after couple hours of fight with tools. progress I suppose Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 13 01:35:00 2009 @@ -486,6 +486,7 @@ def consider_merge_point(self, op, ignored): # XXX we can sort out here by longevity if we need something # more optimal + ops = [PerformDiscard(op, [])] locs = [None] * len(op.args) for i in range(len(op.args)): @@ -707,7 +708,7 @@ isinstance(vx, Const) or isinstance(vy, Const)): ops0 = [] else: - arglocs[0], ops0 = self.force_allocate_reg(vx, []) + arglocs[0], ops0 = self.make_sure_var_in_reg(vx, []) self.eventually_free_var(vx) self.eventually_free_var(vy) if guard_op is None: From fijal at codespeak.net Fri Mar 13 10:16:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 10:16:51 +0100 (CET) Subject: [pypy-svn] r62923 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313091651.98E8016848F@codespeak.net> Author: fijal Date: Fri Mar 13 10:16:48 2009 New Revision: 62923 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: move debugging print a bit earlier Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 10:16:48 2009 @@ -86,6 +86,15 @@ self.make_sure_mc_exists() op0 = operations[0] op0.position = self.mc.tell() + if self.verbose and we_are_translated(): + print + memo = {} + for op in operations: + args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) + llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) + if op.result is not None: + llop.debug_print(lltype.Void, " => %s" % repr_of_arg(memo, op.result)) + print regalloc = RegAlloc(operations, guard_op, self.cpu.translate_support_code) if not we_are_translated(): self._regalloc = regalloc # for debugging @@ -103,15 +112,6 @@ print pprint.pprint(computed_ops) print - if self.verbose and we_are_translated(): - print - memo = {} - for op in operations: - args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) - llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) - if op.result is not None: - llop.debug_print(lltype.Void, " => %s" % repr_of_arg(memo, op.result)) - print for i in range(len(computed_ops)): op = computed_ops[i] if not we_are_translated(): From fijal at codespeak.net Fri Mar 13 10:38:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 10:38:57 +0100 (CET) Subject: [pypy-svn] r62924 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090313093857.8E14D1684AB@codespeak.net> Author: fijal Date: Fri Mar 13 10:38:54 2009 New Revision: 62924 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: a test and a fix Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Mar 13 10:38:54 2009 @@ -422,12 +422,8 @@ def pick_variable_to_spill(self, v, forbidden_vars, selected_reg=None): # XXX could be improved - if v in self.jump_reg_candidates: - assert selected_reg is None # I don't want to care... - # now we need to spill a variable that resides in a place where - # we would like our var to be. - # XXX Needs test - # XXX better storage + if v in self.jump_reg_candidates and (selected_reg is None or + self.jump_reg_candidates[v] is selected_reg): for var, reg in self.reg_bindings.items(): if reg is self.jump_reg_candidates[v] and v not in forbidden_vars: return var Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Mar 13 10:38:54 2009 @@ -372,3 +372,98 @@ cpu.compile_operations(ops) res = cpu.execute_operations_in_new_frame('foo', ops, args) +def test_bug_3(): + meta_interp = FakeMetaInterp() + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.set_meta_interp(meta_interp) + TP = lltype.GcStruct('x', ('y', lltype.Ptr(lltype.GcStruct('y')))) + cpu.assembler._ovf_error_vtable = llmemory.cast_ptr_to_adr(lltype.nullptr(TP)) + cpu.assembler._ovf_error_inst = cpu.assembler._ovf_error_vtable + ptr_0 = lltype.malloc(TP) + ptr_0.y = lltype.malloc(TP.y.TO) + ptr_1 = lltype.nullptr(TP) + ptr_2 = lltype.nullptr(TP) + ptr_3 = ptr_0 + ptr_4 = ptr_0 + boxptr_0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_0)) + boxint_1 = BoxInt(60) + boxint_2 = BoxInt(40) + boxint_3 = BoxInt(57) + boxptr_4 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_1)) + boxint_5 = BoxInt(40) + boxint_6 = BoxInt(100000000) + boxint_7 = BoxInt(0) + boxint_8 = BoxInt(1) + boxptr_9 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + boxptr_10 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + boxptr_11 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + boxint_12 = BoxInt(1) + boxptr_13 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_3)) + constint_14 = ConstInt(1) + boxint_15 = BoxInt(1) + constint_16 = ConstInt(0) + boxint_17 = BoxInt(0) + boxint_18 = BoxInt(0) + boxint_19 = BoxInt(0) + boxint_20 = BoxInt(40) + boxint_21 = BoxInt(40) + constint_22 = ConstInt(1) + boxint_23 = BoxInt(41) + constptr_24 = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_1)) + constint_25 = ConstInt(2) + boxint_26 = BoxInt(0) + boxint_27 = BoxInt(42) + boxint_28 = BoxInt(0) + boxint_29 = BoxInt(0) + boxint_30 = BoxInt(0) + boxint_31 = BoxInt(0) + boxint_32 = BoxInt(0) + boxint_33 = BoxInt(0) + constint_34 = ConstInt(2) + boxint_35 = BoxInt(62) + constptr_36 = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_4)) + boxptr_37 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_3)) + boxint_38 = BoxInt(0) + constint_39 = ConstInt(57) + constptr_40 = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, ptr_2)) + constint_41 = ConstInt(1) + ops = [ + ResOperation(rop.MERGE_POINT, [boxptr_0, boxint_1, boxint_2, boxint_3, boxptr_4, boxint_5, boxint_6, boxint_7, boxint_8, boxptr_9, boxptr_10, boxptr_11, boxint_12, boxptr_13], None), + ResOperation(rop.GUARD_VALUE, [boxint_12, constint_14], None), + ResOperation(rop.OOISNULL, [boxptr_9], boxint_15), + ResOperation(rop.GUARD_TRUE, [boxint_15], None), + ResOperation(rop.INT_LT, [boxint_5, constint_16], boxint_17), + ResOperation(rop.GUARD_FALSE, [boxint_17], None), + ResOperation(rop.INT_GE, [boxint_5, boxint_6], boxint_18), + ResOperation(rop.GUARD_FALSE, [boxint_18], None), + ResOperation(rop.INT_LT, [boxint_5, constint_16], boxint_19), + ResOperation(rop.GUARD_FALSE, [boxint_19], None), + ResOperation(rop.INT_MUL, [boxint_5, boxint_8], boxint_20), + ResOperation(rop.INT_ADD, [boxint_7, boxint_20], boxint_21), + ResOperation(rop.INT_ADD, [boxint_5, constint_22], boxint_23), + ResOperation(rop.GUARD_VALUE, [boxptr_4, constptr_24], None), + ResOperation(rop.INT_MOD_OVF, [boxint_21, constint_25], boxint_26), + ResOperation(rop.GUARD_NO_EXCEPTION, [], None), + ResOperation(rop.INT_XOR, [boxint_21, constint_25], boxint_27), + ResOperation(rop.INT_LE, [boxint_27, constint_16], boxint_28), + ResOperation(rop.INT_NE, [boxint_26, constint_16], boxint_29), + ResOperation(rop.INT_AND, [boxint_28, boxint_29], boxint_30), + ResOperation(rop.INT_MUL, [boxint_30, constint_25], boxint_31), + ResOperation(rop.INT_ADD, [boxint_26, boxint_31], boxint_32), + ResOperation(rop.INT_NE, [boxint_32, constint_16], boxint_33), + ResOperation(rop.GUARD_FALSE, [boxint_33], None), + ResOperation(rop.INT_ADD_OVF, [boxint_1, constint_34], boxint_35), + ResOperation(rop.GUARD_NO_EXCEPTION, [], None), + ResOperation(rop.GETFIELD_GC, [constptr_36], boxptr_37), + ResOperation(rop.OOISNULL, [boxptr_37], boxint_38), + ResOperation(rop.GUARD_FALSE, [boxint_38], None), + ResOperation(rop.JUMP, [boxptr_0, boxint_35, boxint_21, constint_39, boxptr_4, boxint_23, boxint_6, boxint_7, boxint_8, boxptr_9, constptr_40, constptr_40, constint_41, boxptr_37], None), + ] + ops[-1].jump_target = ops[0] + for op in ops: + if op.is_guard(): + op.liveboxes = [] + ops[-4].descr = cpu.fielddescrof(TP, 'y') + cpu.compile_operations(ops) + args = [boxptr_0, boxint_1, boxint_2, boxint_3, boxptr_4, boxint_5, boxint_6, boxint_7, boxint_8, boxptr_9, boxptr_10, boxptr_11, boxint_12, boxptr_13] + res = cpu.execute_operations_in_new_frame('foo', ops, args) From fijal at codespeak.net Fri Mar 13 11:16:13 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 11:16:13 +0100 (CET) Subject: [pypy-svn] r62925 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090313101613.CD9AD1684A8@codespeak.net> Author: fijal Date: Fri Mar 13 11:16:11 2009 New Revision: 62925 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: outdated check Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 13 11:16:11 2009 @@ -831,11 +831,7 @@ for vtable in storage.allocations: if metainterp.cpu.translate_support_code: vtable_addr = metainterp.cpu.cast_int_to_adr(vtable) - try: - size = metainterp.class_sizes[vtable_addr] - except KeyError: - print vtable_addr, vtable, "CRAAAAAAAASH" - raise + size = metainterp.class_sizes[vtable_addr] else: size = metainterp.class_sizes[vtable] vtablebox = ConstInt(vtable) From fijal at codespeak.net Fri Mar 13 11:28:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 11:28:43 +0100 (CET) Subject: [pypy-svn] r62926 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313102843.353261684A8@codespeak.net> Author: fijal Date: Fri Mar 13 11:28:41 2009 New Revision: 62926 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: Print also liveboxes of guards. Will allow better tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 11:28:41 2009 @@ -94,6 +94,10 @@ llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) if op.result is not None: llop.debug_print(lltype.Void, " => %s" % repr_of_arg(memo, op.result)) + if op.is_guard(): + liveboxes_s = ",".join([repr_of_arg(memo, arg) for arg in + op.liveboxes]) + llop.debug_print(lltype.Void, " .. %s" % liveboxes_s) print regalloc = RegAlloc(operations, guard_op, self.cpu.translate_support_code) if not we_are_translated(): From cfbolz at codespeak.net Fri Mar 13 11:37:53 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 13 Mar 2009 11:37:53 +0100 (CET) Subject: [pypy-svn] r62927 - in pypy/trunk/pypy/lang/smalltalk: . test Message-ID: <20090313103753.13743168041@codespeak.net> Author: cfbolz Date: Fri Mar 13 11:37:53 2009 New Revision: 62927 Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py pypy/trunk/pypy/lang/smalltalk/wrapper.py Log: make int getters/setters be consistent with normal wrapper getters and setters. Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/primitives.py (original) +++ pypy/trunk/pypy/lang/smalltalk/primitives.py Fri Mar 13 11:37:53 2009 @@ -301,8 +301,8 @@ def func(interp, x, y): w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2) point = wrapper.PointWrapper(interp.space, w_res) - point.store_x(interp.space, x) - point.store_y(interp.space, y) + point.store_x(x) + point.store_y(y) return w_res Modified: pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py Fri Mar 13 11:37:53 2009 @@ -464,8 +464,8 @@ w_point = interp.s_active_context().top() from pypy.lang.smalltalk.wrapper import PointWrapper point = PointWrapper(interp.space, w_point) - assert point.x(interp.space) == 0 - assert point.y(interp.space) == 1 + assert point.x() == 0 + assert point.y() == 1 def test_longJumpIfTrue(): interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15)) Modified: pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py Fri Mar 13 11:37:53 2009 @@ -115,7 +115,7 @@ def new_semaphore(excess_signals=0): w_semaphore = model.W_PointersObject(None, 3) semaphore = wrapper.SemaphoreWrapper(space, w_semaphore) - semaphore.store_excess_signals(space, excess_signals) + semaphore.store_excess_signals(excess_signals) return semaphore @@ -205,7 +205,7 @@ semaphore = new_semaphore() self.space = space semaphore.signal(self) - assert semaphore.excess_signals(space) == 1 + assert semaphore.excess_signals() == 1 def test_highest_priority(self): py.test.raises(FatalError, wrapper.scheduler(space).highest_priority_process) Modified: pypy/trunk/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/trunk/pypy/lang/smalltalk/wrapper.py Fri Mar 13 11:37:53 2009 @@ -36,13 +36,13 @@ return make_getter(index0), make_setter(index0) def make_int_getter(index0): - def getter(self, space): - return space.unwrap_int(self.read(index0)) + def getter(self): + return self.space.unwrap_int(self.read(index0)) return getter def make_int_setter(index0): - def setter(self, space, new): - return self.write(index0, space.wrap_int(new)) + def setter(self, new): + return self.write(index0, self.space.wrap_int(new)) return setter def make_int_getter_setter(index0): @@ -185,17 +185,17 @@ def signal(self, interp): if self.is_empty_list(): - value = self.excess_signals(interp.space) - self.store_excess_signals(interp.space, value + 1) + value = self.excess_signals() + self.store_excess_signals(value + 1) else: process = self.remove_first_link_of_list() ProcessWrapper(self.space, process).resume(interp) def wait(self, interp): - excess = self.excess_signals(interp.space) + excess = self.excess_signals() w_process = scheduler(interp.space).active_process() if excess > 0: - self.store_excess_signals(interp.space, excess - 1) + self.store_excess_signals(excess - 1) else: self.add_last_link(w_process) ProcessWrapper(self.space, w_process).suspend(interp) From fijal at codespeak.net Fri Mar 13 11:44:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 11:44:21 +0100 (CET) Subject: [pypy-svn] r62928 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090313104421.C32E21684A9@codespeak.net> Author: fijal Date: Fri Mar 13 11:44:21 2009 New Revision: 62928 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: some test functions... Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Fri Mar 13 11:44:21 2009 @@ -6,7 +6,8 @@ while i < 100: i = i + 3 print i - assert i == 102 + s + #assert i == 102 def f1(): print "simple loop with inplace_add" @@ -17,17 +18,15 @@ print i assert i == 102 -def f(): +def f2(): print "range object, but outside the loop" s = 0 for i in range(100): - # XXX implement inplace_add method for ints s = s + i print s - assert s == 4950 -def f(): +def f3(): try: i = 100 while i > 0: @@ -39,4 +38,35 @@ else: raise AssertionError -f() +def f4(): + s = 0 + for i in range(100): + if i % 2: + s += 1 + else: + s += 2 + print s + +def f5(): + t = (1, 2, 3) + i = 0 + while i < 1000: + t = t[1], t[2], t[0] + i += 1 + +def f6(): + print "Arbitrary test function." + n = 5 + i = 0 + x = 1 + while i Author: fijal Date: Fri Mar 13 11:47:51 2009 New Revision: 62929 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: a crashing test Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Fri Mar 13 11:47:51 2009 @@ -370,7 +370,30 @@ res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == f(10) - + + def test_always_virtual_with_origfields(self): + py.test.skip("CRASH") + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + _always_virtual_ = ['l'] + + def __init__(self, l): + self.l = l + + def f(n): + frame = Frame([1,2,3]) + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n) + jitdriver.jit_merge_point(frame=frame, n=n) + n -= frame.l[0] + return frame.l[1] + + res = self.meta_interp(f, [10], listops=True) + assert res == 2 def test_external_read(self): py.test.skip("Fails") From arigo at codespeak.net Fri Mar 13 11:57:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Mar 2009 11:57:30 +0100 (CET) Subject: [pypy-svn] r62930 - pypy/branch/pyjitpl5/pypy/rlib Message-ID: <20090313105730.4AC511684BD@codespeak.net> Author: arigo Date: Fri Mar 13 11:57:29 2009 New Revision: 62930 Modified: pypy/branch/pyjitpl5/pypy/rlib/rarithmetic.py Log: These two are NOT_RPYTHON. Modified: pypy/branch/pyjitpl5/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/rarithmetic.py Fri Mar 13 11:57:29 2009 @@ -95,6 +95,7 @@ del _bits, _itest, _Ltest def ovfcheck(r): + "NOT_RPYTHON" # to be used as ovfcheck(x y) # raise OverflowError if the operation did overflow assert not isinstance(r, r_uint), "unexpected ovf check on unsigned" @@ -111,6 +112,7 @@ return r def ovfcheck_lshift(a, b): + "NOT_RPYTHON" return _local_ovfcheck(int(long(a) << b)) FL_MAXINT = float(LONG_TEST-1) From arigo at codespeak.net Fri Mar 13 13:12:43 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Mar 2009 13:12:43 +0100 (CET) Subject: [pypy-svn] r62931 - in pypy/trunk/pypy/translator/c: . src Message-ID: <20090313121243.72985168481@codespeak.net> Author: arigo Date: Fri Mar 13 13:12:41 2009 New Revision: 62931 Modified: pypy/trunk/pypy/translator/c/funcgen.py pypy/trunk/pypy/translator/c/src/rtyper.h pypy/trunk/pypy/translator/c/src/support.h Log: Port r60900 and r61877 from the oo-jit branch: Fix debug_print of strings, broken now that the RPython strings are no longer zero-terminated. Requires copying the RPython strings into a non-movable, zero-terminated buffer. Modified: pypy/trunk/pypy/translator/c/funcgen.py ============================================================================== --- pypy/trunk/pypy/translator/c/funcgen.py (original) +++ pypy/trunk/pypy/translator/c/funcgen.py Fri Mar 13 13:12:41 2009 @@ -714,7 +714,7 @@ format.append(''.join(arg.value.chars).replace('%', '%%')) else: format.append('%s') - argv.append('RPyString_AsString(%s)' % self.expr(arg)) + argv.append('RPyString_AsCharP(%s)' % self.expr(arg)) continue elif T == Signed: format.append('%d') @@ -734,7 +734,7 @@ else: raise Exception("don't know how to debug_print %r" % (T,)) argv.append(self.expr(arg)) - return "fprintf(stderr, %s%s);" % ( + return "fprintf(stderr, %s%s); RPyString_FreeCache();" % ( c_string_constant(' '.join(format) + '\n\000'), ''.join([', ' + s for s in argv])) @@ -751,7 +751,7 @@ if isinstance(msg, Constant): msg = c_string_constant(''.join(msg.value.chars)) else: - msg = 'RPyString_AsString(%s)' % self.expr(msg) + msg = 'RPyString_AsCharP(%s)' % self.expr(msg) return 'fprintf(stderr, "%%s\\n", %s); abort();' % msg Modified: pypy/trunk/pypy/translator/c/src/rtyper.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/rtyper.h (original) +++ pypy/trunk/pypy/translator/c/src/rtyper.h Fri Mar 13 13:12:41 2009 @@ -5,13 +5,14 @@ #define RPyString_Size(rps) ((rps)->rs_chars.length) -#define RPyString_AsString(rps) ((rps)->rs_chars.items) #define RPyUnicode_Size(rpu) ((rpu)->ru_chars.length) #define RPyUnicode_AsUnicode(rpu) ((rpu)->ru_chars.items) /* prototypes */ +char *RPyString_AsCharP(RPyString *rps); +void RPyString_FreeCache(void); RPyString *RPyString_FromString(char *buf); @@ -19,11 +20,39 @@ #ifndef PYPY_NOT_MAIN_FILE +struct _RPyString_dump_t { + struct _RPyString_dump_t *next; + char data[1]; +} *_RPyString_dump = NULL; + +char *RPyString_AsCharP(RPyString *rps) +{ + long len = RPyString_Size(rps); + struct _RPyString_dump_t *dump = \ + malloc(sizeof(struct _RPyString_dump_t) + len); + if (!dump) + return "(out of memory!)"; + dump->next = _RPyString_dump; + _RPyString_dump = dump; + memcpy(dump->data, rps->rs_chars.items, len); + dump->data[len] = 0; + return dump->data; +} + +void RPyString_FreeCache(void) +{ + while (_RPyString_dump) { + struct _RPyString_dump_t *dump = _RPyString_dump; + _RPyString_dump = dump->next; + free(dump); + } +} + RPyString *RPyString_FromString(char *buf) { int length = strlen(buf); RPyString *rps = RPyString_New(length); - memcpy(RPyString_AsString(rps), buf, length); + memcpy(rps->rs_chars.items, buf, length); return rps; } Modified: pypy/trunk/pypy/translator/c/src/support.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/support.h (original) +++ pypy/trunk/pypy/translator/c/src/support.h Fri Mar 13 13:12:41 2009 @@ -20,15 +20,15 @@ #define FAIL_ZER(msg) FAIL_EXCEPTION(PyExc_ZeroDivisionError, msg) #define CFAIL() RPyConvertExceptionFromCPython() -#define PyString_FromRPyString(rpystr) \ - PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr)) +/* #define PyString_FromRPyString(rpystr) \ */ +/* PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr)) */ -#define PyUnicode_FromRPyUnicode(rpystr) \ - PyUnicode_FromUnicode(RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) +/* #define PyUnicode_FromRPyUnicode(rpystr) \ */ +/* PyUnicode_FromUnicode(RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) */ -#define PyString_ToRPyString(s, rpystr) \ - memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \ - RPyString_Size(rpystr)) +/* #define PyString_ToRPyString(s, rpystr) \ */ +/* memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \ */ +/* RPyString_Size(rpystr)) */ /* Extra checks can be enabled with the RPY_ASSERT or RPY_LL_ASSERT * macros. They differ in the level at which the tests are made. From arigo at codespeak.net Fri Mar 13 13:26:52 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Mar 2009 13:26:52 +0100 (CET) Subject: [pypy-svn] r62932 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313122652.16AFD168481@codespeak.net> Author: arigo Date: Fri Mar 13 13:26:49 2009 New Revision: 62932 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Minor changes, fix repr_of_arg(), and don't raise NotImplementedError in there when seeing new unsupported subclasses of AbstractValue. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 13:26:49 2009 @@ -2,7 +2,7 @@ import ctypes from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.history import Const, ConstInt, Box, ConstPtr, BoxPtr,\ - BoxInt + BoxInt, ConstAddr from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory from pypy.rpython.lltypesystem.rclass import OBJECT from pypy.rpython.lltypesystem.lloperation import llop @@ -34,8 +34,11 @@ return "bi(%d,%d)" % (mv, arg.value) elif isinstance(arg, BoxPtr): return "bp(%d,%d)" % (mv, arg.get_()) + elif isinstance(arg, ConstAddr): + return "ca(%d,%d)" % (mv, arg.get_()) else: - raise NotImplementedError + #raise NotImplementedError + return "?%r" % (arg,) class Assembler386(object): MC_SIZE = 1024*1024 # 1MB, but assumed infinite for now @@ -229,9 +232,6 @@ genop_guard_list[op.op.opnum](self, op.op, op.guard_op, op.arglocs, op.result_loc) - def regalloc_store_to_arg(self, op): - self.mc.MOV(arg_pos(op.pos), op.from_loc) - def _unaryop(asmop): def genop_unary(self, op, arglocs, resloc): getattr(self.mc, asmop)(arglocs[0]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 13 13:26:49 2009 @@ -49,8 +49,8 @@ def __ne__(self, other): return not self == other - def _getrepr_(self): - return repr(self.v) + def __repr__(self): + return '' % (self.v,) class CPU386(object): debug = True From arigo at codespeak.net Fri Mar 13 13:33:16 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Mar 2009 13:33:16 +0100 (CET) Subject: [pypy-svn] r62933 - in pypy/branch/pyjitpl5/pypy: jit/tl module/pypyjit translator/goal Message-ID: <20090313123316.EE9B7168481@codespeak.net> Author: arigo Date: Fri Mar 13 13:33:16 2009 New Revision: 62933 Added: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py - copied unchanged from r62930, pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py pypy/branch/pyjitpl5/pypy/translator/goal/targetpypystandalone.py Log: Rename portal.py to policy.py. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Fri Mar 13 13:33:16 2009 @@ -1,7 +1,7 @@ from pypy.conftest import option from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp import warmspot -from pypy.module.pypyjit.portal import PyPyJitPolicy +from pypy.module.pypyjit.policy import PyPyJitPolicy # Current output: http://paste.pocoo.org/show/106540/ # Modified: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py Fri Mar 13 13:33:16 2009 @@ -67,5 +67,5 @@ def jitpolicy(driver): """Returns the JIT policy to use when translating.""" - from pypy.module.pypyjit.portal import PyPyJitPolicy + from pypy.module.pypyjit.policy import PyPyJitPolicy return PyPyJitPolicy(driver.translator) Modified: pypy/branch/pyjitpl5/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/goal/targetpypystandalone.py Fri Mar 13 13:33:16 2009 @@ -199,7 +199,7 @@ return self.get_entry_point(config) def jitpolicy(self, driver): - from pypy.module.pypyjit.portal import PyPyJitPolicy + from pypy.module.pypyjit.policy import PyPyJitPolicy return PyPyJitPolicy(driver.translator) def get_entry_point(self, config): From afa at codespeak.net Fri Mar 13 14:11:02 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Mar 2009 14:11:02 +0100 (CET) Subject: [pypy-svn] r62934 - in pypy/trunk/pypy: module/pyexpat objspace Message-ID: <20090313131102.E7C5D16845E@codespeak.net> Author: afa Date: Fri Mar 13 14:11:01 2009 New Revision: 62934 Added: pypy/trunk/pypy/module/pyexpat/ (props changed) pypy/trunk/pypy/module/pyexpat/__init__.py (contents, props changed) pypy/trunk/pypy/module/pyexpat/app_pyexpat.py (contents, props changed) pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (contents, props changed) Modified: pypy/trunk/pypy/objspace/descroperation.py Log: interp_level implementation of the pyexpat module. When run with py.py, it passes all tests in test_pyexpat and test_minidom: bin\py.py -S --withmod-pyexpat -m test.test_minidom But don't try to translate it for the moment... Added: pypy/trunk/pypy/module/pyexpat/__init__.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/pyexpat/__init__.py Fri Mar 13 14:11:01 2009 @@ -0,0 +1,16 @@ +import py + +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + appleveldefs = { + 'ExpatError' : 'app_pyexpat.ExpatError', + 'error' : 'app_pyexpat.ExpatError', + } + + interpleveldefs = { + 'ParserCreate': 'interp_pyexpat.ParserCreate', + 'XMLParserType': 'interp_pyexpat.W_XMLParserType', + 'ErrorString': 'interp_pyexpat.ErrorString', + } + Added: pypy/trunk/pypy/module/pyexpat/app_pyexpat.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/pyexpat/app_pyexpat.py Fri Mar 13 14:11:01 2009 @@ -0,0 +1,6 @@ +class ExpatError(Exception): + def __init__(self, msg, code, lineno, colno): + Exception.__init__(self, msg) + self.code = code + self.lineno = lineno + self.colno = colno Added: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Fri Mar 13 14:11:01 2009 @@ -0,0 +1,438 @@ +from pypy.interpreter.baseobjspace import Wrappable +from pypy.interpreter.typedef import TypeDef, GetSetProperty +from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped +from pypy.interpreter.gateway import interp2app +from pypy.interpreter.error import OperationError +from pypy.objspace.descroperation import object_setattr +from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rpython.tool import rffi_platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo + +import sys + +if sys.platform == "win32": + libname = 'libexpat' +else: + libname = 'expat' +eci = ExternalCompilationInfo( + libraries=[libname], + includes=['expat.h'] + ) +eci = rffi_platform.configure_external_library( + libname, eci, + [dict(prefix='expat-', + include_dir='lib', library_dir='win32/bin/release'), + ]) + +class CConfigure: + _compilation_info_ = eci + XML_Content = rffi_platform.Struct('XML_Content',[ + ('numchildren', rffi.INT), + ('children', rffi.VOIDP), + ('name', rffi.CCHARP), + ('type', rffi.INT), + ('quant', rffi.INT), + ]) + XML_FALSE = rffi_platform.ConstantInteger('XML_FALSE') + XML_TRUE = rffi_platform.ConstantInteger('XML_TRUE') +XML_Parser = rffi.VOIDP # an opaque pointer + +for k, v in rffi_platform.configure(CConfigure).items(): + globals()[k] = v + + +def expat_external(*a, **kw): + kw['compilation_info'] = eci + return rffi.llexternal(*a, **kw) + +HANDLERS = dict( + StartElementHandler = [rffi.CCHARP, rffi.CCHARPP], + EndElementHandler = [rffi.CCHARP], + ProcessingInstructionHandler = [rffi.CCHARP, rffi.CCHARP], + CharacterDataHandler = [rffi.CCHARP, rffi.INT], + UnparsedEntityDeclHandler = [rffi.CCHARP] * 5, + NotationDeclHandler = [rffi.CCHARP] * 4, + StartNamespaceDeclHandler = [rffi.CCHARP, rffi.CCHARP], + EndNamespaceDeclHandler = [rffi.CCHARP], + CommentHandler = [rffi.CCHARP], + StartCdataSectionHandler = [], + EndCdataSectionHandler = [], + DefaultHandler = [rffi.CCHARP, rffi.INT], + DefaultHandlerExpand = [rffi.CCHARP, rffi.INT], + NotStandaloneHandler = [], + ExternalEntityRefHandler = [rffi.CCHARP] * 4, + StartDoctypeDeclHandler = [rffi.CCHARP, rffi.CCHARP, rffi.CCHARP, rffi.INT], + EndDoctypeDeclHandler = [], + EntityDeclHandler = [rffi.CCHARP, rffi.INT, rffi.CCHARP, rffi.INT, + rffi.CCHARP, rffi.CCHARP, rffi.CCHARP, rffi.CCHARP], + XmlDeclHandler = [rffi.CCHARP, rffi.CCHARP, rffi.INT], + ElementDeclHandler = [rffi.CCHARP, lltype.Ptr(XML_Content)], + AttlistDeclHandler = [rffi.CCHARP] * 4 + [rffi.INT], + ) +if True: #XML_COMBINED_VERSION >= 19504: + HANDLERS['SkippedEntityHandler'] = [rffi.CCHARP, rffi.INT] + +SETTERS = {} +for name, params in HANDLERS.items(): + c_name = 'XML_Set' + name + if name in ['UnknownEncodingHandler', + 'ExternalEntityRefHandler', + 'NotStandaloneHandler']: + RESULT_TYPE = rffi.INT + else: + RESULT_TYPE = lltype.Void + CALLBACK = lltype.Ptr(lltype.FuncType( + [rffi.VOIDP] + params, RESULT_TYPE)) + func = expat_external(c_name, + [XML_Parser, CALLBACK], rffi.INT) + SETTERS[name] = func + +XML_ParserCreate = expat_external( + 'XML_ParserCreate', [rffi.CCHARP], XML_Parser) +XML_ParserCreateNS = expat_external( + 'XML_ParserCreateNS', [rffi.CCHARP, rffi.CHAR], XML_Parser) +XML_Parse = expat_external( + 'XML_Parse', [XML_Parser, rffi.CCHARP, rffi.INT, rffi.INT], rffi.INT) +XML_StopParser = expat_external( + 'XML_StopParser', [XML_Parser, rffi.INT], lltype.Void) + +XML_SetReturnNSTriplet = expat_external( + 'XML_SetReturnNSTriplet', [XML_Parser, rffi.INT], lltype.Void) +XML_GetSpecifiedAttributeCount = expat_external( + 'XML_GetSpecifiedAttributeCount', [XML_Parser], rffi.INT) + +XML_GetErrorCode = expat_external( + 'XML_GetErrorCode', [XML_Parser], rffi.INT) +XML_ErrorString = expat_external( + 'XML_ErrorString', [rffi.INT], rffi.CCHARP) +XML_GetCurrentLineNumber = expat_external( + 'XML_GetCurrentLineNumber', [XML_Parser], rffi.INT) +XML_GetErrorLineNumber = XML_GetCurrentLineNumber +XML_GetCurrentColumnNumber = expat_external( + 'XML_GetCurrentColumnNumber', [XML_Parser], rffi.INT) +XML_GetErrorColumnNumber = XML_GetCurrentColumnNumber +XML_GetCurrentByteIndex = expat_external( + 'XML_GetCurrentByteIndex', [XML_Parser], rffi.INT) +XML_GetErrorByteIndex = XML_GetCurrentByteIndex + +XML_FreeContentModel = expat_external( + 'XML_FreeContentModel', [XML_Parser, lltype.Ptr(XML_Content)], lltype.Void) + + +class W_XMLParserType(Wrappable): + + def __init__(self, encoding, namespace_separator, w_intern): + if encoding: + self.encoding = encoding + else: + self.encoding = 'utf-8' + self.namespace_separator = namespace_separator + + self.w_intern = w_intern + + self.returns_unicode = True + self.ordered_attributes = False + self.specified_attributes = False + + if namespace_separator: + self.itself = XML_ParserCreateNS(self.encoding, namespace_separator) + else: + self.itself = XML_ParserCreate(self.encoding) + + self.buffer_w = None + self.buffer_size = 8192 + self.w_character_data_handler = None + + self._exc_info = None + + # Handlers management + + def w_convert(self, space, s): + if self.returns_unicode: + return space.call_function( + space.getattr(space.wrap(s), space.wrap("decode")), + space.wrap(self.encoding), + space.wrap("strict")) + else: + return space.wrap(s) + + def w_convert_charp(self, space, data): + if data: + return self.w_convert(space, rffi.charp2str(data)) + else: + return space.w_None + + def w_convert_charp_n(self, space, data, length): + if data: + return self.w_convert(space, rffi.charp2strn(data, length)) + else: + return space.w_None + + def w_convert_model(self, space, model): + children = [self._conv_content_model(model.children[i]) + for i in range(model.c_numchildren)] + return space.newtuple([ + space.wrap(model.c_type), + space.wrap(model.c_quant), + self.w_convert_charp(space, model.c_name), + space.newtuple(children)]) + + def sethandler(self, space, name, w_handler): + if name == 'StartElementHandler': + def callback(unused, name, attrs): + self.flush_character_buffer(space) + w_name = self.w_convert_charp(space, name) + + if self.specified_attributes: + maxindex = XML_GetSpecifiedAttributeCount(self.itself) + else: + maxindex = 0 + while attrs[maxindex]: + maxindex += 2 # copied + + if self.ordered_attributes: + w_attrs = space.newlist([ + self.w_convert_charp(space, attrs[i]) + for i in range(maxindex)]) + else: + w_attrs = space.newdict() + for i in range(0, maxindex, 2): + space.setitem( + w_attrs, + self.w_convert_charp(space, attrs[i]), + self.w_convert_charp(space, attrs[i + 1])) + space.call_function(w_handler, w_name, w_attrs) + + elif name == 'CharacterDataHandler': + def callback(unused, data, length): + w_string = self.w_convert_charp_n(space, data, length) + + if self.buffer_w is None: + space.call_function(w_handler, w_string) + else: + if len(self.buffer_w) + length > self.buffer_size: # XXX sum(len(buffer)) + self.flush_character_buffer(space) + if self.w_character_data_handler is None: + return + if length >= self.buffer_size: + space.call_function(w_handler, w_string) + self.buffer_w = [] + else: + self.buffer_w.append(w_string) + self.flush_character_buffer(space) + if space.is_w(w_handler, space.w_None): + self.w_character_data_handler = None + else: + self.w_character_data_handler = w_handler + + elif name in ['DefaultHandlerExpand', 'DefaultHandler']: + def callback(unused, data, length): + w_string = self.w_convert_charp_n(space, data, length) + space.call_function(w_handler, w_string) + + elif name == 'ElementDeclHandler': + def callback(unused, name, model): + self.flush_character_buffer(space) + w_model = self.w_convert_model(space, model) + XML_FreeContentModel(self.itself, model) + space.call_function(w_handler, + self.w_convert_charp(space, name), + w_model) + + elif name == 'EntityDeclHandler': + def callback(unused, ename, is_param, value, value_len, + base, system_id, pub_id, not_name): + self.flush_character_buffer(space) + + space.call_function( + w_handler, + self.w_convert_charp(space, ename), + space.wrap(is_param), + self.w_convert_charp_n(space, value, value_len), + self.w_convert_charp(space, base), + self.w_convert_charp(space, system_id), + self.w_convert_charp(space, pub_id), + self.w_convert_charp(space, not_name)) + + elif name == 'ExternalEntityRefHandler': + def callback(unused, context, base, system_id, pub_id): + w_res = space.call_function( + w_handler, + self.w_convert_charp(space, context), + self.w_convert_charp(space, base), + self.w_convert_charp(space, system_id), + self.w_convert_charp(space, pub_id)) + if space.is_w(w_res, space.w_None): + return 0 + return space.int_w(w_res) + + else: + ARGTYPES = HANDLERS[name] + def callback(unused, *args): + self.flush_character_buffer(space) + args_w = [] + for i, arg in enumerate(args): + if ARGTYPES[i] is rffi.CCHARP: + w_arg = self.w_convert_charp(space, arg) + else: + w_arg = space.wrap(arg) + args_w.append(w_arg) + space.call_function(w_handler, *args_w) + + def callback_wrapper(*args): + # Catch errors and record them + try: + return callback(*args) + except OperationError, e: + self._exc_info = e + XML_StopParser(self.itself, XML_FALSE) + callback_wrapper.func_name = name + '_callback' + SETTERS[name](self.itself, callback_wrapper) + + def setattr(self, space, name, w_value): + if name == "namespace_prefixes": + XML_SetReturnNSTriplet(self.itself, space.int_w(w_value)) + return + elif name in SETTERS: + return self.sethandler(space, name, w_value) + + # fallback to object.__setattr__() + return space.call_function( + object_setattr(space), + space.wrap(self), space.wrap(name), w_value) + setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] + + # Parse methods + + def Parse(self, space, data, isfinal=True): + res = XML_Parse(self.itself, data, len(data), isfinal) + if self._exc_info: + e = self._exc_info + self._exc_info = None + raise e + elif res == 0: + exc = self.set_error(space, XML_GetErrorCode(self.itself)) + raise exc + self.flush_character_buffer(space) + return res + Parse.unwrap_spec = ['self', ObjSpace, str, bool] + + def ParseFile(self, space, w_file): + return + ParseFile.unwrap_spec = ['self', ObjSpace, W_Root] + + def flush_character_buffer(self, space): + if not self.buffer_w: + return + w_data = space.call_function( + space.getattr(space.wrap(''), space.wrap('join')), + space.newlist(self.buffer_w)) + self.buffer_w = [] + + if self.w_character_data_handler: + space.call_function(self.w_character_data_handler, w_data) + + # Error management + + def set_error(self, space, code): + err = rffi.charp2strn(XML_ErrorString(code), 200) + lineno = XML_GetCurrentLineNumber(self.itself) + colno = XML_GetCurrentColumnNumber(self.itself) + msg = "%s: line: %d, column: %d" % (err, lineno, colno) + w_module = space.getbuiltinmodule('pyexpat') + w_errorcls = space.getattr(w_module, space.wrap('error')) + w_error = space.call_function( + w_errorcls, + space.wrap(msg), space.wrap(code), + space.wrap(colno), space.wrap(lineno)) + self.w_error = w_error + return OperationError(w_errorcls, w_error) + + def descr_ErrorCode(space, self): + return space.wrap(XML_GetErrorCode(self.itself)) + + def descr_ErrorLineNumber(space, self): + return space.wrap(XML_GetErrorLineNumber(self.itself)) + + def descr_ErrorColumnNumber(space, self): + return space.wrap(XML_GetErrorColumnNumber(self.itself)) + + def descr_ErrorByteIndex(space, self): + return space.wrap(XML_GetErrorByteIndex(self.itself)) + + def get_buffer_text(space, self): + return space.wrap(self.buffer_w is not None) + def set_buffer_text(space, self, w_value): + if space.is_true(w_value): + self.buffer_w = [] + else: + self.flush_character_buffer(space) + self.buffer_w = None + + def get_intern(space, self): + return self.w_intern + + +def bool_property(name, cls, doc=None): + def fget(space, obj): + return space.wrap(getattr(obj, name)) + def fset(space, obj, value): + setattr(obj, name, space.bool_w(value)) + return GetSetProperty(fget, fset, cls=cls, doc=doc) + +W_XMLParserType.typedef = TypeDef( + "pyexpat.XMLParserType", + __doc__ = "XML parser", + __setattr__ = interp2app(W_XMLParserType.setattr), + returns_unicode = bool_property('returns_unicode', W_XMLParserType), + ordered_attributes = bool_property('ordered_attributes', W_XMLParserType), + specified_attributes = bool_property('specified_attributes', W_XMLParserType), + intern = GetSetProperty(W_XMLParserType.get_intern, cls=W_XMLParserType), + buffer_text = GetSetProperty(W_XMLParserType.get_buffer_text, + W_XMLParserType.set_buffer_text, cls=W_XMLParserType), + + ErrorCode = GetSetProperty(W_XMLParserType.descr_ErrorCode, cls=W_XMLParserType), + ErrorLineNumber = GetSetProperty(W_XMLParserType.descr_ErrorLineNumber, cls=W_XMLParserType), + ErrorColumnNumber = GetSetProperty(W_XMLParserType.descr_ErrorColumnNumber, cls=W_XMLParserType), + ErrorByteIndex = GetSetProperty(W_XMLParserType.descr_ErrorByteIndex, cls=W_XMLParserType), + CurrentLineNumber = GetSetProperty(W_XMLParserType.descr_ErrorLineNumber, cls=W_XMLParserType), + CurrentColumnNumber = GetSetProperty(W_XMLParserType.descr_ErrorColumnNumber, cls=W_XMLParserType), + CurrentByteIndex = GetSetProperty(W_XMLParserType.descr_ErrorByteIndex, cls=W_XMLParserType), + + **dict((name, interp2app(getattr(W_XMLParserType, name), + unwrap_spec=getattr(W_XMLParserType, + name).unwrap_spec)) + for name in "Parse ParseFile".split()) + ) + +def ParserCreate(space, w_encoding=None, w_namespace_separator=None, + w_intern=NoneNotWrapped): + if space.is_w(w_encoding, space.w_None): + encoding = None + else: + encoding = space.str_w(w_encoding) + + if space.is_w(w_namespace_separator, space.w_None): + namespace_separator = '\0' + else: + separator = space.str_w(w_namespace_separator) + if len(separator) == 0: + namespace_separator = '\0' + elif len(separator) == 1: + namespace_separator = separator[0] + else: + raise OperationError( + space.w_ValueError, + space.wrap('namespace_separator must be at most one character,' + ' omitted, or None')) + if w_intern is None: + w_intern = space.newdict() + + parser = W_XMLParserType(encoding, namespace_separator, w_intern) + return space.wrap(parser) +ParserCreate.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root] + +def ErrorString(space, code): + return space.wrap(rffi.charp2str(XML_ErrorString(code))) +ErrorString.unwrap_spec = [ObjSpace, int] + Modified: pypy/trunk/pypy/objspace/descroperation.py ============================================================================== --- pypy/trunk/pypy/objspace/descroperation.py (original) +++ pypy/trunk/pypy/objspace/descroperation.py Fri Mar 13 14:11:01 2009 @@ -13,6 +13,13 @@ return w_getattribute object_getattribute._annspecialcase_ = 'specialize:memo' +def object_setattr(space): + "Utility that returns the app-level descriptor object.__setattr__." + w_src, w_setattr = space.lookup_in_type_where(space.w_object, + '__setattr__') + return w_setattr +object_setattr._annspecialcase_ = 'specialize:memo' + def raiseattrerror(space, w_obj, name, w_descr=None): w_type = space.type(w_obj) typename = w_type.getname(space, '?') From cfbolz at codespeak.net Fri Mar 13 14:40:18 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 13 Mar 2009 14:40:18 +0100 (CET) Subject: [pypy-svn] r62935 - in pypy/trunk/pypy/lang/smalltalk: . test Message-ID: <20090313134018.98B2B168453@codespeak.net> Author: cfbolz Date: Fri Mar 13 14:40:15 2009 New Revision: 62935 Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py pypy/trunk/pypy/lang/smalltalk/wrapper.py Log: Revert to before 62880. The last checkins here were stupidity on my part: All this work is already done on the spy-graphic branch. Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/primitives.py (original) +++ pypy/trunk/pypy/lang/smalltalk/primitives.py Fri Mar 13 14:40:15 2009 @@ -299,10 +299,10 @@ @expose_primitive(MAKE_POINT, unwrap_spec=[int, int]) def func(interp, x, y): - w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2) + w_res = interp.space.classtable['w_Point'].as_class_get_shadow(interp.space).new(2) point = wrapper.PointWrapper(interp.space, w_res) - point.store_x(x) - point.store_y(y) + point.store_x(interp.space, x) + point.store_y(interp.space, y) return w_res @@ -771,7 +771,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.w_Semaphore): + interp.space.classtable['w_Semaphore']): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(interp) return w_rcvr @@ -780,7 +780,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.w_Semaphore): + interp.space.classtable['w_Semaphore']): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(interp) return w_rcvr @@ -789,7 +789,7 @@ def func(interp, w_rcvr,): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.w_Process): + interp.space.classtable['w_Process']): raise PrimitiveFailedError() wrapper.ProcessWrapper(interp.space, w_rcvr).resume(interp) return w_rcvr @@ -798,7 +798,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.w_Process): + interp.space.classtable['w_Process']): raise PrimitiveFailedError() wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(interp) return w_rcvr Modified: pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/trunk/pypy/lang/smalltalk/test/test_interpreter.py Fri Mar 13 14:40:15 2009 @@ -464,8 +464,8 @@ w_point = interp.s_active_context().top() from pypy.lang.smalltalk.wrapper import PointWrapper point = PointWrapper(interp.space, w_point) - assert point.x() == 0 - assert point.y() == 1 + assert point.x(interp.space) == 0 + assert point.y(interp.space) == 1 def test_longJumpIfTrue(): interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15)) Modified: pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/trunk/pypy/lang/smalltalk/test/test_wrapper.py Fri Mar 13 14:40:15 2009 @@ -115,7 +115,7 @@ def new_semaphore(excess_signals=0): w_semaphore = model.W_PointersObject(None, 3) semaphore = wrapper.SemaphoreWrapper(space, w_semaphore) - semaphore.store_excess_signals(excess_signals) + semaphore.store_excess_signals(space, excess_signals) return semaphore @@ -205,7 +205,7 @@ semaphore = new_semaphore() self.space = space semaphore.signal(self) - assert semaphore.excess_signals() == 1 + assert semaphore.excess_signals(space) == 1 def test_highest_priority(self): py.test.raises(FatalError, wrapper.scheduler(space).highest_priority_process) Modified: pypy/trunk/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/trunk/pypy/lang/smalltalk/wrapper.py Fri Mar 13 14:40:15 2009 @@ -11,14 +11,12 @@ def read(self, index0): try: return self.w_self.fetch(self.space, index0) - # XXX Index error never raised after translation except IndexError: raise WrapperException("Unexpected instance layout. Too small") def write(self, index0, w_new): try: self.w_self.store(self.space, index0, w_new) - # XXX Index error never raised after translation except IndexError: raise WrapperException("Unexpected instance layout. Too small") @@ -36,13 +34,13 @@ return make_getter(index0), make_setter(index0) def make_int_getter(index0): - def getter(self): - return self.space.unwrap_int(self.read(index0)) + def getter(self, space): + return space.unwrap_int(self.read(index0)) return getter def make_int_setter(index0): - def setter(self, new): - return self.write(index0, self.space.wrap_int(new)) + def setter(self, space, new): + return self.write(index0, space.wrap_int(new)) return setter def make_int_getter_setter(index0): @@ -53,9 +51,12 @@ class ProcessWrapper(LinkWrapper): suspended_context, store_suspended_context = make_getter_setter(1) - priority = make_int_getter(2) my_list, store_my_list = make_getter_setter(3) + def priority(self): + w_priority = self.read(2) + return self.space.unwrap_int(w_priority) + def put_to_sleep(self): sched = scheduler(self.space) priority = self.priority() @@ -185,17 +186,17 @@ def signal(self, interp): if self.is_empty_list(): - value = self.excess_signals() - self.store_excess_signals(value + 1) + value = self.excess_signals(interp.space) + self.store_excess_signals(interp.space, value + 1) else: process = self.remove_first_link_of_list() ProcessWrapper(self.space, process).resume(interp) def wait(self, interp): - excess = self.excess_signals() + excess = self.excess_signals(interp.space) w_process = scheduler(interp.space).active_process() if excess > 0: - self.store_excess_signals(excess - 1) + self.store_excess_signals(interp.space, excess - 1) else: self.add_last_link(w_process) ProcessWrapper(self.space, w_process).suspend(interp) From arigo at codespeak.net Fri Mar 13 16:00:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Mar 2009 16:00:39 +0100 (CET) Subject: [pypy-svn] r62936 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090313150039.E2FF7168448@codespeak.net> Author: arigo Date: Fri Mar 13 16:00:36 2009 New Revision: 62936 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: Update the target, in particular by printing the OperationError. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Fri Mar 13 16:00:36 2009 @@ -53,10 +53,11 @@ while i < 1000: t = t[1], t[2], t[0] i += 1 + print t def f6(): print "Arbitrary test function." - n = 5 + n = 21 i = 0 x = 1 while i Author: fijal Date: Fri Mar 13 16:23:54 2009 New Revision: 62938 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: don't let it take forever Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Fri Mar 13 16:23:54 2009 @@ -50,7 +50,7 @@ def f5(): t = (1, 2, 3) i = 0 - while i < 1000: + while i < 100: t = t[1], t[2], t[0] i += 1 print t From afa at codespeak.net Fri Mar 13 16:43:06 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Mar 2009 16:43:06 +0100 (CET) Subject: [pypy-svn] r62939 - pypy/trunk/pypy/lib Message-ID: <20090313154306.B6A7E1684DA@codespeak.net> Author: afa Date: Fri Mar 13 16:43:06 2009 New Revision: 62939 Modified: pypy/trunk/pypy/lib/pyexpat.py Log: Add UseForeignDTD to pyexpat. Completely untested, since ctypes_configure does not work on Windows :-( Modified: pypy/trunk/pypy/lib/pyexpat.py ============================================================================== --- pypy/trunk/pypy/lib/pyexpat.py (original) +++ pypy/trunk/pypy/lib/pyexpat.py Fri Mar 13 16:43:06 2009 @@ -70,6 +70,8 @@ declare_external('XML_StopParser', [XML_Parser, c_int], None) declare_external('XML_ErrorString', [c_int], c_char_p) declare_external('XML_SetBase', [XML_Parser, c_char_p], None) +if XML_COMBINED_VERSION >= 19505: + declare_external('XML_UseForeignDTD', [XML_Parser, c_int], None) declare_external('XML_SetUnknownEncodingHandler', [XML_Parser, c_void_p, c_void_p], None) @@ -419,6 +421,14 @@ def SetParamEntityParsing(self, arg): XML_SetParamEntityParsing(self.itself, arg) + if XML_COMBINED_VERSION >= 19505: + def UseForeignDTD(self, arg=True): + if arg: + flag = XML_TRUE + else: + flag = XML_FALSE + XML_SetParamEntityParsing(self.itself, flag) + def __getattr__(self, name): if name == 'buffer_text': return self.buffer is not None From fijal at codespeak.net Fri Mar 13 16:46:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 16:46:09 +0100 (CET) Subject: [pypy-svn] r62940 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090313154609.550811684E1@codespeak.net> Author: fijal Date: Fri Mar 13 16:46:08 2009 New Revision: 62940 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: refactor optimize.py, now passes the rogue test. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 13 16:46:08 2009 @@ -29,22 +29,26 @@ class CancelInefficientLoop(Exception): pass +FLAG_ALLOCATIONS = 0x0 +FLAG_LIST_ALLOCATIONS = 0x1 +FLAG_PREBULT_OBJECTS = 0x2 +FLAG_BOXES_FROM_FRAME = 0x3 +FLAG_SHIFT = 2 +FLAG_MASK = 0x3 + class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate # setfields: list of triples - # (index_in_allocations, ofs, ~index_in_arglist) - # -or- - # (index_in_allocations, ofs, index_in_allocations) - # -or- - # (~index_in_arglist, ofs, index_in_allocations) - # -or- - # (~index_in_arglist, ofs, ~index_in_arglist) - # last two cases are for virtualizables only + # (index_of_parent, ofs, index_of_child) + # indexes have two least significant bits representing + # where they're living, look above. self.allocations = [] self.setfields = [] # the same as above, but for lists and for running setitem self.list_allocations = [] + # objects that are "always virtual" + self.prebuilt_objects = [] self.setitems = [] def deal_with_box(self, box, nodes, liveboxes, memo, cpu): @@ -60,35 +64,34 @@ virtual = instnode.virtual virtualized = instnode.virtualized if virtual: - if isinstance(instnode.cls.source, FixedList): - ld = instnode.cls.source - assert isinstance(ld, FixedList) - alloc_offset = len(self.list_allocations) - ad = ld.arraydescr - if instnode.cursize == -1: - # fish fish fish - instnode.cursize = executor.execute(cpu, rop.ARRAYLEN_GC, - [instnode.source], - ad).getint() - self.list_allocations.append((ad, instnode.cursize)) - res = (alloc_offset + 1) << 16 + if instnode.always_virtual: + res = ((len(self.prebuilt_objects) << FLAG_SHIFT) + | FLAG_PREBULT_OBJECTS) + self.prebuilt_objects.append(instnode.source) else: - alloc_offset = len(self.allocations) - self.allocations.append(instnode.cls.source.getint()) - res = alloc_offset + if isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + assert isinstance(ld, FixedList) + alloc_offset = len(self.list_allocations) + ad = ld.arraydescr + self.list_allocations.append((ad, instnode.cursize)) + res = (alloc_offset << FLAG_SHIFT) | FLAG_LIST_ALLOCATIONS + else: + alloc_offset = len(self.allocations) + self.allocations.append(instnode.cls.source.getint()) + res = (alloc_offset << FLAG_SHIFT) | FLAG_ALLOCATIONS memo[box] = res for ofs, node in instnode.curfields.items(): num = self.deal_with_box(node.source, nodes, liveboxes, memo, cpu) if isinstance(instnode.cls.source, FixedList): ld = instnode.cls.source - x = (alloc_offset + 1) << 16 assert isinstance(ld, FixedList) - self.setitems.append((x, ld.arraydescr, ofs, num)) + self.setitems.append((res, ld.arraydescr, ofs, num)) else: - self.setfields.append((alloc_offset, ofs, num)) + self.setfields.append((res, ofs, num)) elif virtualized: - res = ~len(liveboxes) + res = (len(liveboxes) << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME memo[box] = res liveboxes.append(box) for ofs, node in instnode.curfields.items(): @@ -96,7 +99,7 @@ cpu) self.setfields.append((res, ofs, num)) else: - res = ~len(liveboxes) + res = (len(liveboxes) << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME memo[box] = res liveboxes.append(box) return res @@ -134,6 +137,8 @@ self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables + self.always_virtual = False # a flag that is set on objects + # passed around, that are virtuals stored on virtualizables def is_nonzero(self): return self.cls is not None or self.nonzero @@ -145,8 +150,11 @@ if self in memo: return memo[self] = None - if self.startbox and escape_self: - self.escaped = True + if self.startbox: + if escape_self: + self.escaped = True + else: + self.always_virtual = True if not self.virtualized: for node in self.curfields.values(): node.escape_if_startbox(memo) @@ -525,12 +533,13 @@ if box not in rev_boxes: rev_boxes[box] = len(liveboxes) liveboxes.append(box) - index = ~rev_boxes[box] + index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME fieldbox = subnode.source if fieldbox not in rev_boxes: rev_boxes[fieldbox] = len(liveboxes) liveboxes.append(fieldbox) - fieldindex = ~rev_boxes[fieldbox] + fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | + FLAG_BOXES_FROM_FRAME) if (node.cls is not None and isinstance(node.cls.source, FixedList)): ld = node.cls.source @@ -816,12 +825,27 @@ new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode) -def box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index): - if index < 0: - return boxes_from_frame[~index] - if index > 0xffff: - return allocated_lists[(index - 1) >> 16] - return allocated_boxes[index] +class Chooser(object): + def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists, + prebuilt_objects): + self.boxes_from_frame = boxes_from_frame + self.allocated_lists = allocated_lists + self.allocated_boxes = allocated_boxes + self.prebuilt_objects = prebuilt_objects + + def box_from_index(self, index): + ofs = index >> FLAG_SHIFT + where_from = index & FLAG_MASK + if where_from == FLAG_BOXES_FROM_FRAME: + return self.boxes_from_frame[ofs] + elif where_from == FLAG_ALLOCATIONS: + return self.allocated_boxes[ofs] + elif where_from == FLAG_LIST_ALLOCATIONS: + return self.allocated_lists[ofs] + elif where_from == FLAG_PREBULT_OBJECTS: + return self.prebuilt_objects[ofs] + else: + assert 0, "I can't count to 4" def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): allocated_boxes = [] @@ -843,30 +867,22 @@ listbox = metainterp.execute_and_record(rop.NEW_ARRAY, [sizebox], ad) allocated_lists.append(listbox) + chooser = Chooser(boxes_from_frame, allocated_boxes, allocated_lists, + storage.prebuilt_objects) for index_in_alloc, ofs, index_in_arglist in storage.setfields: - fieldbox = box_from_index(allocated_boxes, allocated_lists, - boxes_from_frame, index_in_arglist) - box = box_from_index(allocated_boxes, allocated_lists, - boxes_from_frame, - index_in_alloc) + fieldbox = chooser.box_from_index(index_in_arglist) + box = chooser.box_from_index(index_in_alloc) assert isinstance(ofs, AbstractDescr) metainterp.execute_and_record(rop.SETFIELD_GC, [box, fieldbox], ofs) for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: - itembox = box_from_index(allocated_boxes, allocated_lists, - boxes_from_frame, index_in_arglist) - box = box_from_index(allocated_boxes, allocated_lists, - boxes_from_frame, index_in_alloc) + itembox = chooser.box_from_index(index_in_arglist) + box = chooser.box_from_index(index_in_alloc) metainterp.execute_and_record(rop.SETARRAYITEM_GC, [box, ofs, itembox], ad) newboxes = [] for index in storage.indices: - if index < 0: - newboxes.append(boxes_from_frame[~index]) - elif index > 0xffff: - newboxes.append(allocated_lists[(index - 1) >> 16]) - else: - newboxes.append(allocated_boxes[index]) + newboxes.append(chooser.box_from_index(index)) return newboxes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Fri Mar 13 16:46:08 2009 @@ -372,7 +372,6 @@ assert res == f(10) def test_always_virtual_with_origfields(self): - py.test.skip("CRASH") jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) From fijal at codespeak.net Fri Mar 13 16:47:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 16:47:47 +0100 (CET) Subject: [pypy-svn] r62941 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090313154747.63C18168444@codespeak.net> Author: fijal Date: Fri Mar 13 16:47:45 2009 New Revision: 62941 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: fix tests Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Mar 13 16:47:45 2009 @@ -309,7 +309,7 @@ assert guard_op.liveboxes == [E.sum2, E.v2] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, E.ofs_value, -2)] + assert guard_op.storage_info.setfields == [(0, E.ofs_value, 7)] def test_E_rebuild_after_failure(): class FakeMetaInterp(object): @@ -461,7 +461,7 @@ assert guard_op.liveboxes == [G.sum2, ConstInt(124)] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, G.ofs_value, -2)] + assert guard_op.storage_info.setfields == [(0, G.ofs_value, 7)] # ____________________________________________________________ From fijal at codespeak.net Fri Mar 13 17:00:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 17:00:48 +0100 (CET) Subject: [pypy-svn] r62942 - pypy/branch/pyjitpl5/pypy/translator/platform Message-ID: <20090313160048.970921684A9@codespeak.net> Author: fijal Date: Fri Mar 13 17:00:47 2009 New Revision: 62942 Modified: pypy/branch/pyjitpl5/pypy/translator/platform/linux.py Log: I suppose for now let's leave -O0 on this branch. Make sure we don't merge it! Modified: pypy/branch/pyjitpl5/pypy/translator/platform/linux.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/platform/linux.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/platform/linux.py Fri Mar 13 17:00:47 2009 @@ -9,7 +9,7 @@ name = "linux" link_flags = ['-pthread'] - cflags = ['-O3', '-pthread', '-fomit-frame-pointer'] + cflags = ['-O0', '-pthread', '-fomit-frame-pointer'] standalone_only = [] shared_only = [] so_ext = 'so' From fijal at codespeak.net Fri Mar 13 17:54:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 17:54:28 +0100 (CET) Subject: [pypy-svn] r62943 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313165428.9FE1C1683EE@codespeak.net> Author: fijal Date: Fri Mar 13 17:54:26 2009 New Revision: 62943 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: improve logging of events from x86 backend. That let's us leave almost full traces for even complex tests that include failing guards and catches. Note that debugging tools are not ready to parse that yet :) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 17:54:26 2009 @@ -1,4 +1,4 @@ -import sys +import sys, os import ctypes from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.history import Const, ConstInt, Box, ConstPtr, BoxPtr,\ @@ -54,6 +54,20 @@ self.malloc_func_addr = 0 self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) self._exception_addr = 0 + self._log_fd = self._get_log() + + def _get_log(self): + s = os.environ.get('PYPYJITLOG') + if not s: + return -1 + s += '.ops' + try: + flags = os.O_WRONLY|os.O_CREAT|os.O_TRUNC + log_fd = os.open(s, flags, 0666) + except OSError: + os.write(2, "could not create log file\n") + return -1 + return log_fd def make_sure_mc_exists(self): if self.mc is None: @@ -79,7 +93,43 @@ # the address of the function called by 'new': directly use # Boehm's GC_malloc function. if self.malloc_func_addr == 0: - self.malloc_func_addr = gc_malloc_fnaddr() + self.malloc_func_addr = gc_malloc_fnaddr() + + def eventually_log_operations(self, operations, guard_op): + if self._log_fd == -1: + return + memo = {} + os.write(self._log_fd, "<<<<<<<<<<\n") + if guard_op is not None: + os.write(self._log_fd, "GO(%d)\n" % guard_op._jmp_from) + for op in operations: + args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) + os.write(self._log_fd, "%s %s\n" % (op.getopname(), args)) + if op.result is not None: + os.write(self._log_fd, " => %s\n" % repr_of_arg(memo, + op.result)) + if op.is_guard(): + liveboxes_s = ",".join([repr_of_arg(memo, arg) for arg in + op.liveboxes]) + os.write(self._log_fd, " .. %s\n" % liveboxes_s) + os.write(self._log_fd, ">>>>>>>>>>\n") + + def log_failure_recovery(self, gf, guard_index): + if self._log_fd == -1: + return + os.write(self._log_fd, 'xxxxxxxxxx\n') + j = 0 + memo = {} + reprs = [] + for box in gf.guard_op.liveboxes: + if isinstance(box, Box): + valuebox = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j) + reprs.append(repr_of_arg(memo, valuebox)) + j += 1 + jmp = gf.guard_op._jmp_from + os.write(self._log_fd, "%d %d %s\n" % (guard_index, jmp, + ",".join(reprs))) + os.write(self._log_fd, 'xxxxxxxxxx\n') def assemble(self, operations, guard_op, verbose=False): self.verbose = verbose @@ -89,19 +139,7 @@ self.make_sure_mc_exists() op0 = operations[0] op0.position = self.mc.tell() - if self.verbose and we_are_translated(): - print - memo = {} - for op in operations: - args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) - llop.debug_print(lltype.Void, "%s %s" % (op.getopname(), args)) - if op.result is not None: - llop.debug_print(lltype.Void, " => %s" % repr_of_arg(memo, op.result)) - if op.is_guard(): - liveboxes_s = ",".join([repr_of_arg(memo, arg) for arg in - op.liveboxes]) - llop.debug_print(lltype.Void, " .. %s" % liveboxes_s) - print + self.eventually_log_operations(operations, guard_op) regalloc = RegAlloc(operations, guard_op, self.cpu.translate_support_code) if not we_are_translated(): self._regalloc = regalloc # for debugging Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp Fri Mar 13 17:54:26 2009 @@ -1,12 +1,40 @@ -merge_point bp(0,135638976),bi(1,210),bi(2,4),bi(3,1),bi(4,1),bi(5,2),bi(6,6) -guard_value bi(5,2),ci(7,2) -int_le bi(2,4),ci(8,1) - => bi(9,0) -int_is_true bi(9,0) - => bi(10,0) -guard_false bi(10,0) -int_mul bi(1,210),bi(2,4) - => bi(11,840) -int_sub bi(2,4),ci(12,1) - => bi(13,3) -jump bp(0,135638976),bi(11,840),bi(13,3),ci(14,1),ci(8,1),ci(15,2),bi(6,6) +<<<<<<<<<< +merge_point bi(0,7),bi(1,3),bi(2,27) +int_add bi(2,27),bi(0,7) + => bi(3,34) +int_add bi(1,3),ci(4,1) + => bi(5,4) +int_eq bi(5,4),ci(6,4) + => bi(7,1) +guard_true bi(7,1) + .. bi(0,7),bi(3,34),bi(5,4),ci(8,0) +int_add bi(3,34),ci(9,100) + => bi(10,134) +int_sub bi(0,7),ci(4,1) + => bi(11,6) +int_gt bi(11,6),ci(8,0) + => bi(12,1) +guard_true bi(12,1) + .. bi(11,6),bi(10,134),ci(8,0),ci(8,0) +jump bi(11,6),ci(8,0),bi(10,134) +>>>>>>>>>> +xxxxxxxxxx +0 -1342111720 bi(0,6),bi(1,140),bi(2,1) +xxxxxxxxxx +xxxxxxxxxx +0 -1342111720 bi(0,2),bi(1,254),bi(2,1) +xxxxxxxxxx +<<<<<<<<<< +GO(-1342111720) +catch bi(0,2),bi(1,254),bi(2,1),ci(3,0) +int_sub bi(0,2),ci(4,1) + => bi(5,1) +int_gt bi(5,1),ci(3,0) + => bi(6,1) +guard_true bi(6,1) + .. bi(5,1),bi(1,254),bi(2,1),ci(3,0) +jump bi(5,1),bi(2,1),bi(1,254) +>>>>>>>>>> +xxxxxxxxxx +2 -1342111655 bi(0,0),bi(1,255),bi(2,2) +xxxxxxxxxx Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 13 17:54:26 2009 @@ -145,6 +145,7 @@ llop.debug_print(lltype.Void, '.. calling back from', guard_op, 'to the jit') gf = GuardFailed(self, frame_addr, guard_op) + self.assembler.log_failure_recovery(gf, guard_index) self.metainterp.handle_guard_failure(gf) self.return_value_type = gf.return_value_type if self.debug: From fijal at codespeak.net Fri Mar 13 20:23:05 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 20:23:05 +0100 (CET) Subject: [pypy-svn] r62944 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313192305.18B411684F9@codespeak.net> Author: fijal Date: Fri Mar 13 20:23:00 2009 New Revision: 62944 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: try to put logging into one place and also make it write to file (only if env var is set). This sorts out logging of x86 backend, parser needs adoption though Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Mar 13 20:23:00 2009 @@ -44,6 +44,7 @@ MC_SIZE = 1024*1024 # 1MB, but assumed infinite for now generic_return_addr = 0 position = -1 + log_fd = -1 def __init__(self, cpu, translate_support_code=False): self.cpu = cpu @@ -54,8 +55,7 @@ self.malloc_func_addr = 0 self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) self._exception_addr = 0 - self._log_fd = self._get_log() - + def _get_log(self): s = os.environ.get('PYPYJITLOG') if not s: @@ -71,6 +71,7 @@ def make_sure_mc_exists(self): if self.mc is None: + self._log_fd = self._get_log() # we generate the loop body in 'mc' # 'mc2' is for guard recovery code if we_are_translated(): @@ -131,6 +132,14 @@ ",".join(reprs))) os.write(self._log_fd, 'xxxxxxxxxx\n') + def log_call(self, name, valueboxes): + if self._log_fd == -1: + return + memo = {} + args_s = ','.join([repr_of_arg(memo, box) for box in valueboxes]) + os.write(self._log_fd, "CALL\n") + os.write(self._log_fd, "%s %s\n" % (name, args_s)) + def assemble(self, operations, guard_op, verbose=False): self.verbose = verbose # the last operation can be 'jump', 'return' or 'guard_pause'; Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/inp Fri Mar 13 20:23:00 2009 @@ -18,9 +18,13 @@ .. bi(11,6),bi(10,134),ci(8,0),ci(8,0) jump bi(11,6),ci(8,0),bi(10,134) >>>>>>>>>> +CALL +run_this_loop bi(0,6),bi(1,0),bi(2,134) xxxxxxxxxx 0 -1342111720 bi(0,6),bi(1,140),bi(2,1) xxxxxxxxxx +CALL +run_this_loop bi(0,3),bi(1,3),bi(2,149) xxxxxxxxxx 0 -1342111720 bi(0,2),bi(1,254),bi(2,1) xxxxxxxxxx Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Fri Mar 13 20:23:00 2009 @@ -141,19 +141,19 @@ try: del self.keepalives[self.keepalives_index:] guard_op = self._guard_list[guard_index] - if self.debug: - llop.debug_print(lltype.Void, '.. calling back from', - guard_op, 'to the jit') + #if self.debug: + # llop.debug_print(lltype.Void, '.. calling back from', + # guard_op, 'to the jit') gf = GuardFailed(self, frame_addr, guard_op) self.assembler.log_failure_recovery(gf, guard_index) self.metainterp.handle_guard_failure(gf) self.return_value_type = gf.return_value_type - if self.debug: - if gf.return_addr == self.assembler.generic_return_addr: - llop.debug_print(lltype.Void, 'continuing at generic return address') - else: - llop.debug_print(lltype.Void, 'continuing at', - uhex(gf.return_addr)) + #if self.debug: + #if gf.return_addr == self.assembler.generic_return_addr: + # llop.debug_print(lltype.Void, 'continuing at generic return address') + #else: + # llop.debug_print(lltype.Void, 'continuing at', + # uhex(gf.return_addr)) return gf.return_addr except Exception, e: if not we_are_translated(): @@ -325,20 +325,19 @@ v = self.get_box_value_as_int(box) values_as_int[i] = v # debug info - if self.debug: - values_repr = ", ".join([str(values_as_int[i]) for i in - range(len(valueboxes))]) - llop.debug_print(lltype.Void, 'exec:', name, values_repr) + #if self.debug and not we_are_translated(): + # values_repr = ", ".join([str(values_as_int[i]) for i in + # range(len(valueboxes))]) + # llop.debug_print(lltype.Void, 'exec:', name, values_repr) + self.assembler.log_call(name, valueboxes) self.keepalives_index = len(self.keepalives) res = self.execute_call(startmp, func, values_as_int) if self.return_value_type == VOID: - if self.debug: - llop.debug_print(lltype.Void, " => void result") + #self.assembler.log_void_result() res = None else: - if self.debug: - llop.debug_print(lltype.Void, " => ", res) + #self.assembler.log_result(res) res = self.get_valuebox_from_int(self.return_value_type, res) keepalive_until_here(valueboxes) self.keepalives_index = oldindex From fijal at codespeak.net Fri Mar 13 20:55:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 20:55:39 +0100 (CET) Subject: [pypy-svn] r62945 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313195539.E764B16850B@codespeak.net> Author: fijal Date: Fri Mar 13 20:55:37 2009 New Revision: 62945 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Log: adapt the tool... Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Fri Mar 13 20:55:37 2009 @@ -1,15 +1,37 @@ #!/usr/bin/env python -""" A simple parser for debug output from x86 backend. used to derive +""" A parser for debug output from x86 backend. used to derive new tests from crashes """ import sys, py, re +def pairs(lst): + res = [] + for i in range(0, len(lst), 2): + res.append(lst[i] + ',' + lst[i + 1]) + return res + +class Loop(object): + def __init__(self, operations, guard_op): + self.operations = operations + self.guard_op = guard_op + +class Call(object): + def __init__(self, name, args): + self.name = name + self.args = args + +class GuardFailure(object): + def __init__(self, index, jmp_from, args): + self.index = index + self.jmp_from = jmp_from + self.args = args + class Parser(object): def __init__(self): self.boxes = {} self.box_creations = [] - self.operations = [] + self.blocks = [] self.unique_ptrs = {} def parse_name(self, name): @@ -55,17 +77,14 @@ res.append(unique_box) return res - def parse(self, fname): - def pairs(lst): - res = [] - for i in range(0, len(lst), 2): - res.append(lst[i] + ',' + lst[i + 1]) - return res - - operations = [] - data = py.path.local(fname).read() - lines = data.split("\n") + def parse_loop(self, lines): i = 0 + operations = [] + if lines[0].startswith('GO'): + guard_op = int(re.search('\((-?\d+)\)', lines[0]).group(1)) + i = 1 + else: + guard_op = None while i < len(lines): line = lines[i] if line: @@ -80,8 +99,47 @@ [res] = self.parse_args([box]) else: res = None - self.operations.append((opname, parsed_args, res)) + if i + 1 < len(lines) and lines[i + 1].startswith(' ..'): + i += 1 + liveboxes = lines[i][5:] + liveboxes = self.parse_args(pairs(liveboxes.split(","))) + else: + liveboxes = None + operations.append((opname, parsed_args, res, liveboxes)) i += 1 + return Loop(operations, guard_op) + + def parse_call(self, line): + name, args = line.split(" ") + return Call(name, self.parse_args(pairs(args.split(",")))) + + def parse_guard_failure(self, line): + index, jmp_from, args = line.split(" ") + return GuardFailure(index, jmp_from, self.parse_args(pairs(args.split(",")))) + + def parse(self, fname): + data = py.path.local(fname).read() + lines = data.split("\n") + i = 0 + while i < len(lines): + if lines[i] == '<<<<<<<<<<': + # a loop + j = i + while lines[j] != '>>>>>>>>>>': + j += 1 + self.blocks.append(self.parse_loop(lines[i+1:j])) + i = j + 1 + elif lines[i] == 'CALL': + self.blocks.append(self.parse_call(lines[i+1])) + i += 2 + elif lines[i] == 'xxxxxxxxxx': + assert lines[i + 2] == 'xxxxxxxxxx' + self.blocks.append(self.parse_guard_failure(lines[i + 1])) + i += 3 + elif not lines[i]: + i += 1 + else: + xxxx def output(self): for box in self.box_creations: @@ -104,8 +162,8 @@ def test_loopparser(): parser = Parser() parser.parse(py.magic.autopath().join('..', 'inp')) - assert len(parser.operations) == 8 - assert parser.operations[1] == ('guard_value', ['boxint_5', 'constint_7'], - None) - assert len(parser.box_creations) == 8 + assert len(parser.blocks[0].operations) == 10 + assert parser.blocks[0].operations[1] == ('int_add', + ['boxint_2', 'boxint_0'], 'boxint_3', None) + assert len(parser.box_creations) == 13 From fijal at codespeak.net Fri Mar 13 21:03:12 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 21:03:12 +0100 (CET) Subject: [pypy-svn] r62946 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313200312.D51DD168515@codespeak.net> Author: fijal Date: Fri Mar 13 21:03:12 2009 New Revision: 62946 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Log: minor fixes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Fri Mar 13 21:03:12 2009 @@ -43,6 +43,8 @@ return 'ConstInt' elif name == 'cp': return 'ConstPtr' + elif name == 'ca': + return 'ConstAddr' raise NotImplementedError def _get_unique_ptr(self, val): @@ -55,6 +57,9 @@ def get_ptr_val(self, val): return 'lltype.cast_opaque_ptr(llmemory.GCREF, ptr_%d)' % self._get_unique_ptr(val) + def get_adr_val(self, val): + return 'llmemory.cast_ptr_to_adr(ptr_%d)' % self._get_unique_ptr(val) + def register_box(self, id, name, val): try: return self.boxes[id] @@ -63,6 +68,8 @@ self.boxes[id] = result if name.endswith('Ptr'): val = self.get_ptr_val(val) + elif name == 'ConstAddr': + val = self.get_adr_val(val) self.box_creations.append('%s = %s(%s)' % (result, name, val)) return result @@ -144,12 +151,19 @@ def output(self): for box in self.box_creations: print " " * 4 + box - print " " * 4 + "ops = [" - for name, args, res in self.operations: - print " " * 8 + "ResOperation(rop.%s, [%s], %s)," % (name.upper(), ", ".join(args), res) - print " " * 4 + "]" - print " " * 4 + "ops[-1].jump_target = ops[0]" - print " " * 4 + "cpu.compile_operations(ops)" + for block in self.blocks: + if isinstance(block, Loop): + print " " * 4 + "ops = [" + d = {} + for i, (name, args, res, liveboxes) in enumerate(block.operations): + print " " * 8 + "ResOperation(rop.%s, [%s], %s)," % (name.upper(), ", ".join(args), res) + if liveboxes is not None: + d[i] = liveboxes + for k, v in d.items(): + print " " * 4 + "ops[%d].liveboxes = [%s]" % (k, ", ".join(v)) + print " " * 4 + "]" + print " " * 4 + "ops[-1].jump_target = ops[0]" + print " " * 4 + "cpu.compile_operations(ops)" if __name__ == '__main__': if len(sys.argv) != 2: From fijal at codespeak.net Fri Mar 13 21:17:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 21:17:35 +0100 (CET) Subject: [pypy-svn] r62947 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090313201735.F1AFB1684ED@codespeak.net> Author: fijal Date: Fri Mar 13 21:17:30 2009 New Revision: 62947 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Log: another improvements. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/loopparser.py Fri Mar 13 21:17:30 2009 @@ -149,10 +149,14 @@ xxxx def output(self): + for val, num in self.unique_ptrs.items(): + print " " * 4 + "ptr_%d = xxx(%d)" % (num, val) for box in self.box_creations: print " " * 4 + box for block in self.blocks: if isinstance(block, Loop): + if block.operations[-1][0] == '<119>': + continue print " " * 4 + "ops = [" d = {} for i, (name, args, res, liveboxes) in enumerate(block.operations): @@ -164,6 +168,14 @@ print " " * 4 + "]" print " " * 4 + "ops[-1].jump_target = ops[0]" print " " * 4 + "cpu.compile_operations(ops)" + if isinstance(block, Call): + if block.name == 'call': + continue # ignore calls to single function + print " " * 4 + "cpu.execute_operations_in_new_frame('%s', [%s])" % (block.name, ", ".join(block.args)) + if isinstance(block, GuardFailure): + expected = "[" + ", ".join(["%s.value" % arg for arg in block.args]) + "]" + print " " * 4 + "expected = " + expected + print " " * 4 + "assert meta_interp.recordedvalues = expected" if __name__ == '__main__': if len(sys.argv) != 2: From fijal at codespeak.net Fri Mar 13 21:32:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Mar 2009 21:32:27 +0100 (CET) Subject: [pypy-svn] r62948 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090313203227.C7FA216851F@codespeak.net> Author: fijal Date: Fri Mar 13 21:32:25 2009 New Revision: 62948 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: looks like I broke stuff. This is a partial fix, more tomorrow Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Mar 13 21:32:25 2009 @@ -67,7 +67,7 @@ if instnode.always_virtual: res = ((len(self.prebuilt_objects) << FLAG_SHIFT) | FLAG_PREBULT_OBJECTS) - self.prebuilt_objects.append(instnode.source) + self.prebuilt_objects.append(instnode.source.constbox()) else: if isinstance(instnode.cls.source, FixedList): ld = instnode.cls.source From fijal at codespeak.net Sat Mar 14 10:30:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Mar 2009 10:30:34 +0100 (CET) Subject: [pypy-svn] r62950 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090314093034.4CB161684FA@codespeak.net> Author: fijal Date: Sat Mar 14 10:30:31 2009 New Revision: 62950 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: a test that showcases some problem Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Sat Mar 14 10:30:31 2009 @@ -394,6 +394,35 @@ res = self.meta_interp(f, [10], listops=True) assert res == 2 + def test_pass_always_virtual_to_bridge(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + _always_virtual_ = ['l'] + + def __init__(self, l): + self.l = l + + def f(n): + frame = Frame([1,2,3]) + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n) + jitdriver.jit_merge_point(frame=frame, n=n) + if n % 3: + n -= frame.l[0] + else: + n -= frame.l[1] + return frame.l[2] + + res = self.meta_interp(f, [30], listops=True) + self.check_loops(setarrayitem_gc=0) + self.check_loop_count(3) + assert res == 3 + + def test_external_read(self): py.test.skip("Fails") jitdriver = JitDriver(greens = [], reds = ['frame'], From fijal at codespeak.net Sat Mar 14 13:51:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Mar 2009 13:51:40 +0100 (CET) Subject: [pypy-svn] r62951 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090314125140.AA33816846D@codespeak.net> Author: fijal Date: Sat Mar 14 13:51:38 2009 New Revision: 62951 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Log: couple of missing ops + a minor improvement in descr display Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sat Mar 14 13:51:38 2009 @@ -532,12 +532,16 @@ else: return do_getarrayitem_gc_int(array, index, self.memocast) + op_getarrayitem_gc_pure = op_getarrayitem_gc + def op_getfield_gc(self, fielddescr, struct): if fielddescr.type == 'p': return do_getfield_gc_ptr(struct, fielddescr.ofs) else: return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast) + op_getfield_gc_pure = op_getfield_gc + def op_getfield_raw(self, fielddescr, struct): if fielddescr.type == 'p': return do_getfield_raw_ptr(struct, fielddescr.ofs) @@ -581,6 +585,8 @@ err_result = 0 return _do_call_common(func, self.memocast, err_result) + op_call_pure = op_call + def op_new_array(self, arraydescr, count): return do_new_array(arraydescr.ofs, count) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sat Mar 14 13:51:38 2009 @@ -15,6 +15,8 @@ class Descr(history.AbstractDescr): + name = None + def __init__(self, ofs, type='?'): self.ofs = ofs self.type = type @@ -45,9 +47,10 @@ raise TypeError("cannot use comparison on Descrs") def __repr__(self): + if self.name is not None: + return '' % (self.ofs, self.type, self.name) return '' % (self.ofs, self.type) - class CPU(object): def __init__(self, rtyper, stats=None, translate_support_code=False, @@ -234,7 +237,9 @@ def fielddescrof(S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname) token = history.getkind(getattr(S, fieldname)) - return Descr(ofs, token[0]) + res = Descr(ofs, token[0]) + res.name = fieldname + return res @staticmethod def arraydescrof(A): @@ -368,7 +373,6 @@ else: # calldescr.type == 'v' # void llimpl.do_call_void(func, self.memo_cast) - class GuardFailed(object): returns = False From afa at codespeak.net Sat Mar 14 14:28:44 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 14 Mar 2009 14:28:44 +0100 (CET) Subject: [pypy-svn] r62952 - pypy/trunk/pypy/annotation Message-ID: <20090314132844.93707168491@codespeak.net> Author: afa Date: Sat Mar 14 14:28:42 2009 New Revision: 62952 Modified: pypy/trunk/pypy/annotation/annrpython.py Log: Remove a unused variable, that can even cause an exception when reporting a degenerated value. Modified: pypy/trunk/pypy/annotation/annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/annrpython.py (original) +++ pypy/trunk/pypy/annotation/annrpython.py Sat Mar 14 14:28:42 2009 @@ -309,7 +309,6 @@ except AttributeError: pass - graph = position_key[0] msgstr = format_someobject_error(self, position_key, what, s_value, called_from_graph, self.bindings.get(what, "(none)")) From fijal at codespeak.net Sat Mar 14 15:44:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Mar 2009 15:44:10 +0100 (CET) Subject: [pypy-svn] r62953 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090314144410.4661A168453@codespeak.net> Author: fijal Date: Sat Mar 14 15:44:08 2009 New Revision: 62953 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: A controversial checkin - try to reuse logic for virtualizables for always_virtuals (they're more or less the same after all). Tests that showcase problems with bridges Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Mar 14 15:44:08 2009 @@ -10,6 +10,7 @@ SpecNodeWithBox, DelayedFixedListSpecNode, VirtualFixedListSpecNode, + VirtualizableListSpecNode, ) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated @@ -26,12 +27,18 @@ assert other.arraydescr == self.arraydescr return True +class FixedClass(Const): + def equals(self, other): + assert isinstance(other, FixedClass) + return True + class CancelInefficientLoop(Exception): - pass + def __init__(self, *args): + import pdb + pdb.set_trace() FLAG_ALLOCATIONS = 0x0 FLAG_LIST_ALLOCATIONS = 0x1 -FLAG_PREBULT_OBJECTS = 0x2 FLAG_BOXES_FROM_FRAME = 0x3 FLAG_SHIFT = 2 FLAG_MASK = 0x3 @@ -47,11 +54,9 @@ self.setfields = [] # the same as above, but for lists and for running setitem self.list_allocations = [] - # objects that are "always virtual" - self.prebuilt_objects = [] self.setitems = [] - def deal_with_box(self, box, nodes, liveboxes, memo, cpu): + def deal_with_box(self, box, nodes, liveboxes, memo): if isinstance(box, Const) or box not in nodes: virtual = False virtualized = False @@ -64,26 +69,20 @@ virtual = instnode.virtual virtualized = instnode.virtualized if virtual: - if instnode.always_virtual: - res = ((len(self.prebuilt_objects) << FLAG_SHIFT) - | FLAG_PREBULT_OBJECTS) - self.prebuilt_objects.append(instnode.source.constbox()) + if isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + assert isinstance(ld, FixedList) + alloc_offset = len(self.list_allocations) + ad = ld.arraydescr + self.list_allocations.append((ad, instnode.cursize)) + res = (alloc_offset << FLAG_SHIFT) | FLAG_LIST_ALLOCATIONS else: - if isinstance(instnode.cls.source, FixedList): - ld = instnode.cls.source - assert isinstance(ld, FixedList) - alloc_offset = len(self.list_allocations) - ad = ld.arraydescr - self.list_allocations.append((ad, instnode.cursize)) - res = (alloc_offset << FLAG_SHIFT) | FLAG_LIST_ALLOCATIONS - else: - alloc_offset = len(self.allocations) - self.allocations.append(instnode.cls.source.getint()) - res = (alloc_offset << FLAG_SHIFT) | FLAG_ALLOCATIONS + alloc_offset = len(self.allocations) + self.allocations.append(instnode.cls.source.getint()) + res = (alloc_offset << FLAG_SHIFT) | FLAG_ALLOCATIONS memo[box] = res for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo, - cpu) + num = self.deal_with_box(node.source, nodes, liveboxes, memo) if isinstance(instnode.cls.source, FixedList): ld = instnode.cls.source assert isinstance(ld, FixedList) @@ -95,9 +94,14 @@ memo[box] = res liveboxes.append(box) for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo, - cpu) - self.setfields.append((res, ofs, num)) + num = self.deal_with_box(node.source, nodes, liveboxes, + memo) + if instnode.cls and isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + assert isinstance(ld, FixedList) + self.setitems.append((res, ld.arraydescr, ofs, num)) + else: + self.setfields.append((res, ofs, num)) else: res = (len(liveboxes) << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME memo[box] = res @@ -137,8 +141,6 @@ self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables - self.always_virtual = False # a flag that is set on objects - # passed around, that are virtuals stored on virtualizables def is_nonzero(self): return self.cls is not None or self.nonzero @@ -146,34 +148,31 @@ def is_zero(self): return self.const and not self.source.getptr_base() - def escape_if_startbox(self, memo, escape_self=True): + def escape_if_startbox(self, memo): if self in memo: return memo[self] = None if self.startbox: - if escape_self: - self.escaped = True - else: - self.always_virtual = True + self.escaped = True if not self.virtualized: for node in self.curfields.values(): node.escape_if_startbox(memo) else: for key, node in self.curfields.items(): - if self.vdesc is not None and not av_list_in(self.vdesc, key): - esc_self = True - else: - esc_self = False - node.escape_if_startbox(memo, esc_self) + if self.vdesc is not None and av_list_in(self.vdesc, key): + node.virtualized = True + if node.cls is None: + node.cls = InstanceNode(FixedClass(), const=True) + node.escape_if_startbox(memo) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: - if self.vdesc is not None and not av_list_in(self.vdesc, key): - esc_self = True - else: - esc_self = False - node.escape_if_startbox(memo, esc_self) + if self.vdesc is not None and av_list_in(self.vdesc, key): + node.virtualized = True + if node.cls is None: + node.cls = InstanceNode(FixedClass(), const=True) + node.escape_if_startbox(memo) def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) @@ -201,12 +200,9 @@ return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: + assert self is not other fields = [] - if self is other: - d = self.origfields.copy() - d.update(other.curfields) - else: - d = other.curfields + d = other.curfields lst = d.keys() sort_descrs(lst) for ofs in lst: @@ -240,18 +236,21 @@ sort_descrs(offsets) fields = [] for ofs in offsets: - if ofs in self.origfields and ofs in other.curfields: + if ofs in other.curfields: node = other.curfields[ofs] + if ofs not in self.origfields: + box = node.source.clonebox() + self.origfields[ofs] = InstanceNode(box, escaped=False) + self.origfields[ofs].cls = node.cls + nodes[box] = self.origfields[ofs] specnode = self.origfields[ofs].intersect(node, nodes) - elif ofs in self.origfields: + else: + # ofs in self.origfields: node = self.origfields[ofs] specnode = node.intersect(node, nodes) - else: - # ofs in other.curfields - node = other.curfields[ofs] - self.origfields[ofs] = InstanceNode(node.source.clonebox()) - specnode = NotSpecNode() fields.append((ofs, specnode)) + if isinstance(known_class, FixedList): + return VirtualizableListSpecNode(known_class, fields) return VirtualizableSpecNode(known_class, fields) def __repr__(self): @@ -522,7 +521,7 @@ op = op.clone() for box in old_boxes: indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo, self.cpu)) + liveboxes, memo)) rev_boxes = {} for i in range(len(liveboxes)): box = liveboxes[i] @@ -574,9 +573,16 @@ def optimize_getfield(self, instnode, ofs, box): assert isinstance(ofs, AbstractValue) - if instnode.virtual or instnode.virtualized: + if instnode.virtual: assert ofs in instnode.curfields return True # this means field is never actually + elif instnode.virtualized: + if ofs in instnode.curfields: + return True + # this means field comes from a virtualizable but is never + # written. Cool, simply make the result constant + self.nodes[box] = InstanceNode(box.constbox(), const=True) + return True elif ofs in instnode.cleanfields: self.nodes[box] = instnode.cleanfields[ofs] return True @@ -721,6 +727,7 @@ instnode = self.getnode(op.args[0]) # we know the result is constant if instnode is a virtual, # a constant, or known to be non-zero. + # XXX what about virtualizables? if instnode.virtual or instnode.const or instnode.is_nonzero(): box = op.result instnode = InstanceNode(box.constbox(), const=True) @@ -805,6 +812,8 @@ return True def match(self, old_operations): + import pdb + pdb.set_trace() old_mp = old_operations[0] jump_op = self.loop.operations[-1] assert jump_op.opnum == rop.JUMP @@ -826,12 +835,10 @@ old_specnode.adapt_to(new_instnode) class Chooser(object): - def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists, - prebuilt_objects): + def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists): self.boxes_from_frame = boxes_from_frame self.allocated_lists = allocated_lists self.allocated_boxes = allocated_boxes - self.prebuilt_objects = prebuilt_objects def box_from_index(self, index): ofs = index >> FLAG_SHIFT @@ -842,10 +849,8 @@ return self.allocated_boxes[ofs] elif where_from == FLAG_LIST_ALLOCATIONS: return self.allocated_lists[ofs] - elif where_from == FLAG_PREBULT_OBJECTS: - return self.prebuilt_objects[ofs] else: - assert 0, "I can't count to 4" + assert 0, "Should not happen" def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): allocated_boxes = [] @@ -867,8 +872,7 @@ listbox = metainterp.execute_and_record(rop.NEW_ARRAY, [sizebox], ad) allocated_lists.append(listbox) - chooser = Chooser(boxes_from_frame, allocated_boxes, allocated_lists, - storage.prebuilt_objects) + chooser = Chooser(boxes_from_frame, allocated_boxes, allocated_lists) for index_in_alloc, ofs, index_in_arglist in storage.setfields: fieldbox = chooser.box_from_index(index_in_arglist) box = chooser.box_from_index(index_in_alloc) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Mar 14 15:44:08 2009 @@ -139,7 +139,7 @@ subspecnode.adapt_to(instnode.curfields[ofs]) class VirtualizedSpecNode(SpecNodeWithFields): - + def expand_boxlist(self, instnode, newboxlist, start): newboxlist.append(instnode.source) SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) @@ -217,10 +217,44 @@ def equals(self, other): if not isinstance(other, VirtualizableSpecNode): return False + return SpecNodeWithFields.equals(self, other) + + def adapt_to(self, instnode): + instnode.virtualized = True + VirtualizedSpecNode.adapt_to(self, instnode) + +class VirtualizableListSpecNode(VirtualizedSpecNode): + + def equals(self, other): + if not isinstance(other, VirtualizableListSpecNode): + return False return SpecNodeWithFields.equals(self, other) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.resoperation import rop + from pypy.jit.metainterp.optimize import FixedList + from pypy.jit.metainterp.history import check_descr + + resultlist.append(valuebox) + cls = self.known_class + assert isinstance(cls, FixedList) + arraydescr = cls.arraydescr + check_descr(arraydescr) + for ofs, subspecnode in self.fields: + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ofs], arraydescr) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + + def adapt_to(self, instnode): + instnode.virtualized = True + VirtualizedSpecNode.adapt_to(self, instnode) class VirtualSpecNode(SpecNodeWithFields): + def adapt_to(self, instnode): + instnode.virtual = True + SpecNodeWithFields.adapt_to(self, instnode) + def mutate_nodes(self, instnode): SpecNodeWithFields.mutate_nodes(self, instnode) instnode.virtual = True @@ -240,7 +274,7 @@ def mutate_nodes(self, instnode): VirtualSpecNode.mutate_nodes(self, instnode) - instnode.known_length = self.known_length + instnode.cursize = self.known_length def equals(self, other): if not isinstance(other, VirtualFixedListSpecNode): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Sat Mar 14 15:44:08 2009 @@ -277,8 +277,6 @@ class BaseFrame(object): _virtualizable2_ = True - _always_virtual_ = ['x'] - def __init__(self, x): self.x = x @@ -335,11 +333,12 @@ node = frame.node subnode = node.node g(subnode) - frame.node = Node(SubNode(subnode.x + 1)) + frame.node.node = SubNode(subnode.x + 1) n -= 1 return n res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) + self.check_loops(getfield_gc=1) assert res == 0 def test_external_pass(self): @@ -421,7 +420,43 @@ self.check_loops(setarrayitem_gc=0) self.check_loop_count(3) assert res == 3 - + + def test_virtual_obj_on_always_virtual(self): + py.test.skip("XYz") + jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + _always_virtual_ = ['l'] + + def __init__(self, l): + self.l = l + + class Stuff(object): + def __init__(self, elem): + self.elem = elem + + def f(n): + frame = Frame([Stuff(3), Stuff(4)]) + s = 0 + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n, s=s) + jitdriver.jit_merge_point(frame=frame, n=n, s=s) + if n % 2: + s += frame.l[0].elem + frame.l[0] = Stuff(n) + else: + s += frame.l[1].elem + frame.l[1] = Stuff(n) + n -= 1 + return s + + res = self.meta_interp(f, [30], listops=True) + self.check_loops(getfield_gc=1) + assert res == f(30) + def test_external_read(self): py.test.skip("Fails") From fijal at codespeak.net Sat Mar 14 15:59:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Mar 2009 15:59:06 +0100 (CET) Subject: [pypy-svn] r62954 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090314145906.75E9216843A@codespeak.net> Author: fijal Date: Sat Mar 14 15:59:06 2009 New Revision: 62954 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: er, get rid of pdbs Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Mar 14 15:59:06 2009 @@ -33,9 +33,7 @@ return True class CancelInefficientLoop(Exception): - def __init__(self, *args): - import pdb - pdb.set_trace() + pass FLAG_ALLOCATIONS = 0x0 FLAG_LIST_ALLOCATIONS = 0x1 @@ -812,8 +810,6 @@ return True def match(self, old_operations): - import pdb - pdb.set_trace() old_mp = old_operations[0] jump_op = self.loop.operations[-1] assert jump_op.opnum == rop.JUMP From fijal at codespeak.net Sat Mar 14 16:00:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Mar 2009 16:00:35 +0100 (CET) Subject: [pypy-svn] r62955 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090314150035.B715516843A@codespeak.net> Author: fijal Date: Sat Mar 14 16:00:35 2009 New Revision: 62955 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Log: I *think* that we should reuse the loop in the case where items on lists are different. rationale is that we want to have a loop which later on fails with guard and generates a bridge. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Mar 14 16:00:35 2009 @@ -228,7 +228,7 @@ def equals(self, other): if not isinstance(other, VirtualizableListSpecNode): return False - return SpecNodeWithFields.equals(self, other) + return True def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop From fijal at codespeak.net Sat Mar 14 16:08:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Mar 2009 16:08:11 +0100 (CET) Subject: [pypy-svn] r62956 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090314150811.9FB4616843F@codespeak.net> Author: fijal Date: Sat Mar 14 16:08:11 2009 New Revision: 62956 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Log: of course that's the exact thing we cannot do Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Mar 14 16:08:11 2009 @@ -228,7 +228,7 @@ def equals(self, other): if not isinstance(other, VirtualizableListSpecNode): return False - return True + return SpecNodeWithFields.equals(self, other) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop From arigo at codespeak.net Sun Mar 15 12:08:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 15 Mar 2009 12:08:38 +0100 (CET) Subject: [pypy-svn] r62958 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090315110838.5FFE2168067@codespeak.net> Author: arigo Date: Sun Mar 15 12:08:36 2009 New Revision: 62958 Removed: pypy/branch/pyjitpl5/pypy/jit/backend/x86/executor.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Remove dead code. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 15 12:08:36 2009 @@ -14,7 +14,6 @@ from pypy.jit.backend.x86.assembler import Assembler386, WORD, RETURN from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname -from pypy.jit.backend.x86.executor import execute from pypy.jit.backend.x86.support import gc_malloc_fnaddr GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) From arigo at codespeak.net Sun Mar 15 12:58:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 15 Mar 2009 12:58:48 +0100 (CET) Subject: [pypy-svn] r62959 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090315115848.4755D168417@codespeak.net> Author: arigo Date: Sun Mar 15 12:58:46 2009 New Revision: 62959 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Minor cleanups. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py Sun Mar 15 12:58:46 2009 @@ -66,7 +66,6 @@ class MachineCodeDumper: enabled = True log_fd = -1 - sys_executable = None def _freeze_(self): # reset the machine_code_dumper global instance to its default state Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sun Mar 15 12:58:46 2009 @@ -644,7 +644,11 @@ @staticmethod def cast_int_to_adr(x): - return llmemory.cast_ptr_to_adr(rffi.cast(llmemory.GCREF, x)) + if we_are_translated(): + return rffi.cast(llmemory.Address, x) + else: + # indirect casting because the above doesn't work with ll2ctypes + return llmemory.cast_ptr_to_adr(rffi.cast(llmemory.GCREF, x)) def cast_gcref_to_int(self, x): return rffi.cast(lltype.Signed, x) @@ -652,10 +656,6 @@ def cast_int_to_gcref(self, x): return rffi.cast(llmemory.GCREF, x) -DEFINED_INT_VALUE = { - 'MALLOC_ZERO_FILLED': 1, # using Boehm for now - } - def uhex(x): if we_are_translated(): return hex(x) From arigo at codespeak.net Mon Mar 16 11:04:29 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 16 Mar 2009 11:04:29 +0100 (CET) Subject: [pypy-svn] r62964 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090316100429.6F38516850B@codespeak.net> Author: arigo Date: Mon Mar 16 11:04:27 2009 New Revision: 62964 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: A (failing) test for aliasing. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Mon Mar 16 11:04:27 2009 @@ -838,3 +838,33 @@ # return False -- as there was already a guard_class done on n1 ResOperation('jump', [], None), ]) + +# ____________________________________________________________ + +class P: + locals().update(A.__dict__) # :-) + thirdnode = lltype.malloc(NODE) + n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, thirdnode)) + f = BoxInt(0) # False + ops = [ + ResOperation('merge_point', [n1, n3], None), + ResOperation('getfield_gc', [n3], v, ofs_value), + ResOperation('setfield_gc', [n1, ConstInt(1)], None, ofs_value), + ResOperation('getfield_gc', [n3], v2, ofs_value), + ResOperation('int_eq', [v, v2], f), + ResOperation('guard_false', [f], None), + ResOperation('getfield_gc', [n1], n2, ofs_next), + ResOperation('jump', [n2, n3], None), + ] + ops[-3].liveboxes = [] + +def test_P_optimize_loop(): + spec = PerfectSpecializer(Loop(P.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + # Optimization should not remove any operation. + # If it does, then aliasing is not correctly detected. + # It is ok to reorder just the 'getfield_gc[n1], n2' operation, + # but the three remaining getfields/setfields *must* be in that order. + equaloplists(spec.loop.operations, P.ops) From fijal at codespeak.net Mon Mar 16 14:33:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 16 Mar 2009 14:33:04 +0100 (CET) Subject: [pypy-svn] r62968 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090316133304.A9B551683F7@codespeak.net> Author: fijal Date: Mon Mar 16 14:33:01 2009 New Revision: 62968 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: skip correctly failing tests. now we can at least run all of them Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Mon Mar 16 14:33:01 2009 @@ -859,6 +859,7 @@ ops[-3].liveboxes = [] def test_P_optimize_loop(): + py.test.skip("explodes") spec = PerfectSpecializer(Loop(P.ops)) spec.find_nodes() spec.intersect_input_and_output() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Mon Mar 16 14:33:01 2009 @@ -394,6 +394,7 @@ assert res == 2 def test_pass_always_virtual_to_bridge(self): + py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) @@ -406,11 +407,11 @@ self.l = l def f(n): - frame = Frame([1,2,3]) + frame = Frame([1,1,3]) while n > 0: jitdriver.can_enter_jit(frame=frame, n=n) jitdriver.jit_merge_point(frame=frame, n=n) - if n % 3: + if n % 2: n -= frame.l[0] else: n -= frame.l[1] @@ -418,11 +419,11 @@ res = self.meta_interp(f, [30], listops=True) self.check_loops(setarrayitem_gc=0) - self.check_loop_count(3) + self.check_loop_count(2) assert res == 3 def test_virtual_obj_on_always_virtual(self): - py.test.skip("XYz") + py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) @@ -454,9 +455,8 @@ return s res = self.meta_interp(f, [30], listops=True) - self.check_loops(getfield_gc=1) + self.check_loops(getfield_gc=0) assert res == f(30) - def test_external_read(self): py.test.skip("Fails") From arigo at codespeak.net Mon Mar 16 20:41:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 16 Mar 2009 20:41:22 +0100 (CET) Subject: [pypy-svn] r62976 - pypy/trunk/pypy/translator/c/src Message-ID: <20090316194122.48835168405@codespeak.net> Author: arigo Date: Mon Mar 16 20:41:21 2009 New Revision: 62976 Modified: pypy/trunk/pypy/translator/c/src/rtyper.h pypy/trunk/pypy/translator/c/src/support.h Log: Fix the failures -- seems that we really need these macros for now. Modified: pypy/trunk/pypy/translator/c/src/rtyper.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/rtyper.h (original) +++ pypy/trunk/pypy/translator/c/src/rtyper.h Mon Mar 16 20:41:21 2009 @@ -4,10 +4,13 @@ #include +/* Note that RPython strings are not 0-terminated! For debugging, + use PyString_FromRPyString or RPyString_AsCharP */ #define RPyString_Size(rps) ((rps)->rs_chars.length) +#define _RPyString_AsString(rps) ((rps)->rs_chars.items) #define RPyUnicode_Size(rpu) ((rpu)->ru_chars.length) -#define RPyUnicode_AsUnicode(rpu) ((rpu)->ru_chars.items) +#define _RPyUnicode_AsUnicode(rpu) ((rpu)->ru_chars.items) /* prototypes */ Modified: pypy/trunk/pypy/translator/c/src/support.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/support.h (original) +++ pypy/trunk/pypy/translator/c/src/support.h Mon Mar 16 20:41:21 2009 @@ -20,15 +20,16 @@ #define FAIL_ZER(msg) FAIL_EXCEPTION(PyExc_ZeroDivisionError, msg) #define CFAIL() RPyConvertExceptionFromCPython() -/* #define PyString_FromRPyString(rpystr) \ */ -/* PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr)) */ - -/* #define PyUnicode_FromRPyUnicode(rpystr) \ */ -/* PyUnicode_FromUnicode(RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) */ - -/* #define PyString_ToRPyString(s, rpystr) \ */ -/* memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \ */ -/* RPyString_Size(rpystr)) */ +/* the following macros are used by rpython/lltypesystem/rstr.py */ +#define PyString_FromRPyString(rpystr) \ + PyString_FromStringAndSize(_RPyString_AsString(rpystr), RPyString_Size(rpystr)) + +#define PyUnicode_FromRPyUnicode(rpystr) \ + PyUnicode_FromUnicode(_RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) + +#define PyString_ToRPyString(s, rpystr) \ + memcpy(_RPyString_AsString(rpystr), PyString_AS_STRING(s), \ + RPyString_Size(rpystr)) /* Extra checks can be enabled with the RPY_ASSERT or RPY_LL_ASSERT * macros. They differ in the level at which the tests are made. From fijal at codespeak.net Tue Mar 17 10:23:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Mar 2009 10:23:58 +0100 (CET) Subject: [pypy-svn] r62988 - pypy/trunk/pypy/translator/c Message-ID: <20090317092358.51F4A168453@codespeak.net> Author: fijal Date: Tue Mar 17 10:23:57 2009 New Revision: 62988 Modified: pypy/trunk/pypy/translator/c/genc.py Log: (arigo, fijal) Fix the segfault by keeping alive the whole ModuleWithCleanup by Wrapper Modified: pypy/trunk/pypy/translator/c/genc.py ============================================================================== --- pypy/trunk/pypy/translator/c/genc.py (original) +++ pypy/trunk/pypy/translator/c/genc.py Tue Mar 17 10:23:57 2009 @@ -265,12 +265,13 @@ def __getattr__(self, name): mod = self.__dict__['mod'] obj = getattr(mod, name) + parentself = self if callable(obj) and getattr(obj, '__module__', None) == mod.__name__: # The module must be kept alive with the function. # This wrapper avoids creating a cycle. class Wrapper: def __init__(self, obj): - self.mod = mod + self.myself = parentself self.func = obj def __call__(self, *args, **kwargs): return self.func(*args, **kwargs) From fijal at codespeak.net Tue Mar 17 10:34:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Mar 2009 10:34:52 +0100 (CET) Subject: [pypy-svn] r62989 - pypy/trunk/pypy/doc/config Message-ID: <20090317093452.127CF168443@codespeak.net> Author: fijal Date: Tue Mar 17 10:34:49 2009 New Revision: 62989 Added: pypy/trunk/pypy/doc/config/objspace.usemodules.pyexpat.txt (contents, props changed) Log: Option Added: pypy/trunk/pypy/doc/config/objspace.usemodules.pyexpat.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/config/objspace.usemodules.pyexpat.txt Tue Mar 17 10:34:49 2009 @@ -0,0 +1,2 @@ +Use (experimental) pyexpat module written in RPython, instead of CTypes +version which is used by default. From fijal at codespeak.net Tue Mar 17 11:06:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Mar 2009 11:06:03 +0100 (CET) Subject: [pypy-svn] r62990 - pypy/trunk/pypy Message-ID: <20090317100603.B6B86168419@codespeak.net> Author: fijal Date: Tue Mar 17 11:06:00 2009 New Revision: 62990 Modified: pypy/trunk/pypy/testrunner_cfg.py Log: Run x86 backend tests per-file Modified: pypy/trunk/pypy/testrunner_cfg.py ============================================================================== --- pypy/trunk/pypy/testrunner_cfg.py (original) +++ pypy/trunk/pypy/testrunner_cfg.py Tue Mar 17 11:06:00 2009 @@ -3,9 +3,10 @@ def collect_one_testdir(testdirs, reldir, tests): if (reldir.startswith('translator/c/') or reldir.startswith('rlib/test') or - reldir.startswith('rpython/memory/')): + reldir.startswith('rpython/memory/') or + reldir.startswith('jit/backend/x86')): testdirs.extend(tests) - else: + else: testdirs.append(reldir) From fijal at codespeak.net Tue Mar 17 11:07:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Mar 2009 11:07:35 +0100 (CET) Subject: [pypy-svn] r62991 - pypy/trunk/pypy/jit/metainterp/test Message-ID: <20090317100735.DDDCA168419@codespeak.net> Author: fijal Date: Tue Mar 17 11:07:35 2009 New Revision: 62991 Modified: pypy/trunk/pypy/jit/metainterp/test/test_send.py Log: temporarily skip this test Modified: pypy/trunk/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/trunk/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/trunk/pypy/jit/metainterp/test/test_send.py Tue Mar 17 11:07:35 2009 @@ -8,6 +8,7 @@ class SendTests: def test_green_send(self): + py.test.skip("fails") myjitdriver = JitDriver(greens = ['i'], reds = ['counter']) lst = ["123", "45"] def f(i): From fijal at codespeak.net Tue Mar 17 11:27:44 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Mar 2009 11:27:44 +0100 (CET) Subject: [pypy-svn] r62992 - in pypy/trunk/pypy/translator/jvm: . test Message-ID: <20090317102744.98112168445@codespeak.net> Author: fijal Date: Tue Mar 17 11:27:40 2009 New Revision: 62992 Removed: pypy/trunk/pypy/translator/jvm/platform.py pypy/trunk/pypy/translator/jvm/test/test_platform.py Log: unused file and a failing test From arigo at codespeak.net Tue Mar 17 13:30:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 17 Mar 2009 13:30:10 +0100 (CET) Subject: [pypy-svn] r62996 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090317123010.9678F168449@codespeak.net> Author: arigo Date: Tue Mar 17 13:30:07 2009 New Revision: 62996 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Minor cleanups and XXXs. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Tue Mar 17 13:30:07 2009 @@ -9,7 +9,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.jit.backend.x86 import symbolic -from pypy.jit.metainterp.resoperation import rop, opname +from pypy.jit.metainterp.resoperation import rop # esi edi and ebp can be added to this list, provided they're correctly # saved and restored @@ -754,7 +754,7 @@ ops += self.sync_var(v) self.reg_bindings = newcheckdict() if op.result is not None: - self.reg_bindings = {op.result: eax} + self.reg_bindings[op.result] = eax self.free_regs = [reg for reg in REGS if reg is not eax] return ops + [Perform(op, arglocs, eax)] else: @@ -812,6 +812,7 @@ op.result) def consider_oononnull(self, op, ignored): + XXX # "consider_oononnull = _consider_nullity" below argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) reg = self.try_allocate_reg(op.result) From afa at codespeak.net Tue Mar 17 16:23:21 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Mar 2009 16:23:21 +0100 (CET) Subject: [pypy-svn] r63001 - in pypy/trunk/pypy/annotation: . test Message-ID: <20090317152321.4B573168418@codespeak.net> Author: afa Date: Tue Mar 17 16:23:18 2009 New Revision: 63001 Modified: pypy/trunk/pypy/annotation/description.py pypy/trunk/pypy/annotation/test/test_annrpython.py Log: Allow MethodDescs to return the graph of their underlying function. This give better error messages when the translation fails because of a missing space.wrap() in some method in an interp_level class. Modified: pypy/trunk/pypy/annotation/description.py ============================================================================== --- pypy/trunk/pypy/annotation/description.py (original) +++ pypy/trunk/pypy/annotation/description.py Tue Mar 17 16:23:18 2009 @@ -701,6 +701,9 @@ self.selfclassdef, self.flags) + def getuniquegraph(self): + return self.funcdesc.getuniquegraph() + def pycall(self, schedule, args, s_previous_result): from pypy.annotation.model import SomeInstance if self.selfclassdef is None: Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/test/test_annrpython.py (original) +++ pypy/trunk/pypy/annotation/test/test_annrpython.py Tue Mar 17 16:23:18 2009 @@ -2402,6 +2402,7 @@ a.build_types(fun, []) a.annotate_helper_method(A, "helper", []) assert a.bookkeeper.getdesc(A.helper).getuniquegraph() + assert a.bookkeeper.getdesc(A().helper).getuniquegraph() def test_chr_out_of_bounds(self): def g(n, max): From tverwaes at codespeak.net Tue Mar 17 16:35:22 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 16:35:22 +0100 (CET) Subject: [pypy-svn] r63002 - in pypy/trunk/pypy/lang/gameboy: . profiling Message-ID: <20090317153522.CFB8A168442@codespeak.net> Author: tverwaes Date: Tue Mar 17 16:35:20 2009 New Revision: 63002 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Log: changing profiling implementation to profile everything Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Tue Mar 17 16:35:20 2009 @@ -22,6 +22,8 @@ else: delay = time.sleep +FPS = 1<<6 # About 1<<6 to make sure we have a clean distrubution of about + # 1<<6 frames per second from pypy.rlib.objectmodel import specialize @@ -65,13 +67,11 @@ return 0 def emulate_cycle(self): - X = 1<<6 # About 1<<6 to make sure we have a clean distrubution of about - # 1<<6 frames per second self.handle_events() - # Come back to this cycle every 1/X seconds - self.emulate(constants.GAMEBOY_CLOCK / X) + # Come back to this cycle every 1/FPS seconds + self.emulate(constants.GAMEBOY_CLOCK / FPS) spent = int(time.time()) - self.sync_time - left = int(1000.0/X) + self.penalty - spent + left = int(1000.0/FPS) + self.penalty - spent if left > 0: delay(left) self.penalty = 0 Modified: pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Tue Mar 17 16:35:20 2009 @@ -1,48 +1,37 @@ #!/usr/bin/env python -from __future__ import generators -from pypy.lang.gameboy.ram import iMemory -from pypy.lang.gameboy.gameboy_implementation import * -from pypy.lang.gameboy.profiling.profiling_cpu import ProfilingCPU -from pypy.lang.gameboy.debug import debug -from pypy.lang.gameboy.debug.debug_socket_memory import * +from pypy.lang.gameboy.gameboy import GameBoy +from pypy.lang.gameboy.joypad import JoypadDriver +from pypy.lang.gameboy.video import VideoDriver +from pypy.lang.gameboy.sound import SoundDriver +from pypy.lang.gameboy.timer import Clock +from pypy.lang.gameboy import constants + +from pypy.rlib.objectmodel import specialize # GAMEBOY ---------------------------------------------------------------------- -class GameBoyProfilingImplementation(GameBoyImplementation): - - def __init__(self, op_codes): - GameBoyImplementation.__init__(self) - self.op_codes = op_codes - self.cycleLimit = cycleLimit - self.cpu = ProfilingCPU(self.interrupt, self) - self.cpu.cycle_limit = cycleLimit - - def handle_execution_error(self): - self.is_running = False - debug.print_results() - +FPS = 1 << 6 -# CUSTOM DRIVER IMPLEMENTATIONS currently not used ============================= - +class GameBoyProfiler(GameBoy): -# VIDEO DRIVER ----------------------------------------------------------------- - -class VideoDriverDebugImplementation(VideoDriverImplementation): - pass - - -# JOYPAD DRIVER ---------------------------------------------------------------- + def __init__(self): + GameBoy.__init__(self) + self.is_running = False -class JoypadDriverDebugImplementation(JoypadDriverImplementation): - pass - - -# SOUND DRIVER ----------------------------------------------------------------- -class SoundDriverDebugImplementation(SoundDriverImplementation): - pass - + def create_drivers(self): + self.clock = Clock() + self.joypad_driver = JoypadDriver() + self.video_driver = VideoDriver() + self.sound_driver = SoundDriver() + + def mainLoop(self): + self.reset() + self.is_running = True + for i in range(600 * FPS): + self.emulate_cycle() -# ============================================================================== + def emulate_cycle(self): + self.emulate(constants.GAMEBOY_CLOCK / FPS) From tverwaes at codespeak.net Tue Mar 17 16:35:48 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 16:35:48 +0100 (CET) Subject: [pypy-svn] r63003 - pypy/trunk/pypy/translator/goal Message-ID: <20090317153548.D733D168453@codespeak.net> Author: tverwaes Date: Tue Mar 17 16:35:48 2009 New Revision: 63003 Added: pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py Log: adding profiling target which profiles everything Added: pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py Tue Mar 17 16:35:48 2009 @@ -0,0 +1,38 @@ +#!/usr/bin/env python +import os, py, pdb, sys, time +from pypy.lang.gameboy.profiling.gameboy_profiling_implementation import GameBoyProfiler + + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" + +def entry_point(argv=None): + if argv is not None and len(argv) > 1: + filename = argv[1] + else: + pos = str(9) + filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" + gameBoy = GameBoyProfiler() + try: + gameBoy.load_cartridge_file(str(filename)) + except: + gameBoy.load_cartridge_file(str(filename), verify=False) + + start = time.time() + gameBoy.mainLoop() + print time.time() - start + + return 0 + + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None + +def test_target(): + entry_point(sys.argv) + +# STARTPOINT =================================================================== + +if __name__ == '__main__': + test_target() From tverwaes at codespeak.net Tue Mar 17 16:47:39 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 16:47:39 +0100 (CET) Subject: [pypy-svn] r63004 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090317154739.ED2D0168453@codespeak.net> Author: tverwaes Date: Tue Mar 17 16:47:37 2009 New Revision: 63004 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/video.py Log: adding FastDoubleRegisters for sp and pc. now runs twice as fast :) Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 17 16:47:37 2009 @@ -1,7 +1,8 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt -from pypy.lang.gameboy.cpu_register import Register, DoubleRegister, \ +from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ + FastDoubleRegister, \ FlagRegister, ImmediatePseudoRegister # --------------------------------------------------------------------------- @@ -50,8 +51,8 @@ self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_PC) - self.sp = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_SP) + self.pc = FastDoubleRegister(self, reset_value=constants.RESET_PC) + self.sp = FastDoubleRegister(self, reset_value=constants.RESET_SP) self.a = Register(self, constants.RESET_A) self.flag = FlagRegister(self, constants.RESET_F) Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Tue Mar 17 16:47:37 2009 @@ -33,19 +33,68 @@ #------------------------------------------------------------------------------ -class DoubleRegister(AbstractRegister): +class AbstractDoubleRegister(AbstractRegister): - def __init__(self, cpu, hi, lo, reset_value=0): - #assert isinstance(cpu, CPU) - #assert isinstance(lo, Register) - #assert isinstance(hi, Register) + def __init__(self, cpu, reset_value=0): self.cpu = cpu + self.reset_value = reset_value + + def set(self, value, use_cycles=True): + # 1 Cycle + raise Exception("Not Implemented") + + def set_hi_lo(self, hi, lo, use_cycles=True): + # 2 Cycles + raise Exception("Not Implemented") + + def reset(self): + self.set(self.reset_value, use_cycles=False) + + def set_hi(self, hi=0, use_cycles=True): + # 1 Cycle + raise Exception("Not Implemented") + + def set_lo(self, lo=0, use_cycles=True): + # 1 Cycle + raise Exception("Not Implemented") + + def get(self, use_cycles=True): + # 0 Cycles TODO: Check entanglement of cycles in CPU class. + raise Exception("Not Implemented") + + def get_hi(self, use_cycles=True): + # 0 Cycles + raise Exception("Not Implemented") + + def get_lo(self, use_cycles=True): + # 0 Cycles + raise Exception("Not Implemented") + + def inc(self, use_cycles=True): + self.add(1, use_cycles) + if use_cycles: + self.cpu.cycles += 1 + + def dec(self, use_cycles=True): + self.add(-1, use_cycles) + if use_cycles: + self.cpu.cycles += 1 + + def add(self, value, use_cycles=True): + self.set(self.get(use_cycles) + value, use_cycles=use_cycles) + if use_cycles: + self.cpu.cycles -= 2 + + + +class DoubleRegister(AbstractDoubleRegister): + + def __init__(self, cpu, hi, lo, reset_value=0): + AbstractDoubleRegister.__init__(self, cpu, reset_value) self.hi = hi self.lo = lo - self.reset_value = reset_value def set(self, value, use_cycles=True): - # previous = self.get(False) value = value & 0xFFFF self.set_hi(value >> 8, use_cycles) self.set_lo(value & 0xFF, use_cycles) @@ -56,9 +105,6 @@ self.set_hi(hi, use_cycles) self.set_lo(lo, use_cycles) - def reset(self): - self.set(self.reset_value, use_cycles=False) - def set_hi(self, hi=0, use_cycles=True): self.hi.set(hi, use_cycles) @@ -74,22 +120,45 @@ def get_lo(self, use_cycles=True): return self.lo.get(use_cycles) - def inc(self, use_cycles=True): - self.set(self.get(use_cycles) +1, use_cycles=use_cycles) + +class FastDoubleRegister(AbstractDoubleRegister): + + def __init__(self, cpu, reset_value=0): + AbstractDoubleRegister.__init__(self, cpu, reset_value) + self.value = 0x0000 + + def set(self, value, use_cycles=True): + self.value = value & 0xFFFF if use_cycles: self.cpu.cycles -= 1 - - def dec(self, use_cycles=True): - self.set(self.get(use_cycles) - 1, use_cycles=use_cycles) + + def set_hi_lo(self, hi, lo, use_cycles=True): + hi &= 0xFF + lo &= 0xFF + self.set((hi << 8) + lo, use_cycles) if use_cycles: self.cpu.cycles -= 1 - - def add(self, value, use_cycles=True): - self.set(self.get(use_cycles) + value, use_cycles=use_cycles) - if use_cycles: - self.cpu.cycles -= 2 + def set_hi(self, hi=0, use_cycles=True): + self.set_hi_lo(hi, self.get_lo(False), use_cycles) + if use_cycles: + self.cpu.cycles += 1 + def set_lo(self, lo=0, use_cycles=True): + self.set_hi_lo(self.get_hi(False), lo, use_cycles) + if use_cycles: + self.cpu.cycles += 1 + + def get(self, use_cycles=True): + return self.value + + def get_hi(self, use_cycles=True): + return (self.value >> 8) + + def get_lo(self, use_cycles=True): + return (self.value & 0xFF) + + # ------------------------------------------------------------------------------ class ImmediatePseudoRegister(Register): Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py Tue Mar 17 16:47:37 2009 @@ -161,4 +161,108 @@ assert register.get() == value+1; register.reset() assert register.get() == value - \ No newline at end of file + +# ------------------------------------------------------------ +# TEST FAST DOUBLE REGISTER + +def test_fast_double_register_constructor(): + cpu = get_cpu() + register = FastDoubleRegister(cpu) + assert register.get() == 0 + assert register.get_hi() == 0 + assert register.get_lo() == 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.get_hi() == reg1.get() + assert register.get_lo() == reg2.get() + +def test_fast_double_register(): + cpu = get_cpu() + register = FastDoubleRegister(cpu) + value = 0x1234 + oldCycles = register.cpu.cycles + register.set(value) + assert oldCycles-register.cpu.cycles == 1 + assert register.get() == value + +def test_fast_double_register_bounds(): + cpu = get_cpu() + register = FastDoubleRegister(cpu) + value = 0xFFFF1234 + register.set(value) + assert register.get() == 0x1234 + register.set(0) + assert register.get() == 0 + +def test_fast_double_register_hilo(): + cpu = get_cpu() + register = FastDoubleRegister(cpu) + value = 0x1234 + valueHi = 0x12 + valueLo = 0x34 + oldCycles = register.cpu.cycles + register.set_hi_lo(valueHi, valueLo) + assert oldCycles-register.cpu.cycles == 2 + assert register.get_hi() == valueHi + assert register.get_lo() == valueLo + assert register.get() == value + + valueHi = 0x56 + oldCycles = register.cpu.cycles + register.set_hi(valueHi) + assert oldCycles-register.cpu.cycles == 1 + assert register.get_hi() == valueHi + assert register.get_lo() == valueLo + + valueLo = 0x78 + oldCycles = register.cpu.cycles + register.set_lo(valueLo) + assert oldCycles-register.cpu.cycles == 1 + assert register.get_hi() == valueHi + assert register.get_lo() == valueLo + + +def test_fast_double_register_methods(): + value = 0x1234 + cpu = get_cpu() + register = FastDoubleRegister(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_fast_double_register_reset(): + value = 0x1234; + cpu = get_cpu() + register = FastDoubleRegister(cpu, reset_value = value) + register.set(value+1) + assert register.get() == value+1; + register.reset() + assert register.get() == value + Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Tue Mar 17 16:47:37 2009 @@ -39,7 +39,6 @@ assert video.background.scroll_y == 0 assert video.window.x == 0 assert video.window.y == 0 - assert video.window.line_y == 0 assert video.background_palette == 0xFC assert video.object_palette_0 == 0xFF assert video.object_palette_1 == 0xFF @@ -181,7 +180,8 @@ video.write(0xFF40, 0x80+0x20) assert video.control.read() == 0x80+0x20 - assert video.window.line_y == 144 + # assert video.window.line_y == 144 # We don't jump, we just adjust and + # # start drawing where we are. def test_control_reset1(): video = get_video() Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Tue Mar 17 16:47:37 2009 @@ -468,6 +468,8 @@ window.draw_clean_line(self.line) def draw_line(self): + # XXX We should check if this is necessary for each line. + self.update_palette() self.draw_window(self.background, self.line_y, self.line) self.draw_window(self.window, self.line_y, self.line) self.draw_sprites(self.line_y, self.line) @@ -506,7 +508,6 @@ self.shown_sprites[highest], self.shown_sprites[index] def send_pixels_line_to_driver(self): - self.update_palette() for x in range(0, GAMEBOY_SCREEN_WIDTH): color = self.palette[self.line[SPRITE_SIZE + x]] self.driver.draw_gb_pixel(x, self.line_y, color) From tverwaes at codespeak.net Tue Mar 17 17:26:35 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 17:26:35 +0100 (CET) Subject: [pypy-svn] r63005 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090317162635.7BABA168449@codespeak.net> Author: tverwaes Date: Tue Mar 17 17:26:31 2009 New Revision: 63005 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: more optimizations. directly inc/dec/add fastdoubleregister and we don't use debug vars when being translated. Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 17 17:26:31 2009 @@ -1,4 +1,4 @@ - +from pypy.rlib.objectmodel import we_are_translated from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ @@ -66,9 +66,10 @@ self.ime = False self.halted = False self.cycles = 0 - self.instruction_counter = 0 - self.last_op_code = -1 - self.last_fetch_execute_op_code = -1 + if not we_are_translated(): + self.instruction_counter = 0 + self.last_op_code = -1 + self.last_fetch_execute_op_code = -1 def reset_registers(self): self.a.reset() @@ -204,13 +205,15 @@ def fetch_execute(self): op_code = self.fetch() - self.last_fetch_execute_op_code = op_code + if not we_are_translated(): + self.last_fetch_execute_op_code = op_code FETCH_EXECUTE_OP_CODES[op_code](self) def execute(self, op_code): - self.instruction_counter += 1 - self.last_op_code = op_code + if not we_are_translated(): + self.instruction_counter += 1 + self.last_op_code = op_code OP_CODES[op_code](self) Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Tue Mar 17 17:26:31 2009 @@ -86,7 +86,6 @@ self.cpu.cycles -= 2 - class DoubleRegister(AbstractDoubleRegister): def __init__(self, cpu, hi, lo, reset_value=0): @@ -158,6 +157,23 @@ def get_lo(self, use_cycles=True): return (self.value & 0xFF) + def inc(self, use_cycles=True): + self.value += 1 + self.value &= 0xFFFF + if use_cycles: + self.cpu.cycles -= 2 + + def dec(self, use_cycles=True): + self.value -= 1 + self.value &= 0xFFFF + if use_cycles: + self.cpu.cycles -= 2 + + def add(self, value, use_cycles=True): + self.value += value + self.value &= 0xFFFF + if use_cycles: + self.cpu.cycles -= 3 # ------------------------------------------------------------------------------ From tverwaes at codespeak.net Tue Mar 17 17:45:16 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 17:45:16 +0100 (CET) Subject: [pypy-svn] r63006 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090317164516.B8ED316840E@codespeak.net> Author: tverwaes Date: Tue Mar 17 17:45:15 2009 New Revision: 63006 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: optimizing by specializing on use_cycles. highlights bug in malloc_removal Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 17 17:45:15 2009 @@ -1,4 +1,4 @@ -from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ @@ -236,6 +236,7 @@ self.memory.write(address, data) self.cycles -= 2 + @specialize.arg(-1) def fetch(self, use_cycles=True): # Fetching 1 cycle if use_cycles: @@ -256,16 +257,19 @@ def fetch_double_register(self, register): self.double_register_inverse_call(CPUFetchCaller(self), register) + @specialize.arg(-1) def push(self, data, use_cycles=True): # Stack, 2 cycles self.sp.dec(use_cycles) # 2 cycles self.memory.write(self.sp.get(use_cycles), data) + @specialize.arg(-1) def push_double_register(self, register, use_cycles=True): # PUSH rr 4 cycles self.push(register.get_hi(), use_cycles) # 2 cycles self.push(register.get_lo(), use_cycles) # 2 cycles + @specialize.arg(-1) def pop(self, use_cycles=True): # 1 cycle data = self.memory.read(self.sp.get()) @@ -283,6 +287,7 @@ register.set_hi_lo(a, b) # 2 cycles self.cycles += 1 + @specialize.arg(-1) def call(self, address, use_cycles=True): # 4 cycles self.push_double_register(self.pc, use_cycles) @@ -740,9 +745,11 @@ # Call Wrappers -------------------------------------------------------------- class CallWrapper(object): + @specialize.arg(-1) def get(self, use_cycles=True): raise Exception("called CallWrapper.get") + @specialize.arg(-1) def set(self, value, use_cycles=True): raise Exception("called CallWrapper.set") @@ -750,9 +757,11 @@ def __init__(self, number): self.number = number + @specialize.arg(-1) def get(self, use_cycles=True): return self.number + @specialize.arg(-1) def set(self, value, use_cycles=True): raise Exception("called CallWrapper.set") @@ -760,9 +769,11 @@ def __init__(self, register): self.register = register + @specialize.arg(-1) def get(self, use_cycles=True): return self.register.get(use_cycles) + @specialize.arg(-1) def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) @@ -771,9 +782,11 @@ def __init__(self, register): self.register = register + @specialize.arg(-1) def get(self, use_cycles=True): return self.register.get(use_cycles) + @specialize.arg(-1) def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) @@ -782,6 +795,7 @@ def __init__(self, cpu): self.cpu = cpu + @specialize.arg(-1) def get(self, use_cycles=True): return self.cpu.pop(use_cycles) @@ -790,6 +804,7 @@ def __init__(self, cpu): self.cpu = cpu + @specialize.arg(-1) def get(self, use_cycles=True): return self.cpu.fetch(use_cycles) Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Tue Mar 17 17:45:15 2009 @@ -1,7 +1,8 @@ - +from pypy.rlib.objectmodel import specialize # --------------------------------------------------------------------------- class AbstractRegister(object): + @specialize.arg(-1) def get(self, use_cycles=True): return 0xFF @@ -17,17 +18,21 @@ def reset(self): self.value = self.reset_value + @specialize.arg(-1) def set(self, value, use_cycles=True): self.value = value & 0xFF if use_cycles: self.cpu.cycles -= 1 + @specialize.arg(-1) def get(self, use_cycles=True): return self.value + @specialize.arg(-1) def add(self, value, use_cycles=True): self.set(self.get(use_cycles)+value, use_cycles) + @specialize.arg(-1) def sub(self, value, use_cycles=True): self.set(self.get(use_cycles)-value, use_cycles) @@ -39,10 +44,12 @@ self.cpu = cpu self.reset_value = reset_value + @specialize.arg(-1) def set(self, value, use_cycles=True): # 1 Cycle raise Exception("Not Implemented") + @specialize.arg(-1) def set_hi_lo(self, hi, lo, use_cycles=True): # 2 Cycles raise Exception("Not Implemented") @@ -50,36 +57,44 @@ def reset(self): self.set(self.reset_value, use_cycles=False) + @specialize.arg(-1) def set_hi(self, hi=0, use_cycles=True): # 1 Cycle raise Exception("Not Implemented") + @specialize.arg(-1) def set_lo(self, lo=0, use_cycles=True): # 1 Cycle raise Exception("Not Implemented") + @specialize.arg(-1) def get(self, use_cycles=True): # 0 Cycles TODO: Check entanglement of cycles in CPU class. raise Exception("Not Implemented") + @specialize.arg(-1) def get_hi(self, use_cycles=True): # 0 Cycles raise Exception("Not Implemented") + @specialize.arg(-1) def get_lo(self, use_cycles=True): # 0 Cycles raise Exception("Not Implemented") + @specialize.arg(-1) def inc(self, use_cycles=True): self.add(1, use_cycles) if use_cycles: self.cpu.cycles += 1 + @specialize.arg(-1) def dec(self, use_cycles=True): self.add(-1, use_cycles) if use_cycles: self.cpu.cycles += 1 + @specialize.arg(-1) def add(self, value, use_cycles=True): self.set(self.get(use_cycles) + value, use_cycles=use_cycles) if use_cycles: @@ -93,6 +108,7 @@ self.hi = hi self.lo = lo + @specialize.arg(-1) def set(self, value, use_cycles=True): value = value & 0xFFFF self.set_hi(value >> 8, use_cycles) @@ -100,22 +116,28 @@ if use_cycles: self.cpu.cycles += 1 + @specialize.arg(-1) def set_hi_lo(self, hi, lo, use_cycles=True): self.set_hi(hi, use_cycles) self.set_lo(lo, use_cycles) + @specialize.arg(-1) def set_hi(self, hi=0, use_cycles=True): self.hi.set(hi, use_cycles) + @specialize.arg(-1) def set_lo(self, lo=0, use_cycles=True): self.lo.set(lo, use_cycles) + @specialize.arg(-1) def get(self, use_cycles=True): return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles) + @specialize.arg(-1) def get_hi(self, use_cycles=True): return self.hi.get(use_cycles) + @specialize.arg(-1) def get_lo(self, use_cycles=True): return self.lo.get(use_cycles) @@ -126,11 +148,13 @@ AbstractDoubleRegister.__init__(self, cpu, reset_value) self.value = 0x0000 + @specialize.arg(-1) def set(self, value, use_cycles=True): self.value = value & 0xFFFF if use_cycles: self.cpu.cycles -= 1 + @specialize.arg(-1) def set_hi_lo(self, hi, lo, use_cycles=True): hi &= 0xFF lo &= 0xFF @@ -138,37 +162,45 @@ if use_cycles: self.cpu.cycles -= 1 + @specialize.arg(-1) def set_hi(self, hi=0, use_cycles=True): self.set_hi_lo(hi, self.get_lo(False), use_cycles) if use_cycles: self.cpu.cycles += 1 + @specialize.arg(-1) def set_lo(self, lo=0, use_cycles=True): self.set_hi_lo(self.get_hi(False), lo, use_cycles) if use_cycles: self.cpu.cycles += 1 + @specialize.arg(-1) def get(self, use_cycles=True): return self.value + @specialize.arg(-1) def get_hi(self, use_cycles=True): return (self.value >> 8) + @specialize.arg(-1) def get_lo(self, use_cycles=True): return (self.value & 0xFF) + @specialize.arg(-1) def inc(self, use_cycles=True): self.value += 1 self.value &= 0xFFFF if use_cycles: self.cpu.cycles -= 2 + @specialize.arg(-1) def dec(self, use_cycles=True): self.value -= 1 self.value &= 0xFFFF if use_cycles: self.cpu.cycles -= 2 + @specialize.arg(-1) def add(self, value, use_cycles=True): self.value += value self.value &= 0xFFFF @@ -179,21 +211,23 @@ class ImmediatePseudoRegister(Register): - def __init__(self, cpu, hl): - #assert isinstance(cpu, CPU) - self.cpu = cpu - self.hl = hl - - def set(self, value, use_cycles=True): - self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0 - if not use_cycles: - self.cpu.cycles += 2 - - def get(self, use_cycles=True): - if not use_cycles: - self.cpu.cycles += 1 - result = self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 - return result + def __init__(self, cpu, hl): + #assert isinstance(cpu, CPU) + self.cpu = cpu + self.hl = hl + + @specialize.arg(-1) + def set(self, value, use_cycles=True): + self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0 + if not use_cycles: + self.cpu.cycles += 2 + + @specialize.arg(-1) + def get(self, use_cycles=True): + if not use_cycles: + self.cpu.cycles += 1 + result = self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 + return result # ------------------------------------------------------------------------------ @@ -259,6 +293,7 @@ self.s_flag = False self.lower = 0x00 + @specialize.arg(-1) def get(self, use_cycles=True): value = 0 value += (int(self.is_carry) << 4) @@ -267,6 +302,7 @@ value += (int(self.is_zero) << 7) return value + self.lower + @specialize.arg(-1) def set(self, value, use_cycles=True): self.is_carry = bool(value & (1 << 4)) self.is_half_carry = bool(value & (1 << 5)) From arigo at codespeak.net Tue Mar 17 18:03:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 17 Mar 2009 18:03:17 +0100 (CET) Subject: [pypy-svn] r63007 - pypy/trunk/pypy/translator/backendopt Message-ID: <20090317170317.A39C1168402@codespeak.net> Author: arigo Date: Tue Mar 17 18:03:16 2009 New Revision: 63007 Modified: pypy/trunk/pypy/translator/backendopt/malloc.py Log: A merge from the oo-jit branch. Modified: pypy/trunk/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/malloc.py (original) +++ pypy/trunk/pypy/translator/backendopt/malloc.py Tue Mar 17 18:03:16 2009 @@ -552,6 +552,7 @@ FIELD_ACCESS = dict.fromkeys(["oogetfield", "oosetfield", "oononnull", + "ooisnull", #"oois", # ??? #"instanceof", # ??? ]) @@ -614,10 +615,10 @@ # equivalent. We can, and indeed must, use the same # flattened list of variables for both, as a "setfield" # via one pointer must be reflected in the other. - elif op.opname == "oononnull": + elif op.opname in ("ooisnull", "oononnull"): # we know the pointer is not NULL if it comes from # a successful malloc - c = Constant(True, lltype.Bool) + c = Constant(op.opname == "oononnull", lltype.Bool) newop = SpaceOperation('same_as', [c], op.result) self.newops.append(newop) else: From arigo at codespeak.net Tue Mar 17 18:26:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 17 Mar 2009 18:26:38 +0100 (CET) Subject: [pypy-svn] r63008 - in pypy/trunk/pypy/translator/backendopt: . test Message-ID: <20090317172638.E857216846D@codespeak.net> Author: arigo Date: Tue Mar 17 18:26:36 2009 New Revision: 63008 Modified: pypy/trunk/pypy/translator/backendopt/malloc.py pypy/trunk/pypy/translator/backendopt/test/test_malloc.py Log: Finally fix this test, as targetgbimplementation now shows the same problem. Modified: pypy/trunk/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/malloc.py (original) +++ pypy/trunk/pypy/translator/backendopt/malloc.py Tue Mar 17 18:26:36 2009 @@ -460,12 +460,21 @@ pass return S, fldname + def handle_unreachable(self, v_result): + from pypy.rpython.lltypesystem.rstr import string_repr + msg = "unreachable operation (from malloc.py)" + ll_msg = string_repr.convert_const(msg) + c_msg = Constant(ll_msg, lltype.typeOf(ll_msg)) + return SpaceOperation("debug_fatalerror", [c_msg], v_result) + def flowin_op(self, op, vars, newvarsmap): if op.opname in ("getfield", "getarrayitem"): S = op.args[0].concretetype.TO fldname = op.args[1].value key = self.key_for_field_access(S, fldname) - if key in self.accessed_substructs: + if key not in newvarsmap: + newop = self.handle_unreachable(op.result) + elif key in self.accessed_substructs: c_name = Constant('data', lltype.Void) newop = SpaceOperation("getfield", [newvarsmap[key], c_name], @@ -480,8 +489,10 @@ S = op.args[0].concretetype.TO fldname = op.args[1].value key = self.key_for_field_access(S, fldname) - assert key in newvarsmap - if key in self.accessed_substructs: + if key not in newvarsmap: + newop = self.handle_unreachable(op.result) + self.newops.append(newop) + elif key in self.accessed_substructs: c_name = Constant('data', lltype.Void) newop = SpaceOperation("setfield", [newvarsmap[key], c_name, op.args[2]], @@ -516,11 +527,15 @@ opname = "direct_fieldptr" else: opname = "getsubstruct" - v = newvarsmap[S, fldname] - cname = Constant('data', lltype.Void) - newop = SpaceOperation(opname, - [v, cname], - op.result) + try: + v = newvarsmap[S, fldname] + except KeyError: + newop = self.handle_unreachable(op.result) + else: + cname = Constant('data', lltype.Void) + newop = SpaceOperation(opname, + [v, cname], + op.result) self.newops.append(newop) elif op.opname in ("ptr_iszero", "ptr_nonzero"): # we know the pointer is not NULL if it comes from Modified: pypy/trunk/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/trunk/pypy/translator/backendopt/test/test_malloc.py Tue Mar 17 18:26:36 2009 @@ -384,7 +384,6 @@ graph = self.check(f, [int], [42], 42) def test_bogus_cast_pointer(self): - py.test.skip("XXX fix me") S = lltype.GcStruct("S", ('x', lltype.Signed)) T = lltype.GcStruct("T", ('s', S), ('y', lltype.Signed)) def f(x): From arigo at codespeak.net Tue Mar 17 18:50:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 17 Mar 2009 18:50:44 +0100 (CET) Subject: [pypy-svn] r63009 - pypy/trunk/pypy/translator/backendopt/test Message-ID: <20090317175044.E51BF16802E@codespeak.net> Author: arigo Date: Tue Mar 17 18:50:43 2009 New Revision: 63009 Modified: pypy/trunk/pypy/translator/backendopt/test/test_malloc.py Log: Make the test more general by rewriting it without lltypes. Couldn't get a failure on ootype, though, because oosend is not inlined so far. Modified: pypy/trunk/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/trunk/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/trunk/pypy/translator/backendopt/test/test_malloc.py Tue Mar 17 18:50:43 2009 @@ -1,6 +1,5 @@ import py from pypy.translator.backendopt.malloc import LLTypeMallocRemover, OOTypeMallocRemover -from pypy.translator.backendopt.inline import inline_function from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.translator import TranslationContext, graphof from pypy.translator import simplify @@ -36,12 +35,16 @@ assert count2 == 0 # number of calls left check_malloc_removed = classmethod(check_malloc_removed) - def check(self, fn, signature, args, expected_result, must_be_removed=True): + def check(self, fn, signature, args, expected_result, must_be_removed=True, + inline=None): remover = self.MallocRemover() t = TranslationContext() t.buildannotator().build_types(fn, signature) t.buildrtyper(type_system=self.type_system).specialize() graph = graphof(t, fn) + if inline is not None: + from pypy.translator.backendopt.inline import auto_inline_graphs + auto_inline_graphs(t, t.graphs, inline) if option.view: t.view() # to detect missing keepalives and broken intermediate graphs, @@ -129,6 +132,26 @@ return a1.x self.check(fn6, [int], [1], 12, must_be_removed=False) + def test_bogus_cast_pointer(self): + class S: + pass + class T(S): + def f(self): + self.y += 1 + def f(x): + T().y = 5 + s = S() + s.x = 123 + if x < 0: + s.f() + return s.x + graph = self.check(f, [int], [5], 123, inline=20) + found_operations = {} + for block in graph.iterblocks(): + for op in block.operations: + found_operations[op.opname] = True + assert 'debug_fatalerror' in found_operations + class TestLLTypeMallocRemoval(BaseMallocRemovalTest): @@ -383,18 +406,6 @@ return u[0].s.x graph = self.check(f, [int], [42], 42) - def test_bogus_cast_pointer(self): - S = lltype.GcStruct("S", ('x', lltype.Signed)) - T = lltype.GcStruct("T", ('s', S), ('y', lltype.Signed)) - def f(x): - s = lltype.malloc(S) - s.x = 123 - if x < 0: - t = lltype.cast_pointer(lltype.Ptr(T), s) - t.y += 1 - return s.x - graph = self.check(f, [int], [5], 123) - class TestOOTypeMallocRemoval(BaseMallocRemovalTest): type_system = 'ootype' @@ -422,4 +433,7 @@ # is turned into an oosend which prevents malloc removal to # work unless we inline first. See test_classattr in # test_inline.py - pass + py.test.skip("oosend prevents malloc removal") + + def test_bogus_cast_pointer(self): + py.test.skip("oosend prevents malloc removal") From tverwaes at codespeak.net Tue Mar 17 18:55:20 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 18:55:20 +0100 (CET) Subject: [pypy-svn] r63010 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090317175520.899FA168453@codespeak.net> Author: tverwaes Date: Tue Mar 17 18:55:20 2009 New Revision: 63010 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py Log: some small refactorings Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 17 18:55:20 2009 @@ -325,7 +325,7 @@ self.flag.partial_reset(keep_is_zero=True) self.flag.is_half_carry = (((added ^ self.hl.get() ^ data) & 0x1000) != 0) self.flag.is_carry = (added >= 0x10000 or added < 0) - self.hl.set(added & 0xFFFF) + self.hl.set(added) self.cycles -= 1 def add_a_with_carry(self, getCaller, setCaller=None): @@ -347,7 +347,7 @@ self.flag.is_half_carry = (((s ^ self.a.get() ^ data) & 0x10) != 0) self.flag.is_carry = (s > 0xFF or s < 0) self.flag.zero_check(s) - self.a.set(s & 0xFF) # 1 cycle + self.a.set(s) # 1 cycle def subtract_a(self, getCaller, setCaller=None): # 1 cycle @@ -552,7 +552,7 @@ def store_expanded_c_in_a(self): # LDH A,(C) 2 cycles - self.a.set(self.read(0xFF00 + self.bc.get_lo())) # 1+2 cycles + self.a.set(self.read(0xFF00 + self.c.get())) # 1+2 cycles def load_and_increment_a_hli(self): # loadAndIncrement A,(HL) 2 cycles @@ -611,9 +611,9 @@ if (self.a.get() & 0xF0) > 0x90: delta |= 0x60 if not self.is_n(): - self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle + self.a.add(delta) # 1 cycle else: - self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle + self.a.add(-delta) # 1 cycle self.flag.partial_reset(keep_is_subtraction=True) if delta >= 0x60: self.flag.is_carry = True @@ -635,15 +635,15 @@ s = (self.sp.get() + offset) & 0xFFFF self.flag.reset() if (offset >= 0): - self.flag.is_carry = (s < self.sp.get()) - if (s & 0x0F00) < (self.sp.get() & 0x0F00): - self.flag.is_half_carry = True + self.check_carry(s, self.sp.get(False)) else: - self.flag.is_carry = (s > self.sp.get()) - if (s & 0x0F00) > (self.sp.get() & 0x0F00): - self.flag.is_half_carry = True + self.check_carry(self.sp.get(False), s) return s - + + def check_carry(self, big, small): + self.flag.is_carry = big < small + self.flag.is_half_carry = (big & 0x0F00) < (small & 0x0F00) + def complement_carry_flag(self): # CCF/SCF self.flag.partial_reset(keep_is_zero=True, keep_is_carry=True) From afa at codespeak.net Tue Mar 17 19:04:02 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Mar 2009 19:04:02 +0100 (CET) Subject: [pypy-svn] r63011 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090317180402.8D776168457@codespeak.net> Author: afa Date: Tue Mar 17 19:04:02 2009 New Revision: 63011 Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: Fix translation of the pyexpat module: - use the XML_SetUserData to store and retrieve the parser object: don't try to make use of nested scope, this doesn't exist in translated code! the "global_storage" dict is a hack IMO (but maybe a good one) - the handler functions are generated, and sethandler() is specialized for each handler - add XML_UseForeignDTD to line up with the version in pypy/lib/pyexpat.py /me starts a full translation to see if this really works. Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Tue Mar 17 19:04:02 2009 @@ -5,41 +5,54 @@ from pypy.interpreter.error import OperationError from pypy.objspace.descroperation import object_setattr from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rlib.unroll import unrolling_iterable + from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo import sys +import py if sys.platform == "win32": libname = 'libexpat' else: libname = 'expat' eci = ExternalCompilationInfo( - libraries=[libname], - includes=['expat.h'] + libraries=[libname], + includes=['expat.h'], + pre_include_bits=[ + '#define XML_COMBINED_VERSION' + + ' (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION)', + ], ) + eci = rffi_platform.configure_external_library( libname, eci, [dict(prefix='expat-', include_dir='lib', library_dir='win32/bin/release'), ]) +XML_Content_Ptr = lltype.Ptr(lltype.ForwardReference()) +XML_Parser = rffi.VOIDP # an opaque pointer + class CConfigure: _compilation_info_ = eci - XML_Content = rffi_platform.Struct('XML_Content',[ - ('numchildren', rffi.INT), - ('children', rffi.VOIDP), + XML_Content = rffi_platform.Struct('XML_Content', [ + ('numchildren', rffi.UINT), + ('children', XML_Content_Ptr), ('name', rffi.CCHARP), ('type', rffi.INT), ('quant', rffi.INT), ]) + XML_COMBINED_VERSION = rffi_platform.ConstantInteger('XML_COMBINED_VERSION') XML_FALSE = rffi_platform.ConstantInteger('XML_FALSE') XML_TRUE = rffi_platform.ConstantInteger('XML_TRUE') -XML_Parser = rffi.VOIDP # an opaque pointer for k, v in rffi_platform.configure(CConfigure).items(): globals()[k] = v +XML_Content_Ptr.TO.become(rffi.CArray(XML_Content)) + def expat_external(*a, **kw): kw['compilation_info'] = eci @@ -69,28 +82,132 @@ ElementDeclHandler = [rffi.CCHARP, lltype.Ptr(XML_Content)], AttlistDeclHandler = [rffi.CCHARP] * 4 + [rffi.INT], ) -if True: #XML_COMBINED_VERSION >= 19504: +if XML_COMBINED_VERSION >= 19504: HANDLERS['SkippedEntityHandler'] = [rffi.CCHARP, rffi.INT] +NB_HANDLERS = len(HANDLERS) + +class Storage: + "Store objects under a non moving ID" + def __init__(self): + self.next_id = 0 + self.storage = {} + + @staticmethod + def get_nonmoving_id(obj, id=-1): + if id < 0: + id = global_storage.next_id + global_storage.next_id += 1 + global_storage.storage[id] = obj + return id + + @staticmethod + def get_object(id): + return global_storage.storage[id] + + @staticmethod + def free_nonmoving_id(id): + del global_storage.storage[id] + +global_storage = Storage() + +class CallbackData(Wrappable): + def __init__(self, space, parser): + self.space = space + self.parser = parser SETTERS = {} -for name, params in HANDLERS.items(): - c_name = 'XML_Set' + name +for index, (name, params) in enumerate(HANDLERS.items()): + arg_names = ['arg%d' % (i,) for i in range(len(params))] + warg_names = ['w_arg%d' % (i,) for i in range(len(params))] + + converters = [] + for i, ARG in enumerate(params): + if name == "StartElementHandler" and i == 1: + converters.append( + 'w_arg%d = parser.w_convert_attributes(space, arg%d)' % (i, i)) + elif name in ["CharacterDataHandler", "DefaultHandlerExpand", "DefaultHandler"] and i == 0: + converters.append( + 'w_arg%d = parser.w_convert_charp_n(space, arg%d, arg%d)' % (i, i, i+1)) + del warg_names[i+1] + elif name in ["EntityDeclHandler"] and i == 2: + converters.append( + 'w_arg%d = parser.w_convert_charp_n(space, arg%d, arg%d)' % (i, i, i+1)) + del warg_names[i+1] + elif ARG == rffi.CCHARP: + converters.append( + 'w_arg%d = parser.w_convert_charp(space, arg%d)' % (i, i)) + elif ARG == lltype.Ptr(XML_Content): + converters.append( + 'w_arg%d = parser.w_convert_model(space, arg%d)' % (i, i)) + converters.append( + 'XML_FreeContentModel(parser.itself, arg%d)' % (i,)) + else: + converters.append( + 'w_arg%d = space.wrap(arg%d)' % (i, i)) + converters = '; '.join(converters) + + args = ', '.join(arg_names) + wargs = ', '.join(warg_names) + if name in ['UnknownEncodingHandler', 'ExternalEntityRefHandler', 'NotStandaloneHandler']: - RESULT_TYPE = rffi.INT + result_type = rffi.INT + result_converter = "space.int_w(w_result)" + result_error = "0" + else: + result_type = lltype.Void + result_converter = "None" + result_error = "None" + + if name == 'CharacterDataHandler': + pre_code = 'if parser.buffer_string(space, w_arg0, arg1): return' + else: + pre_code = 'parser.flush_character_buffer(space)' + + if name == 'ExternalEntityRefHandler': + post_code = 'if space.is_w(w_result, space.w_None): return 0' else: - RESULT_TYPE = lltype.Void - CALLBACK = lltype.Ptr(lltype.FuncType( - [rffi.VOIDP] + params, RESULT_TYPE)) + post_code = '' + + src = py.code.Source(""" + def handler(ll_userdata, %(args)s): + id = rffi.cast(lltype.Signed, ll_userdata) + userdata = global_storage.get_object(id) + space = userdata.space + parser = userdata.parser + + %(converters)s + %(pre_code)s + try: + w_result = space.call_function(parser.handlers[%(index)s], %(wargs)s) + except OperationError, e: + parser._exc_info = e + XML_StopParser(parser.itself, XML_FALSE) + return %(result_error)s + %(post_code)s + return %(result_converter)s + """ % locals()) + + exec str(src) + + c_name = 'XML_Set' + name + callback_type = lltype.Ptr(lltype.FuncType( + [rffi.VOIDP] + params, result_type)) func = expat_external(c_name, - [XML_Parser, CALLBACK], rffi.INT) - SETTERS[name] = func + [XML_Parser, callback_type], rffi.INT) + SETTERS[name] = (index, func, handler) + +ENUMERATE_SETTERS = unrolling_iterable(SETTERS.items()) XML_ParserCreate = expat_external( 'XML_ParserCreate', [rffi.CCHARP], XML_Parser) XML_ParserCreateNS = expat_external( 'XML_ParserCreateNS', [rffi.CCHARP, rffi.CHAR], XML_Parser) +XML_ParserFree = expat_external( + 'XML_ParserFree', [XML_Parser], lltype.Void) +XML_SetUserData = expat_external( + 'XML_SetUserData', [XML_Parser, rffi.VOIDP], lltype.Void) XML_Parse = expat_external( 'XML_Parse', [XML_Parser, rffi.CCHARP, rffi.INT, rffi.INT], rffi.INT) XML_StopParser = expat_external( @@ -100,6 +217,9 @@ 'XML_SetReturnNSTriplet', [XML_Parser, rffi.INT], lltype.Void) XML_GetSpecifiedAttributeCount = expat_external( 'XML_GetSpecifiedAttributeCount', [XML_Parser], rffi.INT) +if XML_COMBINED_VERSION >= 19505: + XML_UseForeignDTD = expat_external( + 'XML_UseForeignDTD', [XML_Parser, rffi.INT], lltype.Void) XML_GetErrorCode = expat_external( 'XML_GetErrorCode', [XML_Parser], rffi.INT) @@ -118,7 +238,6 @@ XML_FreeContentModel = expat_external( 'XML_FreeContentModel', [XML_Parser, lltype.Ptr(XML_Content)], lltype.Void) - class W_XMLParserType(Wrappable): def __init__(self, encoding, namespace_separator, w_intern): @@ -139,12 +258,27 @@ else: self.itself = XML_ParserCreate(self.encoding) + self.handlers = [None] * NB_HANDLERS + self.buffer_w = None self.buffer_size = 8192 + self.buffer_used = 0 self.w_character_data_handler = None self._exc_info = None + def __del__(self): + if XML_ParserFree: # careful with CPython interpreter shutdown + XML_ParserFree(self.itself) + if global_storage: + global_storage.free_nonmoving_id( + rffi.cast(lltype.Signed, self.itself)) + + def UseForeignDTD(self, space, w_flag=True): + flag = space.is_true(w_flag) + XML_UseForeignDTD(self.itself, flag) + UseForeignDTD.unwrap_spec = ['self', ObjSpace, W_Root] + # Handlers management def w_convert(self, space, s): @@ -168,8 +302,30 @@ else: return space.w_None + def w_convert_attributes(self, space, attrs): + if self.specified_attributes: + maxindex = XML_GetSpecifiedAttributeCount(self.itself) + else: + maxindex = 0 + while attrs[maxindex]: + maxindex += 2 # copied + + if self.ordered_attributes: + w_attrs = space.newlist([ + self.w_convert_charp(space, attrs[i]) + for i in range(maxindex)]) + else: + w_attrs = space.newdict() + for i in range(0, maxindex, 2): + space.setitem( + w_attrs, + self.w_convert_charp(space, attrs[i]), + self.w_convert_charp(space, attrs[i + 1])) + + return w_attrs + def w_convert_model(self, space, model): - children = [self._conv_content_model(model.children[i]) + children = [self.w_convert_model(space, model.c_children[i]) for i in range(model.c_numchildren)] return space.newtuple([ space.wrap(model.c_type), @@ -177,124 +333,46 @@ self.w_convert_charp(space, model.c_name), space.newtuple(children)]) - def sethandler(self, space, name, w_handler): - if name == 'StartElementHandler': - def callback(unused, name, attrs): + def buffer_string(self, space, w_string, length): + if self.buffer_w is not None: + if self.buffer_used + length > self.buffer_size: self.flush_character_buffer(space) - w_name = self.w_convert_charp(space, name) + # handler might have changed; drop the rest on the floor + # if there isn't a handler anymore + if self.w_character_data_handler is None: + return True + if length <= self.buffer_size: + self.buffer_w.append(w_string) + self.buffer_used += length + return True + else: + self.buffer_w = [] + self.buffer_used = 0 + return False + + def sethandler(self, space, name, w_handler, index, setter, handler): - if self.specified_attributes: - maxindex = XML_GetSpecifiedAttributeCount(self.itself) - else: - maxindex = 0 - while attrs[maxindex]: - maxindex += 2 # copied - - if self.ordered_attributes: - w_attrs = space.newlist([ - self.w_convert_charp(space, attrs[i]) - for i in range(maxindex)]) - else: - w_attrs = space.newdict() - for i in range(0, maxindex, 2): - space.setitem( - w_attrs, - self.w_convert_charp(space, attrs[i]), - self.w_convert_charp(space, attrs[i + 1])) - space.call_function(w_handler, w_name, w_attrs) - - elif name == 'CharacterDataHandler': - def callback(unused, data, length): - w_string = self.w_convert_charp_n(space, data, length) - - if self.buffer_w is None: - space.call_function(w_handler, w_string) - else: - if len(self.buffer_w) + length > self.buffer_size: # XXX sum(len(buffer)) - self.flush_character_buffer(space) - if self.w_character_data_handler is None: - return - if length >= self.buffer_size: - space.call_function(w_handler, w_string) - self.buffer_w = [] - else: - self.buffer_w.append(w_string) + if name == 'CharacterDataHandler': self.flush_character_buffer(space) if space.is_w(w_handler, space.w_None): self.w_character_data_handler = None else: self.w_character_data_handler = w_handler - elif name in ['DefaultHandlerExpand', 'DefaultHandler']: - def callback(unused, data, length): - w_string = self.w_convert_charp_n(space, data, length) - space.call_function(w_handler, w_string) + self.handlers[index] = w_handler + setter(self.itself, handler) - elif name == 'ElementDeclHandler': - def callback(unused, name, model): - self.flush_character_buffer(space) - w_model = self.w_convert_model(space, model) - XML_FreeContentModel(self.itself, model) - space.call_function(w_handler, - self.w_convert_charp(space, name), - w_model) - - elif name == 'EntityDeclHandler': - def callback(unused, ename, is_param, value, value_len, - base, system_id, pub_id, not_name): - self.flush_character_buffer(space) - - space.call_function( - w_handler, - self.w_convert_charp(space, ename), - space.wrap(is_param), - self.w_convert_charp_n(space, value, value_len), - self.w_convert_charp(space, base), - self.w_convert_charp(space, system_id), - self.w_convert_charp(space, pub_id), - self.w_convert_charp(space, not_name)) - - elif name == 'ExternalEntityRefHandler': - def callback(unused, context, base, system_id, pub_id): - w_res = space.call_function( - w_handler, - self.w_convert_charp(space, context), - self.w_convert_charp(space, base), - self.w_convert_charp(space, system_id), - self.w_convert_charp(space, pub_id)) - if space.is_w(w_res, space.w_None): - return 0 - return space.int_w(w_res) - - else: - ARGTYPES = HANDLERS[name] - def callback(unused, *args): - self.flush_character_buffer(space) - args_w = [] - for i, arg in enumerate(args): - if ARGTYPES[i] is rffi.CCHARP: - w_arg = self.w_convert_charp(space, arg) - else: - w_arg = space.wrap(arg) - args_w.append(w_arg) - space.call_function(w_handler, *args_w) - - def callback_wrapper(*args): - # Catch errors and record them - try: - return callback(*args) - except OperationError, e: - self._exc_info = e - XML_StopParser(self.itself, XML_FALSE) - callback_wrapper.func_name = name + '_callback' - SETTERS[name](self.itself, callback_wrapper) + sethandler._annspecialcase_ = 'specialize:arg(2)' def setattr(self, space, name, w_value): if name == "namespace_prefixes": XML_SetReturnNSTriplet(self.itself, space.int_w(w_value)) return - elif name in SETTERS: - return self.sethandler(space, name, w_value) + + for handler_name, (index, setter, handler) in ENUMERATE_SETTERS: + if name == handler_name: + return self.sethandler(space, handler_name, w_value, + index, setter, handler) # fallback to object.__setattr__() return space.call_function( @@ -305,7 +383,7 @@ # Parse methods def Parse(self, space, data, isfinal=True): - res = XML_Parse(self.itself, data, len(data), isfinal) + res = XML_Parse(self.itself, data, len(data), bool(isfinal)) if self._exc_info: e = self._exc_info self._exc_info = None @@ -314,8 +392,8 @@ exc = self.set_error(space, XML_GetErrorCode(self.itself)) raise exc self.flush_character_buffer(space) - return res - Parse.unwrap_spec = ['self', ObjSpace, str, bool] + return space.wrap(res) + Parse.unwrap_spec = ['self', ObjSpace, str, int] def ParseFile(self, space, w_file): return @@ -328,6 +406,7 @@ space.getattr(space.wrap(''), space.wrap('join')), space.newlist(self.buffer_w)) self.buffer_w = [] + self.buffer_used = 0 if self.w_character_data_handler: space.call_function(self.w_character_data_handler, w_data) @@ -365,6 +444,7 @@ def set_buffer_text(space, self, w_value): if space.is_true(w_value): self.buffer_w = [] + self.buffer_used = 0 else: self.flush_character_buffer(space) self.buffer_w = None @@ -380,6 +460,10 @@ setattr(obj, name, space.bool_w(value)) return GetSetProperty(fget, fset, cls=cls, doc=doc) +XMLParser_methods = ['Parse', 'ParseFile'] +if XML_COMBINED_VERSION >= 19505: + XMLParser_methods.append('UseForeignDTD') + W_XMLParserType.typedef = TypeDef( "pyexpat.XMLParserType", __doc__ = "XML parser", @@ -402,7 +486,7 @@ **dict((name, interp2app(getattr(W_XMLParserType, name), unwrap_spec=getattr(W_XMLParserType, name).unwrap_spec)) - for name in "Parse ParseFile".split()) + for name in XMLParser_methods) ) def ParserCreate(space, w_encoding=None, w_namespace_separator=None, @@ -429,6 +513,11 @@ w_intern = space.newdict() parser = W_XMLParserType(encoding, namespace_separator, w_intern) + global_storage.get_nonmoving_id( + CallbackData(space, parser), + id=rffi.cast(lltype.Signed, parser.itself)) + XML_SetUserData(parser.itself, parser.itself) + return space.wrap(parser) ParserCreate.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root] From tverwaes at codespeak.net Tue Mar 17 20:55:59 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 17 Mar 2009 20:55:59 +0100 (CET) Subject: [pypy-svn] r63012 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090317195559.E78C616847D@codespeak.net> Author: tverwaes Date: Tue Mar 17 20:55:56 2009 New Revision: 63012 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: removing specialize.arg. this even seems to have a very slight negative performance impact Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Tue Mar 17 20:55:56 2009 @@ -1,4 +1,4 @@ -from pypy.rlib.objectmodel import we_are_translated, specialize +from pypy.rlib.objectmodel import we_are_translated from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ @@ -236,7 +236,6 @@ self.memory.write(address, data) self.cycles -= 2 - @specialize.arg(-1) def fetch(self, use_cycles=True): # Fetching 1 cycle if use_cycles: @@ -257,19 +256,16 @@ def fetch_double_register(self, register): self.double_register_inverse_call(CPUFetchCaller(self), register) - @specialize.arg(-1) def push(self, data, use_cycles=True): # Stack, 2 cycles self.sp.dec(use_cycles) # 2 cycles self.memory.write(self.sp.get(use_cycles), data) - @specialize.arg(-1) def push_double_register(self, register, use_cycles=True): # PUSH rr 4 cycles self.push(register.get_hi(), use_cycles) # 2 cycles self.push(register.get_lo(), use_cycles) # 2 cycles - @specialize.arg(-1) def pop(self, use_cycles=True): # 1 cycle data = self.memory.read(self.sp.get()) @@ -287,7 +283,6 @@ register.set_hi_lo(a, b) # 2 cycles self.cycles += 1 - @specialize.arg(-1) def call(self, address, use_cycles=True): # 4 cycles self.push_double_register(self.pc, use_cycles) @@ -745,11 +740,9 @@ # Call Wrappers -------------------------------------------------------------- class CallWrapper(object): - @specialize.arg(-1) def get(self, use_cycles=True): raise Exception("called CallWrapper.get") - @specialize.arg(-1) def set(self, value, use_cycles=True): raise Exception("called CallWrapper.set") @@ -757,11 +750,9 @@ def __init__(self, number): self.number = number - @specialize.arg(-1) def get(self, use_cycles=True): return self.number - @specialize.arg(-1) def set(self, value, use_cycles=True): raise Exception("called CallWrapper.set") @@ -769,11 +760,9 @@ def __init__(self, register): self.register = register - @specialize.arg(-1) def get(self, use_cycles=True): return self.register.get(use_cycles) - @specialize.arg(-1) def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) @@ -782,11 +771,9 @@ def __init__(self, register): self.register = register - @specialize.arg(-1) def get(self, use_cycles=True): return self.register.get(use_cycles) - @specialize.arg(-1) def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) @@ -795,7 +782,6 @@ def __init__(self, cpu): self.cpu = cpu - @specialize.arg(-1) def get(self, use_cycles=True): return self.cpu.pop(use_cycles) @@ -804,7 +790,6 @@ def __init__(self, cpu): self.cpu = cpu - @specialize.arg(-1) def get(self, use_cycles=True): return self.cpu.fetch(use_cycles) Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Tue Mar 17 20:55:56 2009 @@ -1,8 +1,6 @@ -from pypy.rlib.objectmodel import specialize # --------------------------------------------------------------------------- class AbstractRegister(object): - @specialize.arg(-1) def get(self, use_cycles=True): return 0xFF @@ -18,21 +16,17 @@ def reset(self): self.value = self.reset_value - @specialize.arg(-1) def set(self, value, use_cycles=True): self.value = value & 0xFF if use_cycles: self.cpu.cycles -= 1 - @specialize.arg(-1) def get(self, use_cycles=True): return self.value - @specialize.arg(-1) def add(self, value, use_cycles=True): self.set(self.get(use_cycles)+value, use_cycles) - @specialize.arg(-1) def sub(self, value, use_cycles=True): self.set(self.get(use_cycles)-value, use_cycles) @@ -44,12 +38,10 @@ self.cpu = cpu self.reset_value = reset_value - @specialize.arg(-1) def set(self, value, use_cycles=True): # 1 Cycle raise Exception("Not Implemented") - @specialize.arg(-1) def set_hi_lo(self, hi, lo, use_cycles=True): # 2 Cycles raise Exception("Not Implemented") @@ -57,44 +49,36 @@ def reset(self): self.set(self.reset_value, use_cycles=False) - @specialize.arg(-1) def set_hi(self, hi=0, use_cycles=True): # 1 Cycle raise Exception("Not Implemented") - @specialize.arg(-1) def set_lo(self, lo=0, use_cycles=True): # 1 Cycle raise Exception("Not Implemented") - @specialize.arg(-1) def get(self, use_cycles=True): # 0 Cycles TODO: Check entanglement of cycles in CPU class. raise Exception("Not Implemented") - @specialize.arg(-1) def get_hi(self, use_cycles=True): # 0 Cycles raise Exception("Not Implemented") - @specialize.arg(-1) def get_lo(self, use_cycles=True): # 0 Cycles raise Exception("Not Implemented") - @specialize.arg(-1) def inc(self, use_cycles=True): self.add(1, use_cycles) if use_cycles: self.cpu.cycles += 1 - @specialize.arg(-1) def dec(self, use_cycles=True): self.add(-1, use_cycles) if use_cycles: self.cpu.cycles += 1 - @specialize.arg(-1) def add(self, value, use_cycles=True): self.set(self.get(use_cycles) + value, use_cycles=use_cycles) if use_cycles: @@ -108,7 +92,6 @@ self.hi = hi self.lo = lo - @specialize.arg(-1) def set(self, value, use_cycles=True): value = value & 0xFFFF self.set_hi(value >> 8, use_cycles) @@ -116,28 +99,22 @@ if use_cycles: self.cpu.cycles += 1 - @specialize.arg(-1) def set_hi_lo(self, hi, lo, use_cycles=True): self.set_hi(hi, use_cycles) self.set_lo(lo, use_cycles) - @specialize.arg(-1) def set_hi(self, hi=0, use_cycles=True): self.hi.set(hi, use_cycles) - @specialize.arg(-1) def set_lo(self, lo=0, use_cycles=True): self.lo.set(lo, use_cycles) - @specialize.arg(-1) def get(self, use_cycles=True): return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles) - @specialize.arg(-1) def get_hi(self, use_cycles=True): return self.hi.get(use_cycles) - @specialize.arg(-1) def get_lo(self, use_cycles=True): return self.lo.get(use_cycles) @@ -148,13 +125,11 @@ AbstractDoubleRegister.__init__(self, cpu, reset_value) self.value = 0x0000 - @specialize.arg(-1) def set(self, value, use_cycles=True): self.value = value & 0xFFFF if use_cycles: self.cpu.cycles -= 1 - @specialize.arg(-1) def set_hi_lo(self, hi, lo, use_cycles=True): hi &= 0xFF lo &= 0xFF @@ -162,45 +137,37 @@ if use_cycles: self.cpu.cycles -= 1 - @specialize.arg(-1) def set_hi(self, hi=0, use_cycles=True): self.set_hi_lo(hi, self.get_lo(False), use_cycles) if use_cycles: self.cpu.cycles += 1 - @specialize.arg(-1) def set_lo(self, lo=0, use_cycles=True): self.set_hi_lo(self.get_hi(False), lo, use_cycles) if use_cycles: self.cpu.cycles += 1 - @specialize.arg(-1) def get(self, use_cycles=True): return self.value - @specialize.arg(-1) def get_hi(self, use_cycles=True): return (self.value >> 8) - @specialize.arg(-1) def get_lo(self, use_cycles=True): return (self.value & 0xFF) - @specialize.arg(-1) def inc(self, use_cycles=True): self.value += 1 self.value &= 0xFFFF if use_cycles: self.cpu.cycles -= 2 - @specialize.arg(-1) def dec(self, use_cycles=True): self.value -= 1 self.value &= 0xFFFF if use_cycles: self.cpu.cycles -= 2 - @specialize.arg(-1) def add(self, value, use_cycles=True): self.value += value self.value &= 0xFFFF @@ -216,13 +183,11 @@ self.cpu = cpu self.hl = hl - @specialize.arg(-1) def set(self, value, use_cycles=True): self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0 if not use_cycles: self.cpu.cycles += 2 - @specialize.arg(-1) def get(self, use_cycles=True): if not use_cycles: self.cpu.cycles += 1 @@ -293,7 +258,6 @@ self.s_flag = False self.lower = 0x00 - @specialize.arg(-1) def get(self, use_cycles=True): value = 0 value += (int(self.is_carry) << 4) @@ -302,7 +266,6 @@ value += (int(self.is_zero) << 7) return value + self.lower - @specialize.arg(-1) def set(self, value, use_cycles=True): self.is_carry = bool(value & (1 << 4)) self.is_half_carry = bool(value & (1 << 5)) From tverwaes at codespeak.net Wed Mar 18 03:40:57 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 18 Mar 2009 03:40:57 +0100 (CET) Subject: [pypy-svn] r63021 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090318024057.46DD0168418@codespeak.net> Author: tverwaes Date: Wed Mar 18 03:40:54 2009 New Revision: 63021 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py pypy/trunk/pypy/lang/gameboy/test/test_cpu.py Log: moving around a bit of those carry flags Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Wed Mar 18 03:40:54 2009 @@ -316,11 +316,10 @@ def add_hl(self, register): # 2 cycles data = register.get() - added = (self.hl.get() + data) # 1 cycle + old = self.hl.get() + new = old + data self.flag.partial_reset(keep_is_zero=True) - self.flag.is_half_carry = (((added ^ self.hl.get() ^ data) & 0x1000) != 0) - self.flag.is_carry = (added >= 0x10000 or added < 0) - self.hl.set(added) + self.hl.set(self.double_register_check(old, new, False)) self.cycles -= 1 def add_a_with_carry(self, getCaller, setCaller=None): @@ -361,17 +360,19 @@ self.compare_a_simple(getCaller.get()) def compare_a_simple(self, s): - s = (self.a.get() - s) & 0xFF + s = self.a.get() - s self.flag.reset() self.flag.is_subtraction = True self.flag.zero_check(s) - self.subtract_his_carry_finish(s) + self.check_carry(self.a.get(), s) self.cycles -= 1 - def subtract_his_carry_finish(self, data): - self.flag.is_carry = (data > self.a.get()) - self.flag.is_half_carry_compare(data, self.a.get()) - + def check_carry(self, big, small): + # Overflow + self.flag.is_carry = ((small & 0xFF) > (big & 0xFF)) + # Overflow in lower byte + self.flag.is_half_carry = ((small & 0x0F) > (big & 0x0F)) + def and_a(self, getCaller, setCaller=None): # 1 cycle self.a.set(self.a.get() & getCaller.get()) # 1 cycle @@ -399,12 +400,12 @@ def inc(self, getCaller, setCaller): # 1 cycle - data = (getCaller.get() + 1) & 0xFF + data = getCaller.get() + 1 self.dec_inis_carry_finish(data, setCaller, 0x00) def dec(self, getCaller, setCaller): # 1 cycle - data = (getCaller.get() - 1) & 0xFF + data = getCaller.get() - 1 self.dec_inis_carry_finish(data, setCaller, 0x0F) self.flag.is_subtraction = True @@ -453,7 +454,7 @@ data = getCaller.get() s = (data >> 1) if self.flag.is_carry: - s += 0x80 + s += 0x80 self.flags_and_setter_finish(s, data, setCaller) # 1 cycle def rotate_right_a(self): @@ -490,7 +491,7 @@ def swap(self, getCaller, setCaller): # 1 cycle data = getCaller.get() - s = ((data << 4) + (data >> 4)) & 0xFF + s = ((data & 0x0F) << 4) + ((data & 0xF0) >> 4) self.flag.zero_check(s, reset=True) setCaller.set(s) @@ -627,16 +628,20 @@ def get_fetchadded_sp(self): # 1 cycle offset = process_2s_complement(self.fetch()) # 1 cycle - s = (self.sp.get() + offset) & 0xFFFF + old = self.sp.get() + new = old + offset + self.flag.reset() - if (offset >= 0): - self.check_carry(s, self.sp.get(False)) + return self.double_register_check(old, new, offset < 0) + + def double_register_check(self, old, new, subtraction): + if subtraction: + self.check_carry(old >> 8, new >> 8) else: - self.check_carry(self.sp.get(False), s) - return s - - def check_carry(self, big, small): - self.flag.is_carry = big < small + self.check_carry(new >> 8, old >> 8) + return new + + def check_half_carry(self, big, small): self.flag.is_half_carry = (big & 0x0F00) < (small & 0x0F00) def complement_carry_flag(self): Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Wed Mar 18 03:40:54 2009 @@ -286,13 +286,3 @@ if reset: self.reset() self.is_carry = ((value & compare_and) != 0) - - def is_half_carry_compare(self, value, a, inverted=False): - if inverted: - self.is_half_carry = ((value & 0x0F) < (a & 0x0F)) - else: - self.is_half_carry = ((value & 0x0F) > (a & 0x0F)) - - #def is_carry_compare(self, a, b): - # self.is_carry = (a < b) - Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu.py Wed Mar 18 03:40:54 2009 @@ -881,8 +881,9 @@ cpu = get_cpu() opCode = 0x98 value = 0x12 - registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] + registers = ["b", "c", "d", "e", "h", "l", "hli", "a"] for register in registers: + register = cpu.__dict__[register] cpu.reset() cpu.a.set(value) register.set(value) @@ -896,11 +897,11 @@ cpu.flag.is_carry = True cpu.a.set(value+1) register.set(value) - numCycles= 1 + numCycles = 1 if register == cpu.hli: numCycles = 2 cycle_test(cpu, opCode, numCycles) - if register == cpu.a: + if register is cpu.a: assert cpu.a.get() == 0xFF else: assert cpu.a.get() == 0 From tverwaes at codespeak.net Wed Mar 18 04:06:36 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 18 Mar 2009 04:06:36 +0100 (CET) Subject: [pypy-svn] r63022 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090318030636.B4A3F1683CD@codespeak.net> Author: tverwaes Date: Wed Mar 18 04:06:36 2009 New Revision: 63022 Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: documenting Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Wed Mar 18 04:06:36 2009 @@ -6,7 +6,7 @@ class Register(AbstractRegister): - def __init__(self, cpu, value=0): + def __init__(self, cpu, value=0x00): # assert isinstance(cpu, CPU) self.reset_value = self.value = value self.cpu = cpu From tverwaes at codespeak.net Wed Mar 18 04:25:59 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 18 Mar 2009 04:25:59 +0100 (CET) Subject: [pypy-svn] r63023 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090318032559.66FD8168417@codespeak.net> Author: tverwaes Date: Wed Mar 18 04:25:54 2009 New Revision: 63023 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: moving around code and making reset direct. Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Wed Mar 18 04:25:54 2009 @@ -362,8 +362,8 @@ def compare_a_simple(self, s): s = self.a.get() - s self.flag.reset() - self.flag.is_subtraction = True self.flag.zero_check(s) + self.flag.is_subtraction = True self.check_carry(self.a.get(), s) self.cycles -= 1 @@ -382,13 +382,15 @@ def xor_a(self, getCaller, setCaller=None): # 1 cycle - self.a.set( self.a.get() ^ getCaller.get()) # 1 cycle - self.flag.zero_check(self.a.get(), reset=True) + self.a.set(self.a.get() ^ getCaller.get()) # 1 cycle + self.flag.reset() + self.flag.zero_check(self.a.get()) def or_a(self, getCaller, setCaller=None): # 1 cycle self.a.set(self.a.get() | getCaller.get()) # 1 cycle - self.flag.zero_check(self.a.get(), reset=True) + self.flag.reset() + self.flag.zero_check(self.a.get()) def inc_double_register(self, register): # INC rr @@ -492,7 +494,8 @@ # 1 cycle data = getCaller.get() s = ((data & 0x0F) << 4) + ((data & 0xF0) >> 4) - self.flag.zero_check(s, reset=True) + self.flag.reset() + self.flag.zero_check(s) setCaller.set(s) def test_bit(self, getCaller, setCaller, n): Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Wed Mar 18 04:25:54 2009 @@ -239,8 +239,14 @@ self.reset() def reset(self): - self.partial_reset() - + self.is_zero = False + self.is_subtraction = False + self.is_half_carry = False + self.is_carry = False + self.p_flag = False + self.s_flag = False + self.lower = 0x00 + def partial_reset(self, keep_is_zero=False, keep_is_subtraction=False, keep_is_half_carry=False, keep_is_carry=False,\ keep_p=False, keep_s=False): @@ -260,14 +266,14 @@ def get(self, use_cycles=True): value = 0 - value += (int(self.is_carry) << 4) - value += (int(self.is_half_carry) << 5) - value += (int(self.is_subtraction) << 6) - value += (int(self.is_zero) << 7) + value += (int(self.is_carry) << 4) + value += (int(self.is_half_carry) << 5) + value += (int(self.is_subtraction) << 6) + value += (int(self.is_zero) << 7) return value + self.lower def set(self, value, use_cycles=True): - self.is_carry = bool(value & (1 << 4)) + self.is_carry = bool(value & (1 << 4)) self.is_half_carry = bool(value & (1 << 5)) self.is_subtraction = bool(value & (1 << 6)) self.is_zero = bool(value & (1 << 7)) @@ -275,12 +281,8 @@ if use_cycles: self.cpu.cycles -= 1 - def zero_check(self, a, reset=False): - if reset: - self.reset() - if isinstance(a, (Register)): - a = a.get() - self.is_zero = ((a & 0xFF) == 0) + def zero_check(self, value): + self.is_zero = ((value & 0xFF) == 0) def is_carry_compare(self, value, compare_and=0x01, reset=False): if reset: From pedronis at codespeak.net Wed Mar 18 10:27:42 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 18 Mar 2009 10:27:42 +0100 (CET) Subject: [pypy-svn] r63025 - in pypy/build/bot2/pypybuildbot: . test Message-ID: <20090318092742.4C87E168417@codespeak.net> Author: pedronis Date: Wed Mar 18 10:27:40 2009 New Revision: 63025 Modified: pypy/build/bot2/pypybuildbot/summary.py pypy/build/bot2/pypybuildbot/test/test_summary.py Log: (iko, pedronis) deal with the new 'S' vs 's' distinction Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Wed Mar 18 10:27:40 2009 @@ -46,7 +46,7 @@ namekey = tuple(namekey) self._outcomes[namekey] = shortrepr - if shortrepr == 's': + if shortrepr.lower() == 's': self.skipped.add(namekey) elif shortrepr == '.': pass @@ -403,7 +403,7 @@ line = [] for label, outcome_set in by_label: letter = outcome_set.get_outcome(failure) - failed = letter not in ('s', '.') + failed = letter.lower() not in ('s', '.') if outcome_set.get_longrepr(failure): longrepr_url = self.make_longrepr_url_for(outcome_set, failure) Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Wed Mar 18 10:27:40 2009 @@ -18,11 +18,13 @@ log = StringIO("""F a/b.py:test_one . a/b.py:test_two s a/b.py:test_three +S a/c.py:test_four """) rev_outcome_set.populate(log) - assert rev_outcome_set.skipped == set([("a.b","test_three")]) + assert rev_outcome_set.skipped == set([("a.b","test_three"), + ("a.c", "test_four")]) assert rev_outcome_set.failed == set([("a.b", "test_one")]) assert rev_outcome_set.numpassed == 1 @@ -39,6 +41,11 @@ res = rev_outcome_set.get_outcome(("a.b", "test_two")) assert res == '.' + res = rev_outcome_set.get_outcome(("a.c", "test_four")) + assert res == 'S' + key_namekey = rev_outcome_set.get_key_namekey(("a.c", "test_four")) + assert key_namekey == (('foo', 40), ("a.c", "test_four")) + def test_populate_from_empty(self): rev_outcome_set = summary.RevisionOutcomeSet(0) log = StringIO("") From tverwaes at codespeak.net Wed Mar 18 11:27:24 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 18 Mar 2009 11:27:24 +0100 (CET) Subject: [pypy-svn] r63026 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090318102724.DD616168418@codespeak.net> Author: tverwaes Date: Wed Mar 18 11:27:23 2009 New Revision: 63026 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py Log: refactorings Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Wed Mar 18 11:27:23 2009 @@ -160,12 +160,6 @@ def is_not_c(self): return not self.is_c() - def is_not_h(self): - return not self.is_h() - - def is_not_n(self): - return not self.is_n() - def set_rom(self, banks): self.rom = banks @@ -319,7 +313,8 @@ old = self.hl.get() new = old + data self.flag.partial_reset(keep_is_zero=True) - self.hl.set(self.double_register_check(old, new, False)) + self.double_register_check(old, new, False) + self.hl.set(new) self.cycles -= 1 def add_a_with_carry(self, getCaller, setCaller=None): @@ -596,27 +591,33 @@ self.flag.is_subtraction = True self.flag.is_half_carry = True + def decimal_adjust_byte(self, byte, flag): + # [1 1 X X] or [1 0 1 X] at least + # or flag set: [0 1 1 0] + return ((byte & 0xF) > 0x9 | flag) * 0x6 + + def negate_if_subtraction(self, value): + # Flip the sign-bit of the 8-bit value. + return (self.flag.is_subtraction * 0x80) ^ value + def decimal_adjust_a(self): # DAA 1 cycle delta = 0 - if self.is_h(): - delta |= 0x06 - if self.is_c(): - delta |= 0x60 - if (self.a.get() & 0x0F) > 0x09: - delta |= 0x06 - if (self.a.get() & 0xF0) > 0x80: - delta |= 0x60 - if (self.a.get() & 0xF0) > 0x90: + + a = process_2s_complement(self.a.get()) + + delta |= self.decimal_adjust_byte(a >> 4, self.is_c()) << 4 + delta |= self.decimal_adjust_byte(a, self.is_h()) + + if (a < 0) and ((a & 0xF) > 0x9): delta |= 0x60 - if not self.is_n(): - self.a.add(delta) # 1 cycle - else: - self.a.add(-delta) # 1 cycle + + self.a.add(self.negate_if_subtraction(delta)) # 1 cycle + self.flag.partial_reset(keep_is_subtraction=True) + self.flag.zero_check(self.a.get()) if delta >= 0x60: self.flag.is_carry = True - self.flag.zero_check(self.a.get()) def increment_sp_by_fetch(self): # ADD SP,nn 4 cycles @@ -635,18 +636,14 @@ new = old + offset self.flag.reset() - return self.double_register_check(old, new, offset < 0) + self.double_register_check(old, new, offset < 0) + return new def double_register_check(self, old, new, subtraction): if subtraction: - self.check_carry(old >> 8, new >> 8) - else: - self.check_carry(new >> 8, old >> 8) - return new + new, old = old, new + self.check_carry(new >> 8, old >> 8) - def check_half_carry(self, big, small): - self.flag.is_half_carry = (big & 0x0F00) < (small & 0x0F00) - def complement_carry_flag(self): # CCF/SCF self.flag.partial_reset(keep_is_zero=True, keep_is_carry=True) From afa at codespeak.net Wed Mar 18 13:39:23 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Mar 2009 13:39:23 +0100 (CET) Subject: [pypy-svn] r63029 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090318123923.E3B61168453@codespeak.net> Author: afa Date: Wed Mar 18 13:39:20 2009 New Revision: 63029 Modified: pypy/trunk/pypy/module/pyexpat/__init__.py pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: pyexpat: last translation fixes, add docstrings. Modified: pypy/trunk/pypy/module/pyexpat/__init__.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/__init__.py (original) +++ pypy/trunk/pypy/module/pyexpat/__init__.py Wed Mar 18 13:39:20 2009 @@ -3,6 +3,8 @@ from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): + "Python wrapper for Expat parser." + appleveldefs = { 'ExpatError' : 'app_pyexpat.ExpatError', 'error' : 'app_pyexpat.ExpatError', Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Wed Mar 18 13:39:20 2009 @@ -122,6 +122,7 @@ converters = [] for i, ARG in enumerate(params): + # Some custom argument conversions if name == "StartElementHandler" and i == 1: converters.append( 'w_arg%d = parser.w_convert_attributes(space, arg%d)' % (i, i)) @@ -133,6 +134,8 @@ converters.append( 'w_arg%d = parser.w_convert_charp_n(space, arg%d, arg%d)' % (i, i, i+1)) del warg_names[i+1] + + # the standard conversions elif ARG == rffi.CCHARP: converters.append( 'w_arg%d = parser.w_convert_charp(space, arg%d)' % (i, i)) @@ -177,15 +180,15 @@ space = userdata.space parser = userdata.parser - %(converters)s - %(pre_code)s try: + %(converters)s + %(pre_code)s w_result = space.call_function(parser.handlers[%(index)s], %(wargs)s) + %(post_code)s except OperationError, e: parser._exc_info = e XML_StopParser(parser.itself, XML_FALSE) return %(result_error)s - %(post_code)s return %(result_converter)s """ % locals()) @@ -195,11 +198,13 @@ callback_type = lltype.Ptr(lltype.FuncType( [rffi.VOIDP] + params, result_type)) func = expat_external(c_name, - [XML_Parser, callback_type], rffi.INT) + [XML_Parser, callback_type], lltype.Void) SETTERS[name] = (index, func, handler) ENUMERATE_SETTERS = unrolling_iterable(SETTERS.items()) +# Declarations of external functions + XML_ParserCreate = expat_external( 'XML_ParserCreate', [rffi.CCHARP], XML_Parser) XML_ParserCreateNS = expat_external( @@ -275,6 +280,12 @@ rffi.cast(lltype.Signed, self.itself)) def UseForeignDTD(self, space, w_flag=True): + """UseForeignDTD([flag]) +Allows the application to provide an artificial external subset if one is +not specified as part of the document instance. This readily allows the +use of a 'default' document type controlled by the application, while still +getting the advantage of providing document type information to the parser. +'flag' defaults to True if not provided.""" flag = space.is_true(w_flag) XML_UseForeignDTD(self.itself, flag) UseForeignDTD.unwrap_spec = ['self', ObjSpace, W_Root] @@ -383,6 +394,9 @@ # Parse methods def Parse(self, space, data, isfinal=True): + """Parse(data[, isfinal]) +Parse XML data. `isfinal' should be true at end of input.""" + res = XML_Parse(self.itself, data, len(data), bool(isfinal)) if self._exc_info: e = self._exc_info @@ -396,6 +410,8 @@ Parse.unwrap_spec = ['self', ObjSpace, str, int] def ParseFile(self, space, w_file): + """ParseFile(file) +Parse XML data from file-like object.""" return ParseFile.unwrap_spec = ['self', ObjSpace, W_Root] @@ -491,6 +507,8 @@ def ParserCreate(space, w_encoding=None, w_namespace_separator=None, w_intern=NoneNotWrapped): + """ParserCreate([encoding[, namespace_separator]]) -> parser +Return a new XML parser object.""" if space.is_w(w_encoding, space.w_None): encoding = None else: @@ -522,6 +540,8 @@ ParserCreate.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root] def ErrorString(space, code): + """ErrorString(errno) -> string +Returns string error for given number.""" return space.wrap(rffi.charp2str(XML_ErrorString(code))) ErrorString.unwrap_spec = [ObjSpace, int] From afa at codespeak.net Wed Mar 18 13:55:42 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Mar 2009 13:55:42 +0100 (CET) Subject: [pypy-svn] r63030 - pypy/trunk/pypy/config Message-ID: <20090318125542.7C7D116844E@codespeak.net> Author: afa Date: Wed Mar 18 13:55:42 2009 New Revision: 63030 Modified: pypy/trunk/pypy/config/pypyoption.py Log: pypy.module.pyexpat is now a WorkingModule Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Wed Mar 18 13:55:42 2009 @@ -28,7 +28,7 @@ "rctime" , "select", "zipimport", "_lsprof", "crypt", "signal", "dyngram", "_rawffi", "termios", "zlib", "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO", - "thread", "itertools"] + "thread", "itertools", "pyexpat"] )) working_oo_modules = default_modules.copy() @@ -70,6 +70,7 @@ "zlib" : ["pypy.rlib.rzlib"], "bz2" : ["pypy.module.bz2.interp_bz2"], + "pyexpat" : ["pypy.module.pyexpat.interp_pyexpat"], } def get_module_validator(modname): From fijal at codespeak.net Wed Mar 18 14:13:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 18 Mar 2009 14:13:14 +0100 (CET) Subject: [pypy-svn] r63031 - pypy/branch/virtualizable-specnodes Message-ID: <20090318131314.584A316844E@codespeak.net> Author: fijal Date: Wed Mar 18 14:13:10 2009 New Revision: 63031 Added: pypy/branch/virtualizable-specnodes/ - copied from r63030, pypy/branch/pyjitpl5/ Log: A branch (of a branch) to experiment with virtualizable specnodes From fijal at codespeak.net Wed Mar 18 14:16:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 18 Mar 2009 14:16:21 +0100 (CET) Subject: [pypy-svn] r63032 - in pypy/branch/virtualizable-specnodes/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090318131621.53231168451@codespeak.net> Author: fijal Date: Wed Mar 18 14:16:20 2009 New Revision: 63032 Modified: pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py Log: in-progress checkin of dealing with virtualizable specnodes in a correct way Modified: pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py Wed Mar 18 14:16:20 2009 @@ -37,6 +37,11 @@ def sort_key(self): return self.ofs + def equals(self, other): + if not isinstance(other, Descr): + return False + return self.sort_key() == other.sort_key() + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): @@ -74,6 +79,19 @@ def set_meta_interp(self, metainterp): self.metainterp = metainterp # to handle guard failures + def compile_arg(self, x, c, op, var2index): + if isinstance(x, history.Box): + llimpl.compile_add_var(c, var2index[x]) + elif isinstance(x, history.ConstInt): + llimpl.compile_add_int_const(c, x.value) + elif isinstance(x, history.ConstPtr): + llimpl.compile_add_ptr_const(c, x.value) + elif isinstance(x, history.ConstAddr): + llimpl.compile_add_int_const(c, x.getint()) + else: + raise Exception("%s args contain: %r" % (op.getopname(), + x)) + def compile_operations(self, operations, from_guard=None): """In a real assembler backend, this should assemble the given list of operations. Here we just generate a similar LoopOrBridge @@ -105,17 +123,7 @@ if op.descr is not None: llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type) for x in op.args: - if isinstance(x, history.Box): - llimpl.compile_add_var(c, var2index[x]) - elif isinstance(x, history.ConstInt): - llimpl.compile_add_int_const(c, x.value) - elif isinstance(x, history.ConstPtr): - llimpl.compile_add_ptr_const(c, x.value) - elif isinstance(x, history.ConstAddr): - llimpl.compile_add_int_const(c, x.getint()) - else: - raise Exception("%s args contain: %r" % (op.getopname(), - x)) + self.compile_arg(x, c, op, var2index) x = op.result if x is not None: if isinstance(x, history.BoxInt): @@ -142,6 +150,9 @@ llimpl.compile_from_guard(c, from_guard._compiled, from_guard._opindex) + def update_loop(self, loop, mp, guard_op, newboxlist): + self.compile_operations(loop.operations) + def execute_operations_in_new_frame(self, name, operations, valueboxes): """Perform a 'call' to the given merge point, i.e. create a new CPU frame and use it to execute the operations that Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py Wed Mar 18 14:16:20 2009 @@ -112,6 +112,7 @@ else: name = 'Loop #%d' % len(metainterp.stats.loops) graph = Graph(name, '#f084c2') + graph.extensions = [None] return graph def create_empty_bridge(metainterp): @@ -120,6 +121,7 @@ else: name = 'Bridge #%d' % len(metainterp.stats.loops) graph = Graph(name, '#84f0c2') + graph.extensions = [None] return graph # ____________________________________________________________ @@ -149,6 +151,15 @@ metainterp.cpu.compile_operations(loop.operations, guard_op) metainterp.stats.loops.append(loop) +def update_loop(metainterp, loop, guard_op, newboxlist): + mp = loop.operations[0] + mp.args += newboxlist + jump = loop.operations[-1] + jump.args += newboxlist + guard_op.liveboxes += newboxlist + guard_op.storage = None + metainterp.cpu.update_loop(loop, mp, guard_op, newboxlist) + # ____________________________________________________________ def matching_merge_point(metainterp, targetmp, endliveboxes): @@ -165,10 +176,14 @@ op = ResOperation(rop.JUMP, endliveboxes, None) operations.append(op) # - old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge, - metainterp.cpu) + old_loop, newboxlist = optimize.optimize_bridge(metainterp.options, + old_loops, bridge, + metainterp.cpu) if old_loop is None: return None bridge.jump_to = old_loop + if newboxlist: + # recompile loop + update_loop(metainterp, old_loop, guard_op, newboxlist) finish_loop_or_bridge(metainterp, bridge, old_loop.operations[0], guard_op) return bridge Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py Wed Mar 18 14:16:20 2009 @@ -3,15 +3,10 @@ ResOperation, AbstractDescr, Options, AbstractValue, ConstPtr) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, - VirtualInstanceSpecNode, - VirtualizableSpecNode, - NotSpecNode, - DelayedSpecNode, - SpecNodeWithBox, - DelayedFixedListSpecNode, - VirtualFixedListSpecNode, - VirtualizableListSpecNode, - ) + VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, + DelayedSpecNode, SpecNodeWithBox, DelayedFixedListSpecNode, + VirtualFixedListSpecNode, MatchEverythingSpecNode, + VirtualizableListSpecNode, av_eq, av_hash) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype, llmemory @@ -106,12 +101,6 @@ liveboxes.append(box) return res -def av_eq(self, other): - return self.sort_key() == other.sort_key() - -def av_hash(self): - return self.sort_key() - def av_list_in(lst, key): # lst is a list of about 2 elements in the typical case, so no # point in making a dict lookup @@ -139,6 +128,7 @@ self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables + self.allfields = None def is_nonzero(self): return self.cls is not None or self.nonzero @@ -146,7 +136,7 @@ def is_zero(self): return self.const and not self.source.getptr_base() - def escape_if_startbox(self, memo): + def escape_if_startbox(self, memo, cpu): if self in memo: return memo[self] = None @@ -154,23 +144,29 @@ self.escaped = True if not self.virtualized: for node in self.curfields.values(): - node.escape_if_startbox(memo) + node.escape_if_startbox(memo, cpu) else: for key, node in self.curfields.items(): if self.vdesc is not None and av_list_in(self.vdesc, key): - node.virtualized = True - if node.cls is None: - node.cls = InstanceNode(FixedClass(), const=True) - node.escape_if_startbox(memo) + node.initialize_virtualizable(cpu) + node.escape_if_startbox(memo, cpu) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: if self.vdesc is not None and av_list_in(self.vdesc, key): - node.virtualized = True - if node.cls is None: - node.cls = InstanceNode(FixedClass(), const=True) - node.escape_if_startbox(memo) + node.initialize_virtualizable(cpu) + node.escape_if_startbox(memo, cpu) + + def initialize_virtualizable(self, cpu): + self.virtualized = True + if self.cls is None: + self.cls = InstanceNode(FixedClass(), const=True) + self.allfields = xxx + else: + ad = self.cls.source.arraydescr + lgtbox = cpu.do_arraylen_gc([self.source], ad) + self.allfields = [ConstInt(i) for i in range(lgtbox.getint())] def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) @@ -228,9 +224,7 @@ return DelayedSpecNode(known_class, fields) else: assert self is other - d = self.origfields.copy() - d.update(other.curfields) - offsets = d.keys() + offsets = self.allfields sort_descrs(offsets) fields = [] for ofs in offsets: @@ -242,10 +236,11 @@ self.origfields[ofs].cls = node.cls nodes[box] = self.origfields[ofs] specnode = self.origfields[ofs].intersect(node, nodes) - else: - # ofs in self.origfields: + elif ofs in self.origfields: node = self.origfields[ofs] specnode = node.intersect(node, nodes) + else: + specnode = MatchEverythingSpecNode() fields.append((ofs, specnode)) if isinstance(known_class, FixedList): return VirtualizableListSpecNode(known_class, fields) @@ -285,9 +280,14 @@ perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): - perfect_specializer.adapt_for_match(old_loop.operations) + num = len(old_loop.extensions) + newlist, newspecnodes = perfect_specializer.adapt_for_match( + old_loop.operations, num) + if newlist: + old_loop.extensions.append(newspecnodes) + perfect_specializer.loop.operations[0].args.extend(newlist) perfect_specializer.optimize_loop() - return old_loop + return old_loop, newlist return None # no loop matches class PerfectSpecializer(object): @@ -439,7 +439,8 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) if op.vdesc: - instnode.vdesc = op.vdesc.virtuals + instnode.vdesc = op.vdesc.virtuals + instnode.allfields = op.vdesc.fields continue elif op.is_always_pure(): for arg in op.args: @@ -469,7 +470,7 @@ for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): - self.nodes[end_box].escape_if_startbox(memo) + self.nodes[end_box].escape_if_startbox(memo, self.cpu) for i in range(len(end_args)): box = self.loop.operations[0].args[i] other_box = end_args[i] @@ -508,18 +509,28 @@ box = boxlist[i] specnode = self.specnodes[i] specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) + l = [] + for i, (group, arg) in enumerate(newboxlist): + l.append((group, i, arg)) + l.sort() + return [e[2] for e in l] + return newboxlist - def optimize_guard(self, op): - liveboxes = [] + def deal_with_boxes(self, boxes): storage = AllocationStorage() - memo = {} + newboxes = [] indices = [] + memo = {} + for box in boxes: + indices.append(storage.deal_with_box(box, self.nodes, newboxes, + memo)) + return storage, newboxes, indices + + def optimize_guard(self, op): old_boxes = op.liveboxes op = op.clone() - for box in old_boxes: - indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo)) + storage, liveboxes, indices = self.deal_with_boxes(old_boxes) rev_boxes = {} for i in range(len(liveboxes)): box = liveboxes[i] @@ -821,14 +832,18 @@ return False return True - def adapt_for_match(self, old_operations): + def adapt_for_match(self, old_operations, num): old_mp = old_operations[0] jump_op = self.loop.operations[-1] self.specnodes = old_mp.specnodes + newboxlist = [] + extensions = [] for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] new_instnode = self.nodes[jump_op.args[i]] - old_specnode.adapt_to(new_instnode) + old_specnode.adapt_to(new_instnode, newboxlist, extensions, num) + newboxlist = [i for _, i in newboxlist] + return newboxlist, extensions class Chooser(object): def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists): Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py Wed Mar 18 14:16:20 2009 @@ -898,7 +898,11 @@ for i in range(len(mp.specnodes)): specnode = mp.specnodes[i] specnode.extract_runtime_data(self.cpu, args[i], expanded_args) - return expanded_args + l = [] + for i, (group, arg) in enumerate(expanded_args): + l.append((group, i, arg)) + l.sort() + return [e[2] for e in l] def _initialize_from_start(self, original_boxes, num_green_args, *args): if args: Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py Wed Mar 18 14:16:20 2009 @@ -1,15 +1,22 @@ from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp import executor +from pypy.rlib.objectmodel import r_dict + +def av_eq(self, other): + return self.sort_key() == other.sort_key() + +def av_hash(self): + return self.sort_key() class SpecNode(object): def expand_boxlist(self, instnode, newboxlist, start): - newboxlist.append(instnode.source) + newboxlist.append((0, instnode.source)) def extract_runtime_data(self, cpu, valuebox, resultlist): - resultlist.append(valuebox) + resultlist.append((0, valuebox)) - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num): instnode.escaped = True def mutate_nodes(self, instnode): @@ -21,6 +28,33 @@ def matches(self, other): raise NotImplementedError +class RedirectingSpecNode(SpecNode): + def __init__(self, specnode, group): + self.redirect_to = specnode + self.group = group + + def expand_boxlist(self, instnode, newboxlist, start): + l = [] + self.redirect_to.expand_boxlist(instnode, l, start) + newboxlist.extend([(self.group, e) for _, e in l]) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + l = [] + self.redirect_to.extract_runtime_data(cpu, valuebox, l) + resultlist.extend([(self.group, e) for _, e in l]) + + def adapt_to(self, *args): + self.redirect_to.adapt_to(*args) + + def equals(self, other): + return self.redirect_to.equals(other) + + def matches(self, other): + return self.redirect_to.matches(other) + +class MatchEverythingSpecNode(SpecNode): + pass + class NotSpecNode(SpecNode): def mutate_nodes(self, instnode): instnode.cursize = -1 @@ -68,31 +102,20 @@ return False return instnode.cls.source.equals(self.known_class) -##class FixedListSpecNode(FixedClassSpecNode): - -## def equals(self, other): -## if type(other) is not FixedListSpecNode: -## return False -## else: -## assert isinstance(other, FixedListSpecNode) # make annotator happy -## return self.known_class.equals(other.known_class) - class SpecNodeWithFields(FixedClassSpecNode): def __init__(self, known_class, fields): FixedClassSpecNode.__init__(self, known_class) self.fields = fields def mutate_nodes(self, instnode): - from pypy.jit.metainterp.optimize import av_eq, av_hash - from pypy.rlib.objectmodel import r_dict - FixedClassSpecNode.mutate_nodes(self, instnode) curfields = r_dict(av_eq, av_hash) for ofs, subspecnode in self.fields: - subinstnode = instnode.origfields[ofs] - # should really be there - subspecnode.mutate_nodes(subinstnode) - curfields[ofs] = subinstnode + if not isinstance(subspecnode, MatchEverythingSpecNode): + subinstnode = instnode.origfields[ofs] + # should really be there + subspecnode.mutate_nodes(subinstnode) + curfields[ofs] = subinstnode instnode.curfields = curfields def equals(self, other): @@ -111,66 +134,70 @@ return True def matches(self, instnode): - # XXX think about details of virtual vs virtualizable if not FixedClassSpecNode.matches(self, instnode): return False for key, value in self.fields: - if key not in instnode.curfields: - return False - if value is not None and not value.matches(instnode.curfields[key]): - return False + if not isinstance(value, MatchEverythingSpecNode): + if key not in instnode.curfields: + return False + if value is not None and not value.matches(instnode.curfields[key]): + return False return True def expand_boxlist(self, instnode, newboxlist, start): for ofs, subspecnode in self.fields: - subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start) + if not isinstance(subspecnode, MatchEverythingSpecNode): + subinstnode = instnode.curfields[ofs] # should really be there + subspecnode.expand_boxlist(subinstnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: from pypy.jit.metainterp.history import AbstractDescr assert isinstance(ofs, AbstractDescr) - fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox], ofs) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + if not isinstance(subspecnode, MatchEverythingSpecNode): + fieldbox = executor.execute(cpu, rop.GETFIELD_GC, + [valuebox], ofs) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num): for ofs, subspecnode in self.fields: - subspecnode.adapt_to(instnode.curfields[ofs]) + subspecnode.adapt_to(instnode.curfields[ofs], newboxlist, + newspecnodes, num) -class VirtualizedSpecNode(SpecNodeWithFields): +class VirtualizedOrDelayedSpecNode(SpecNodeWithFields): def expand_boxlist(self, instnode, newboxlist, start): - newboxlist.append(instnode.source) + newboxlist.append((0, instnode.source)) SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): - resultlist.append(valuebox) + resultlist.append((0, valuebox)) SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num): instnode.escaped = True - SpecNodeWithFields.adapt_to(self, instnode) + SpecNodeWithFields.adapt_to(self, instnode, newboxlist, newspecnodes, + num) -class DelayedSpecNode(VirtualizedSpecNode): +class DelayedSpecNode(VirtualizedOrDelayedSpecNode): def expand_boxlist(self, instnode, newboxlist, oplist): from pypy.jit.metainterp.history import AbstractDescr - newboxlist.append(instnode.source) + newboxlist.append((0, instnode.source)) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) if oplist is None: instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append(instnode.curfields[ofs].source) + newboxlist.append((0, instnode.curfields[ofs].source)) else: if ofs in instnode.cleanfields: - newboxlist.append(instnode.cleanfields[ofs].source) + newboxlist.append((0, instnode.cleanfields[ofs].source)) else: box = subspecnode.box.clonebox() assert isinstance(ofs, AbstractDescr) oplist.append(ResOperation(rop.GETFIELD_GC, [instnode.source], box, ofs)) - newboxlist.append(box) + newboxlist.append((0, box)) class DelayedFixedListSpecNode(DelayedSpecNode): @@ -179,7 +206,7 @@ from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList - newboxlist.append(instnode.source) + newboxlist.append((0, instnode.source)) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr @@ -187,22 +214,22 @@ assert isinstance(subspecnode, SpecNodeWithBox) if oplist is None: instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append(instnode.curfields[ofs].source) + newboxlist.append((0, instnode.curfields[ofs].source)) else: if ofs in instnode.cleanfields: - newboxlist.append(instnode.cleanfields[ofs].source) + newboxlist.append((0, instnode.cleanfields[ofs].source)) else: box = subspecnode.box.clonebox() oplist.append(ResOperation(rop.GETARRAYITEM_GC, [instnode.source, ofs], box, arraydescr)) - newboxlist.append(box) + newboxlist.append((0, box)) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList from pypy.jit.metainterp.history import check_descr - resultlist.append(valuebox) + resultlist.append((0, valuebox)) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr @@ -212,48 +239,77 @@ [valuebox, ofs], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) -class VirtualizableSpecNode(VirtualizedSpecNode): +class VirtualizedSpecNode(VirtualizedOrDelayedSpecNode): def equals(self, other): - if not isinstance(other, VirtualizableSpecNode): + if not self.known_class.equals(other.known_class): return False - return SpecNodeWithFields.equals(self, other) + assert len(self.fields) == len(other.fields) + for i in range(len(self.fields)): + if (isinstance(self.fields[i][1], MatchEverythingSpecNode) or + isinstance(other.fields[i][1], MatchEverythingSpecNode)): + continue + assert self.fields[i][0].equals(other.fields[i][0]) + if not self.fields[i][1].equals(other.fields[i][1]): + return False + return True - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num): instnode.virtualized = True - VirtualizedSpecNode.adapt_to(self, instnode) + fields = [] + for ofs, subspecnode in self.fields: + if isinstance(subspecnode, MatchEverythingSpecNode): + if ofs in instnode.curfields: + orignode = instnode.origfields[ofs] + node = instnode.curfields[ofs] + subspecnode = orignode.intersect(node, {}) + subspecnode.mutate_nodes(orignode) + subspecnode = RedirectingSpecNode(subspecnode, num) + subspecnode.expand_boxlist(orignode, newboxlist, None) + newspecnodes.append(subspecnode) + # otherwise we simply ignore unused field + else: + subspecnode.adapt_to(instnode.curfields[ofs], newboxlist, + newspecnodes, num) + fields.append((ofs, subspecnode)) + self.fields = fields + +class VirtualizableSpecNode(VirtualizedSpecNode): + + def equals(self, other): + if not isinstance(other, VirtualizableSpecNode): + return False + return VirtualizedSpecNode.equals(self, other) class VirtualizableListSpecNode(VirtualizedSpecNode): def equals(self, other): if not isinstance(other, VirtualizableListSpecNode): return False - return SpecNodeWithFields.equals(self, other) + return VirtualizedSpecNode.equals(self, other) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList from pypy.jit.metainterp.history import check_descr - resultlist.append(valuebox) + resultlist.append((0, valuebox)) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr check_descr(arraydescr) for ofs, subspecnode in self.fields: - fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ofs], arraydescr) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - - def adapt_to(self, instnode): - instnode.virtualized = True - VirtualizedSpecNode.adapt_to(self, instnode) + if not isinstance(subspecnode, MatchEverythingSpecNode): + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ofs], arraydescr) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualSpecNode(SpecNodeWithFields): - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num): instnode.virtual = True - SpecNodeWithFields.adapt_to(self, instnode) + return SpecNodeWithFields.adapt_to(self, instnode, newboxlist, + newspecnodes, num) def mutate_nodes(self, instnode): SpecNodeWithFields.mutate_nodes(self, instnode) Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py Wed Mar 18 14:16:20 2009 @@ -394,7 +394,6 @@ assert res == 2 def test_pass_always_virtual_to_bridge(self): - py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) @@ -423,7 +422,6 @@ assert res == 3 def test_virtual_obj_on_always_virtual(self): - py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) @@ -452,7 +450,7 @@ s += frame.l[1].elem frame.l[1] = Stuff(n) n -= 1 - return s + return (frame.l[0].elem << 16) + frame.l[1].elem res = self.meta_interp(f, [30], listops=True) self.check_loops(getfield_gc=0) Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py Wed Mar 18 14:16:20 2009 @@ -10,5 +10,18 @@ def __init__(self, cpu, TOPSTRUCT, STRUCTTYPE): "NOT_RPYTHON" - self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for - name in TOPSTRUCT._hints['virtuals']] + self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for + name in TOPSTRUCT._hints['virtuals']] + self.fields = self.catch_all_fields(cpu, STRUCTTYPE) + + def catch_all_fields(self, cpu, S): + lst = [] + p = S + while True: + lst.extend(p._names) + if getattr(p, 'super', None) is not None: + p = p.super + else: + break + return [cpu.fielddescrof(S, name) for name in lst if + name.startswith('inst_')] From cami at codespeak.net Wed Mar 18 15:07:45 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 18 Mar 2009 15:07:45 +0100 (CET) Subject: [pypy-svn] r63033 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090318140745.30D9016802B@codespeak.net> Author: cami Date: Wed Mar 18 15:07:43 2009 New Revision: 63033 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/test/test_cpu.py pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py Log: optimizing registers Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Wed Mar 18 15:07:43 2009 @@ -272,9 +272,8 @@ self.double_register_inverse_call(CPUPopCaller(self), register) def double_register_inverse_call(self, getCaller, register): - b = getCaller.get() # 1 cycle - a = getCaller.get() # 1 cycle - register.set_hi_lo(a, b) # 2 cycles + register.set_lo(getCaller.get()) # 2 cycles + register.set_hi(getCaller.get()) # 2 cycles self.cycles += 1 def call(self, address, use_cycles=True): @@ -694,9 +693,8 @@ def ret(self): # RET 4 cycles - lo = self.pop() # 1 cycle - hi = self.pop() # 1 cycle - self.pc.set_hi_lo(hi, lo) # 2 cycles + self.pop_double_register(self.pc) + self.cycles -= 1 def conditional_return(self, cc): # RET cc 2,5 cycles Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Wed Mar 18 15:07:43 2009 @@ -1,51 +1,103 @@ # --------------------------------------------------------------------------- class AbstractRegister(object): + def __init__(self): + self.invalid = False + def get(self, use_cycles=True): - return 0xFF + self.check_sync() + return self._get(use_cycles) + + def set(self, value, use_cycles=True): + self.check_sync() + self.invalidate_other() + self._set(value, use_cycles) + + def sub(self, value, use_cycles=True): + self.check_sync() + self.invalidate_other() + return self._sub(value, use_cycles) + + def add(self, value, use_cycles=True): + self.check_sync() + self.invalidate_other() + return self._add(value, use_cycles) + + def _get(self, use_cycles): + raise Exception("not implemented") + + def _set(self, value, use_cycles): + raise Exception("not implemented") + + def _sub(self, value, use_cycles): + raise Exception("not implemented") + + def _add(self, value, use_cycles): + raise Exception("not implemented") + + def check_sync(self): + if self.invalid: + self.sync() + + def invalidate_other(self): + raise Exception("not implemented") + + def sync(self): + raise Exception("not implemented") + class Register(AbstractRegister): def __init__(self, cpu, value=0x00): + AbstractRegister.__init__(self) # assert isinstance(cpu, CPU) self.reset_value = self.value = value + self.double_register = None self.cpu = cpu if value != 0: - self.set(value) + self._set(value) def reset(self): self.value = self.reset_value - def set(self, value, use_cycles=True): + def sync(self): + if self.double_register is not None: + self.double_register.sync_registers() + + def invalidate_other(self): + if self.double_register is not None: + self.double_register.invalid = True + + def _set(self, value, use_cycles=True): self.value = value & 0xFF if use_cycles: self.cpu.cycles -= 1 - def get(self, use_cycles=True): + def _get(self, use_cycles=True): return self.value - def add(self, value, use_cycles=True): - self.set(self.get(use_cycles)+value, use_cycles) + def _add(self, value, use_cycles=True): + self._set(self._get(use_cycles) + value, use_cycles) - def sub(self, value, use_cycles=True): - self.set(self.get(use_cycles)-value, use_cycles) + def _sub(self, value, use_cycles=True): + self._set(self._get(use_cycles) - value, use_cycles) #------------------------------------------------------------------------------ class AbstractDoubleRegister(AbstractRegister): def __init__(self, cpu, reset_value=0): + AbstractRegister.__init__(self) + self.invalid = True self.cpu = cpu self.reset_value = reset_value - - def set(self, value, use_cycles=True): - # 1 Cycle - raise Exception("Not Implemented") - def set_hi_lo(self, hi, lo, use_cycles=True): - # 2 Cycles + def sync_registers(self): raise Exception("Not Implemented") - + + def sync(self): + raise Exception("Not Implemented") + def reset(self): self.set(self.reset_value, use_cycles=False) @@ -57,10 +109,6 @@ # 1 Cycle raise Exception("Not Implemented") - def get(self, use_cycles=True): - # 0 Cycles TODO: Check entanglement of cycles in CPU class. - raise Exception("Not Implemented") - def get_hi(self, use_cycles=True): # 0 Cycles raise Exception("Not Implemented") @@ -79,8 +127,8 @@ if use_cycles: self.cpu.cycles += 1 - def add(self, value, use_cycles=True): - self.set(self.get(use_cycles) + value, use_cycles=use_cycles) + def _add(self, value, use_cycles=True): + self._set(self._get(use_cycles) + value, use_cycles=use_cycles) if use_cycles: self.cpu.cycles -= 2 @@ -90,18 +138,30 @@ def __init__(self, cpu, hi, lo, reset_value=0): AbstractDoubleRegister.__init__(self, cpu, reset_value) self.hi = hi + self.hi.double_register = self self.lo = lo + self.lo.double_register = self + self.value = 0x0000 + + def sync_registers(self): + self.hi._set(self.value >> 8, use_cycles=False) + self.hi.invalid = False + self.lo._set(self.value & 0xFF, use_cycles=False) + self.lo.invalid = False + + def sync(self): + self.value = (self.hi._get(use_cycles=False)<<8) + \ + self.lo._get(use_cycles=False) + self.invalid = False + + def invalidate_other(self): + self.hi.invalid = True + self.lo.invalid = True - def set(self, value, use_cycles=True): - value = value & 0xFFFF - self.set_hi(value >> 8, use_cycles) - self.set_lo(value & 0xFF, use_cycles) + def _set(self, value, use_cycles=True): + self.value = value & 0xFFFF if use_cycles: - self.cpu.cycles += 1 - - def set_hi_lo(self, hi, lo, use_cycles=True): - self.set_hi(hi, use_cycles) - self.set_lo(lo, use_cycles) + self.cpu.cycles -= 1 def set_hi(self, hi=0, use_cycles=True): self.hi.set(hi, use_cycles) @@ -109,8 +169,8 @@ def set_lo(self, lo=0, use_cycles=True): self.lo.set(lo, use_cycles) - def get(self, use_cycles=True): - return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles) + def _get(self, use_cycles=True): + return self.value def get_hi(self, use_cycles=True): return self.hi.get(use_cycles) @@ -157,14 +217,12 @@ return (self.value & 0xFF) def inc(self, use_cycles=True): - self.value += 1 - self.value &= 0xFFFF + self.add(1, use_cycles=False) if use_cycles: self.cpu.cycles -= 2 def dec(self, use_cycles=True): - self.value -= 1 - self.value &= 0xFFFF + self.add(-1, use_cycles=False) if use_cycles: self.cpu.cycles -= 2 @@ -233,8 +291,8 @@ (which do not affect C-flag). """ def __init__(self, cpu, reset_value): + Register.__init__(self, cpu) #assert isinstance(cpu, CPU) - self.cpu = cpu self.reset_value = reset_value self.reset() @@ -264,7 +322,7 @@ self.s_flag = False self.lower = 0x00 - def get(self, use_cycles=True): + def _get(self, use_cycles=True): value = 0 value += (int(self.is_carry) << 4) value += (int(self.is_half_carry) << 5) @@ -272,7 +330,7 @@ value += (int(self.is_zero) << 7) return value + self.lower - def set(self, value, use_cycles=True): + def _set(self, value, use_cycles=True): self.is_carry = bool(value & (1 << 4)) self.is_half_carry = bool(value & (1 << 5)) self.is_subtraction = bool(value & (1 << 6)) Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Wed Mar 18 15:07:43 2009 @@ -38,8 +38,8 @@ self.timer = Timer(self.interrupt) self.joypad = Joypad(self.joypad_driver, self.interrupt) self.video = Video(self.video_driver, self.interrupt, self) - self.sound = Sound(self.sound_driver) - #self.sound = BogusSound() + #self.sound = Sound(self.sound_driver) + self.sound = BogusSound() def get_cartridge_manager(self): return self.cartridge_manager Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Mar 18 15:07:43 2009 @@ -12,10 +12,10 @@ from pypy.lang.gameboy import constants import time -show_metadata = False # Extends the window with windows visualizing meta-data +show_metadata = True # Extends the window with windows visualizing meta-data if constants.USE_RSDL: - from pypy.rlib.rsdl import RSDL, RSDL_helper, RMix + from pypy.rlib.rsdl import RSDL, RSDL_helper #, RMix from pypy.rpython.lltypesystem import lltype, rffi delay = RSDL.Delay get_ticks = RSDL.GetTicks @@ -260,18 +260,20 @@ SoundDriver.__init__(self) self.enabled = False self.sampleRate = 44100 - self.chunksize = 1024 + self.buffersize = 512 self.channelCount = 2 self.bitsPerSample = 4 + self.sampleSize = self.bitsPerSample * self.channelCount self.create_sound_driver() def create_sound_driver(self): - if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, - self.channelCount, self.chunksize) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - else: - self.enabled = True + #if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, + # self.channelCount, self.chunksize) != 0: + # error = rffi.charp2str(RSDL.GetError()) + # raise Exception(error) + #else: + # self.enabled = True + pass def start(self): pass Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu.py Wed Mar 18 15:07:43 2009 @@ -431,7 +431,8 @@ # ld_BCi_A def test_0x02(): cpu = get_cpu(); - cpu.bc.set_hi_lo(0xC2, 0x23); + cpu.bc.set_hi(0xC2) + cpu.bc.set_lo(0x23); cpu.a.set(0x12); cycle_test(cpu, 0x02, 2); assert cpu.read(cpu.bc.get()) == cpu.a.get() @@ -451,7 +452,8 @@ # ld_DEi_A def test_0x12(): cpu = get_cpu(); - cpu.de.set_hi_lo(0xC2, 0x23); + cpu.de.set_hi(0xC2) + cpu.de.set_lo(0x23); cpu.a.set(0x12); cycle_test(cpu, 0x12, 2); assert cpu.read(cpu.de.get()) == cpu.a.get() @@ -470,7 +472,8 @@ # ldi_HLi_A def test_0x22(): cpu = get_cpu(); - cpu.hl.set_hi_lo(0xCD, 0xEF); + cpu.hl.set_hi(0xCD) + cpu.hl.set_lo(0xEF); cpu.a.set(0x12); cycle_test(cpu, 0x22, 2); assert cpu.read(0xCDEF) == cpu.a.get() @@ -479,7 +482,8 @@ # ldd_HLi_A def test_0x32(): cpu = get_cpu(); - cpu.hl.set_hi_lo(0xCD, 0xEF); + cpu.hl.set_hi(0xCD) + cpu.hl.set_lo(0xEF); cpu.a.set(0x12); cycle_test(cpu, 0x32, 2); assert cpu.read(0xCDEF) == cpu.a.get() Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py Wed Mar 18 15:07:43 2009 @@ -26,9 +26,14 @@ TEST_CPU = get_cpu(True) TEST_CPU.reset() return TEST_CPU + +def get_double_register(): + cpu = get_cpu() + return DoubleRegister(cpu, Register(cpu), Register(cpu)) # ------------------------------------------------------------ # TEST REGISTER + def test_register_constructor(): register = Register(get_cpu()) assert register.get() == 0 @@ -103,7 +108,8 @@ valueHi = 0x12 valueLo = 0x34 oldCycles = register.cpu.cycles - register.set_hi_lo(valueHi, valueLo) + register.set_hi(valueHi) + register.set_lo(valueLo) assert oldCycles-register.cpu.cycles == 2 assert register.get_hi() == valueHi assert register.get_lo() == valueLo @@ -207,7 +213,8 @@ valueHi = 0x12 valueLo = 0x34 oldCycles = register.cpu.cycles - register.set_hi_lo(valueHi, valueLo) + register.set_hi(valueHi) + register.set_lo(valueLo) assert oldCycles-register.cpu.cycles == 2 assert register.get_hi() == valueHi assert register.get_lo() == valueLo @@ -265,4 +272,81 @@ assert register.get() == value+1; register.reset() assert register.get() == value + +# TEST REGISTER SYNCING ----------------------------------------------------- +def test_register_sync(): + double_register = get_double_register() + assert double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + return double_register + +def test_register_sync_get(): + double_register = test_register_sync() + + double_register.get() + + assert not double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set(): + double_register = test_register_sync() + + double_register.set(0xFFFF) + + assert not double_register.invalid + assert double_register.hi.invalid + assert double_register.lo.invalid + + return double_register + + +def test_register_sync_set_get(): + double_register = test_register_sync_set() + + assert double_register.get() == 0xFFFF + + assert not double_register.invalid + assert double_register.hi.invalid + assert double_register.lo.invalid + + +def test_register_sync_set_get_hi(): + double_register = test_register_sync_set() + + assert double_register.hi.get() == 0xFF + + assert not double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set_get_lo(): + double_register = test_register_sync_set() + + assert double_register.lo.get() == 0xFF + + assert not double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set_hi(): + double_register = test_register_sync() + double_register.hi.set(0x12) + + assert double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set_lo(): + double_register = test_register_sync() + double_register.lo.set(0x12) + + assert double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid \ No newline at end of file From tverwaes at codespeak.net Wed Mar 18 15:38:10 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 18 Mar 2009 15:38:10 +0100 (CET) Subject: [pypy-svn] r63035 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090318143810.15BFD168453@codespeak.net> Author: tverwaes Date: Wed Mar 18 15:38:06 2009 New Revision: 63035 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py Log: reverting changes from yesterday. Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Wed Mar 18 15:38:06 2009 @@ -1,4 +1,4 @@ -from pypy.rlib.objectmodel import we_are_translated + from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ @@ -66,10 +66,9 @@ self.ime = False self.halted = False self.cycles = 0 - if not we_are_translated(): - self.instruction_counter = 0 - self.last_op_code = -1 - self.last_fetch_execute_op_code = -1 + self.instruction_counter = 0 + self.last_op_code = -1 + self.last_fetch_execute_op_code = -1 def reset_registers(self): self.a.reset() @@ -160,6 +159,12 @@ def is_not_c(self): return not self.is_c() + def is_not_h(self): + return not self.is_h() + + def is_not_n(self): + return not self.is_n() + def set_rom(self, banks): self.rom = banks @@ -199,15 +204,13 @@ def fetch_execute(self): op_code = self.fetch() - if not we_are_translated(): - self.last_fetch_execute_op_code = op_code + self.last_fetch_execute_op_code = op_code FETCH_EXECUTE_OP_CODES[op_code](self) def execute(self, op_code): - if not we_are_translated(): - self.instruction_counter += 1 - self.last_op_code = op_code + self.instruction_counter += 1 + self.last_op_code = op_code OP_CODES[op_code](self) @@ -249,6 +252,7 @@ def fetch_double_register(self, register): self.double_register_inverse_call(CPUFetchCaller(self), register) + self.cycles += 1 def push(self, data, use_cycles=True): # Stack, 2 cycles @@ -270,11 +274,11 @@ def pop_double_register(self, register): # 3 cycles self.double_register_inverse_call(CPUPopCaller(self), register) + self.cycles += 1 def double_register_inverse_call(self, getCaller, register): register.set_lo(getCaller.get()) # 2 cycles register.set_hi(getCaller.get()) # 2 cycles - self.cycles += 1 def call(self, address, use_cycles=True): # 4 cycles @@ -309,11 +313,11 @@ def add_hl(self, register): # 2 cycles data = register.get() - old = self.hl.get() - new = old + data + added = (self.hl.get() + data) # 1 cycle self.flag.partial_reset(keep_is_zero=True) - self.double_register_check(old, new, False) - self.hl.set(new) + self.flag.is_half_carry = (((added ^ self.hl.get() ^ data) & 0x1000) != 0) + self.flag.is_carry = (added >= 0x10000 or added < 0) + self.hl.set(added & 0xFFFF) self.cycles -= 1 def add_a_with_carry(self, getCaller, setCaller=None): @@ -335,7 +339,7 @@ self.flag.is_half_carry = (((s ^ self.a.get() ^ data) & 0x10) != 0) self.flag.is_carry = (s > 0xFF or s < 0) self.flag.zero_check(s) - self.a.set(s) # 1 cycle + self.a.set(s & 0xFF) # 1 cycle def subtract_a(self, getCaller, setCaller=None): # 1 cycle @@ -354,19 +358,17 @@ self.compare_a_simple(getCaller.get()) def compare_a_simple(self, s): - s = self.a.get() - s + s = (self.a.get() - s) & 0xFF self.flag.reset() - self.flag.zero_check(s) self.flag.is_subtraction = True - self.check_carry(self.a.get(), s) + self.flag.zero_check(s) + self.subtract_his_carry_finish(s) self.cycles -= 1 - def check_carry(self, big, small): - # Overflow - self.flag.is_carry = ((small & 0xFF) > (big & 0xFF)) - # Overflow in lower byte - self.flag.is_half_carry = ((small & 0x0F) > (big & 0x0F)) - + def subtract_his_carry_finish(self, data): + self.flag.is_carry = (data > self.a.get()) + self.flag.is_half_carry_compare(data, self.a.get()) + def and_a(self, getCaller, setCaller=None): # 1 cycle self.a.set(self.a.get() & getCaller.get()) # 1 cycle @@ -376,7 +378,7 @@ def xor_a(self, getCaller, setCaller=None): # 1 cycle - self.a.set(self.a.get() ^ getCaller.get()) # 1 cycle + self.a.set( self.a.get() ^ getCaller.get()) # 1 cycle self.flag.reset() self.flag.zero_check(self.a.get()) @@ -396,12 +398,12 @@ def inc(self, getCaller, setCaller): # 1 cycle - data = getCaller.get() + 1 + data = (getCaller.get() + 1) & 0xFF self.dec_inis_carry_finish(data, setCaller, 0x00) def dec(self, getCaller, setCaller): # 1 cycle - data = getCaller.get() - 1 + data = (getCaller.get() - 1) & 0xFF self.dec_inis_carry_finish(data, setCaller, 0x0F) self.flag.is_subtraction = True @@ -450,7 +452,7 @@ data = getCaller.get() s = (data >> 1) if self.flag.is_carry: - s += 0x80 + s += 0x80 self.flags_and_setter_finish(s, data, setCaller) # 1 cycle def rotate_right_a(self): @@ -487,7 +489,7 @@ def swap(self, getCaller, setCaller): # 1 cycle data = getCaller.get() - s = ((data & 0x0F) << 4) + ((data & 0xF0) >> 4) + s = ((data << 4) + (data >> 4)) & 0xFF self.flag.reset() self.flag.zero_check(s) setCaller.set(s) @@ -545,7 +547,7 @@ def store_expanded_c_in_a(self): # LDH A,(C) 2 cycles - self.a.set(self.read(0xFF00 + self.c.get())) # 1+2 cycles + self.a.set(self.read(0xFF00 + self.bc.get_lo())) # 1+2 cycles def load_and_increment_a_hli(self): # loadAndIncrement A,(HL) 2 cycles @@ -590,33 +592,27 @@ self.flag.is_subtraction = True self.flag.is_half_carry = True - def decimal_adjust_byte(self, byte, flag): - # [1 1 X X] or [1 0 1 X] at least - # or flag set: [0 1 1 0] - return ((byte & 0xF) > 0x9 | flag) * 0x6 - - def negate_if_subtraction(self, value): - # Flip the sign-bit of the 8-bit value. - return (self.flag.is_subtraction * 0x80) ^ value - def decimal_adjust_a(self): # DAA 1 cycle delta = 0 - - a = process_2s_complement(self.a.get()) - - delta |= self.decimal_adjust_byte(a >> 4, self.is_c()) << 4 - delta |= self.decimal_adjust_byte(a, self.is_h()) - - if (a < 0) and ((a & 0xF) > 0x9): + if self.is_h(): + delta |= 0x06 + if self.is_c(): delta |= 0x60 - - self.a.add(self.negate_if_subtraction(delta)) # 1 cycle - + if (self.a.get() & 0x0F) > 0x09: + delta |= 0x06 + if (self.a.get() & 0xF0) > 0x80: + delta |= 0x60 + if (self.a.get() & 0xF0) > 0x90: + delta |= 0x60 + if not self.is_n(): + self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle + else: + self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle self.flag.partial_reset(keep_is_subtraction=True) - self.flag.zero_check(self.a.get()) if delta >= 0x60: self.flag.is_carry = True + self.flag.zero_check(self.a.get()) def increment_sp_by_fetch(self): # ADD SP,nn 4 cycles @@ -631,18 +627,18 @@ def get_fetchadded_sp(self): # 1 cycle offset = process_2s_complement(self.fetch()) # 1 cycle - old = self.sp.get() - new = old + offset - + s = (self.sp.get() + offset) & 0xFFFF self.flag.reset() - self.double_register_check(old, new, offset < 0) - return new - - def double_register_check(self, old, new, subtraction): - if subtraction: - new, old = old, new - self.check_carry(new >> 8, old >> 8) - + if (offset >= 0): + self.flag.is_carry = (s < self.sp.get()) + if (s & 0x0F00) < (self.sp.get() & 0x0F00): + self.flag.is_half_carry = True + else: + self.flag.is_carry = (s > self.sp.get()) + if (s & 0x0F00) > (self.sp.get() & 0x0F00): + self.flag.is_half_carry = True + return s + def complement_carry_flag(self): # CCF/SCF self.flag.partial_reset(keep_is_zero=True, keep_is_carry=True) @@ -693,8 +689,7 @@ def ret(self): # RET 4 cycles - self.pop_double_register(self.pc) - self.cycles -= 1 + self.double_register_inverse_call(CPUPopCaller(self), self.pc) def conditional_return(self, cc): # RET cc 2,5 cycles Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Wed Mar 18 15:38:06 2009 @@ -346,3 +346,6 @@ if reset: self.reset() self.is_carry = ((value & compare_and) != 0) + + def is_half_carry_compare(self, new, old): + self.is_half_carry = (old & 0x0F) < (new & 0x0F) From iko at codespeak.net Wed Mar 18 15:48:21 2009 From: iko at codespeak.net (iko at codespeak.net) Date: Wed, 18 Mar 2009 15:48:21 +0100 (CET) Subject: [pypy-svn] r63036 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090318144821.8621E168453@codespeak.net> Author: iko Date: Wed Mar 18 15:48:20 2009 New Revision: 63036 Modified: pypy/trunk/pypy/objspace/std/test/test_set.py Log: (iko, pedronis) fix recursive set test fragility Modified: pypy/trunk/pypy/objspace/std/test/test_set.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_set.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_set.py Wed Mar 18 15:48:20 2009 @@ -81,9 +81,11 @@ s = set([1, 2, 3]) s.add(A(s)) - # xxx this seems to have order dependency issues - # "set([set(...), 1, 2, 3])" has been spotted too - assert repr(s) == "set([1, 2, 3, set(...)])" + therepr = repr(s) + assert therepr.startswith("set([") + assert therepr.endswith("])") + inner = set(therepr[5:-2].split(", ")) + assert inner == set(["1", "2", "3", "set(...)"]) def test_recursive_repr_frozenset(self): class A(object): @@ -92,9 +94,11 @@ a = A() s = frozenset([1, 2, 3, a]) a.s = s - # xxx this seems to have order dependency issues - # "frozenset([frozenset(...), 1, 2, 3])" has been spotted too - assert repr(s) == "frozenset([1, 2, 3, frozenset(...)])" + therepr = repr(s) + assert therepr.startswith("frozenset([") + assert therepr.endswith("])") + inner = set(therepr[11:-2].split(", ")) + assert inner == set(["1", "2", "3", "frozenset(...)"]) def test_keyerror_has_key(self): s = set() From fijal at codespeak.net Wed Mar 18 15:51:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 18 Mar 2009 15:51:39 +0100 (CET) Subject: [pypy-svn] r63037 - pypy/branch/virtualizable-specnodes/pypy/jit/metainterp Message-ID: <20090318145139.68BAB168459@codespeak.net> Author: fijal Date: Wed Mar 18 15:51:38 2009 New Revision: 63037 Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py Log: Remove terrible hacks by creating a BoxRetriever class Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py Wed Mar 18 15:51:38 2009 @@ -6,7 +6,7 @@ VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, DelayedSpecNode, SpecNodeWithBox, DelayedFixedListSpecNode, VirtualFixedListSpecNode, MatchEverythingSpecNode, - VirtualizableListSpecNode, av_eq, av_hash) + VirtualizableListSpecNode, av_eq, av_hash, BoxRetriever) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype, llmemory @@ -503,19 +503,13 @@ def expanded_version_of(self, boxlist, oplist): # oplist is None means at the start - newboxlist = [] + newboxes = BoxRetriever() assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) - l = [] - for i, (group, arg) in enumerate(newboxlist): - l.append((group, i, arg)) - l.sort() - return [e[2] for e in l] - - return newboxlist + specnode.expand_boxlist(self.nodes[box], newboxes, oplist) + return newboxes.flatten() def deal_with_boxes(self, boxes): storage = AllocationStorage() @@ -836,14 +830,13 @@ old_mp = old_operations[0] jump_op = self.loop.operations[-1] self.specnodes = old_mp.specnodes - newboxlist = [] + newboxlist = BoxRetriever() extensions = [] for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode, newboxlist, extensions, num) - newboxlist = [i for _, i in newboxlist] - return newboxlist, extensions + return newboxlist.flatten(), extensions class Chooser(object): def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists): Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py Wed Mar 18 15:51:38 2009 @@ -17,6 +17,7 @@ from pypy.jit.metainterp import codewriter, optimize, executor from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize +from pypy.jit.metainterp.specnode import BoxRetriever # ____________________________________________________________ @@ -894,15 +895,11 @@ if mp.specnodes is None: # it is None only for tests return args assert len(mp.specnodes) == len(args) - expanded_args = [] + expanded_args = BoxRetriever() for i in range(len(mp.specnodes)): specnode = mp.specnodes[i] specnode.extract_runtime_data(self.cpu, args[i], expanded_args) - l = [] - for i, (group, arg) in enumerate(expanded_args): - l.append((group, i, arg)) - l.sort() - return [e[2] for e in l] + return expanded_args.flatten() def _initialize_from_start(self, original_boxes, num_green_args, *args): if args: Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py Wed Mar 18 15:51:38 2009 @@ -8,13 +8,35 @@ def av_hash(self): return self.sort_key() +class BoxRetriever(object): + def __init__(self): + self.lists = [[]] + self.current = self.lists[0] + + def flatten(self): + res = self.lists[0] + for i in range(1, len(self.lists)): + res.extend(self.lists[i]) + return res + + def extend(self, group): + while len(self.lists) <= group: + self.lists.append([]) + self.current = self.lists[group] + + def append(self, box): + self.current.append(box) + + def reset(self): + self.current = self.lists[0] + class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist, start): - newboxlist.append((0, instnode.source)) + def expand_boxlist(self, instnode, newboxes, start): + newboxes.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): - resultlist.append((0, valuebox)) + resultlist.append(valuebox) def adapt_to(self, instnode, newboxlist, newspecnodes, num): instnode.escaped = True @@ -33,15 +55,15 @@ self.redirect_to = specnode self.group = group - def expand_boxlist(self, instnode, newboxlist, start): - l = [] - self.redirect_to.expand_boxlist(instnode, l, start) - newboxlist.extend([(self.group, e) for _, e in l]) - - def extract_runtime_data(self, cpu, valuebox, resultlist): - l = [] - self.redirect_to.extract_runtime_data(cpu, valuebox, l) - resultlist.extend([(self.group, e) for _, e in l]) + def expand_boxlist(self, instnode, newboxes, start): + newboxes.extend(self.group) + self.redirect_to.expand_boxlist(instnode, newboxes, start) + newboxes.reset() + + def extract_runtime_data(self, cpu, valuebox, result): + result.extend(self.group) + self.redirect_to.extract_runtime_data(cpu, valuebox, result) + result.reset() def adapt_to(self, *args): self.redirect_to.adapt_to(*args) @@ -167,11 +189,11 @@ class VirtualizedOrDelayedSpecNode(SpecNodeWithFields): def expand_boxlist(self, instnode, newboxlist, start): - newboxlist.append((0, instnode.source)) + newboxlist.append(instnode.source) SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): - resultlist.append((0, valuebox)) + resultlist.append(valuebox) SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist) def adapt_to(self, instnode, newboxlist, newspecnodes, num): @@ -183,21 +205,21 @@ def expand_boxlist(self, instnode, newboxlist, oplist): from pypy.jit.metainterp.history import AbstractDescr - newboxlist.append((0, instnode.source)) + newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: assert isinstance(subspecnode, SpecNodeWithBox) if oplist is None: instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append((0, instnode.curfields[ofs].source)) + newboxlist.append(instnode.curfields[ofs].source) else: if ofs in instnode.cleanfields: - newboxlist.append((0, instnode.cleanfields[ofs].source)) + newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() assert isinstance(ofs, AbstractDescr) oplist.append(ResOperation(rop.GETFIELD_GC, [instnode.source], box, ofs)) - newboxlist.append((0, box)) + newboxlist.append(box) class DelayedFixedListSpecNode(DelayedSpecNode): @@ -206,7 +228,7 @@ from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList - newboxlist.append((0, instnode.source)) + newboxlist.append(instnode.source) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr @@ -214,22 +236,22 @@ assert isinstance(subspecnode, SpecNodeWithBox) if oplist is None: instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append((0, instnode.curfields[ofs].source)) + newboxlist.append(instnode.curfields[ofs].source) else: if ofs in instnode.cleanfields: - newboxlist.append((0, instnode.cleanfields[ofs].source)) + newboxlist.append(instnode.cleanfields[ofs].source) else: box = subspecnode.box.clonebox() oplist.append(ResOperation(rop.GETARRAYITEM_GC, [instnode.source, ofs], box, arraydescr)) - newboxlist.append((0, box)) + newboxlist.append(box) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.optimize import FixedList from pypy.jit.metainterp.history import check_descr - resultlist.append((0, valuebox)) + resultlist.append(valuebox) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr @@ -293,7 +315,7 @@ from pypy.jit.metainterp.optimize import FixedList from pypy.jit.metainterp.history import check_descr - resultlist.append((0, valuebox)) + resultlist.append(valuebox) cls = self.known_class assert isinstance(cls, FixedList) arraydescr = cls.arraydescr From tverwaes at codespeak.net Wed Mar 18 16:20:41 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 18 Mar 2009 16:20:41 +0100 (CET) Subject: [pypy-svn] r63038 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090318152041.8902116845F@codespeak.net> Author: tverwaes Date: Wed Mar 18 16:20:38 2009 New Revision: 63038 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/cpu_register.py pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py Log: we keep on using ReservedDoubleRegisters (FastDoubleRegisters) for sp and pc but shadowed versions for the rest. we should really check if this is useful in the end... Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Wed Mar 18 16:20:38 2009 @@ -2,7 +2,7 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ - FastDoubleRegister, \ + ReservedDoubleRegister,\ FlagRegister, ImmediatePseudoRegister # --------------------------------------------------------------------------- @@ -51,8 +51,8 @@ self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = FastDoubleRegister(self, reset_value=constants.RESET_PC) - self.sp = FastDoubleRegister(self, reset_value=constants.RESET_SP) + self.pc = ReservedDoubleRegister(self, reset_value=constants.RESET_PC) + self.sp = ReservedDoubleRegister(self, reset_value=constants.RESET_SP) self.a = Register(self, constants.RESET_A) self.flag = FlagRegister(self, constants.RESET_F) Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu_register.py Wed Mar 18 16:20:38 2009 @@ -84,65 +84,22 @@ #------------------------------------------------------------------------------ -class AbstractDoubleRegister(AbstractRegister): +class DoubleRegister(AbstractRegister): - def __init__(self, cpu, reset_value=0): + def __init__(self, cpu, hi, lo, reset_value=0x0000): AbstractRegister.__init__(self) - self.invalid = True self.cpu = cpu + self.invalid = True self.reset_value = reset_value - - def sync_registers(self): - raise Exception("Not Implemented") - - def sync(self): - raise Exception("Not Implemented") - - def reset(self): - self.set(self.reset_value, use_cycles=False) - - def set_hi(self, hi=0, use_cycles=True): - # 1 Cycle - raise Exception("Not Implemented") - - def set_lo(self, lo=0, use_cycles=True): - # 1 Cycle - raise Exception("Not Implemented") - - def get_hi(self, use_cycles=True): - # 0 Cycles - raise Exception("Not Implemented") - - def get_lo(self, use_cycles=True): - # 0 Cycles - raise Exception("Not Implemented") - - def inc(self, use_cycles=True): - self.add(1, use_cycles) - if use_cycles: - self.cpu.cycles += 1 - - def dec(self, use_cycles=True): - self.add(-1, use_cycles) - if use_cycles: - self.cpu.cycles += 1 - - def _add(self, value, use_cycles=True): - self._set(self._get(use_cycles) + value, use_cycles=use_cycles) - if use_cycles: - self.cpu.cycles -= 2 - - -class DoubleRegister(AbstractDoubleRegister): - - def __init__(self, cpu, hi, lo, reset_value=0): - AbstractDoubleRegister.__init__(self, cpu, reset_value) self.hi = hi - self.hi.double_register = self self.lo = lo + self.hi.double_register = self self.lo.double_register = self self.value = 0x0000 + def reset(self): + self.set(self.reset_value, use_cycles=False) + def sync_registers(self): self.hi._set(self.value >> 8, use_cycles=False) self.hi.invalid = False @@ -177,44 +134,55 @@ def get_lo(self, use_cycles=True): return self.lo.get(use_cycles) - -class FastDoubleRegister(AbstractDoubleRegister): - - def __init__(self, cpu, reset_value=0): - AbstractDoubleRegister.__init__(self, cpu, reset_value) - self.value = 0x0000 + def inc(self, use_cycles=True): + self.add(1, use_cycles=False) + if use_cycles: + self.cpu.cycles -= 2 - def set(self, value, use_cycles=True): - self.value = value & 0xFFFF + def dec(self, use_cycles=True): + self.add(-1, use_cycles=False) if use_cycles: - self.cpu.cycles -= 1 + self.cpu.cycles -= 2 + + def _add(self, value, use_cycles=True): + self.value += value + self.value &= 0xFFFF + if use_cycles: + self.cpu.cycles -= 3 + +#------------------------------------------------------------------------------ + +class ReservedDoubleRegister(AbstractRegister): - def set_hi_lo(self, hi, lo, use_cycles=True): - hi &= 0xFF - lo &= 0xFF - self.set((hi << 8) + lo, use_cycles) + def __init__(self, cpu, reset_value=0x0000): + AbstractRegister.__init__(self) + self.cpu = cpu + self.reset_value = reset_value + self.value = 0x0000 + + def reset(self): + self.set(self.reset_value, use_cycles=False) + + def set(self, value, use_cycles=True): + self.value = value & 0xFFFF if use_cycles: self.cpu.cycles -= 1 def set_hi(self, hi=0, use_cycles=True): - self.set_hi_lo(hi, self.get_lo(False), use_cycles) - if use_cycles: - self.cpu.cycles += 1 + self.set((hi << 8) + (self.value & 0xFF)) def set_lo(self, lo=0, use_cycles=True): - self.set_hi_lo(self.get_hi(False), lo, use_cycles) - if use_cycles: - self.cpu.cycles += 1 + self.set((self.value & 0xFF00) + (lo & 0xFF)) def get(self, use_cycles=True): return self.value def get_hi(self, use_cycles=True): - return (self.value >> 8) + return (self.value >> 8) & 0xFF def get_lo(self, use_cycles=True): - return (self.value & 0xFF) + return self.value & 0xFF def inc(self, use_cycles=True): self.add(1, use_cycles=False) @@ -232,6 +200,7 @@ if use_cycles: self.cpu.cycles -= 3 + # ------------------------------------------------------------------------------ class ImmediatePseudoRegister(Register): Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py Wed Mar 18 16:20:38 2009 @@ -168,111 +168,7 @@ register.reset() assert register.get() == value -# ------------------------------------------------------------ -# TEST FAST DOUBLE REGISTER - -def test_fast_double_register_constructor(): - cpu = get_cpu() - register = FastDoubleRegister(cpu) - assert register.get() == 0 - assert register.get_hi() == 0 - assert register.get_lo() == 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.get_hi() == reg1.get() - assert register.get_lo() == reg2.get() - -def test_fast_double_register(): - cpu = get_cpu() - register = FastDoubleRegister(cpu) - value = 0x1234 - oldCycles = register.cpu.cycles - register.set(value) - assert oldCycles-register.cpu.cycles == 1 - assert register.get() == value - -def test_fast_double_register_bounds(): - cpu = get_cpu() - register = FastDoubleRegister(cpu) - value = 0xFFFF1234 - register.set(value) - assert register.get() == 0x1234 - register.set(0) - assert register.get() == 0 - -def test_fast_double_register_hilo(): - cpu = get_cpu() - register = FastDoubleRegister(cpu) - value = 0x1234 - valueHi = 0x12 - valueLo = 0x34 - oldCycles = register.cpu.cycles - register.set_hi(valueHi) - register.set_lo(valueLo) - assert oldCycles-register.cpu.cycles == 2 - assert register.get_hi() == valueHi - assert register.get_lo() == valueLo - assert register.get() == value - - valueHi = 0x56 - oldCycles = register.cpu.cycles - register.set_hi(valueHi) - assert oldCycles-register.cpu.cycles == 1 - assert register.get_hi() == valueHi - assert register.get_lo() == valueLo - - valueLo = 0x78 - oldCycles = register.cpu.cycles - register.set_lo(valueLo) - assert oldCycles-register.cpu.cycles == 1 - assert register.get_hi() == valueHi - assert register.get_lo() == valueLo - - -def test_fast_double_register_methods(): - value = 0x1234 - cpu = get_cpu() - register = FastDoubleRegister(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_fast_double_register_reset(): - value = 0x1234; - cpu = get_cpu() - register = FastDoubleRegister(cpu, reset_value = value) - register.set(value+1) - assert register.get() == value+1; - register.reset() - assert register.get() == value - + # TEST REGISTER SYNCING ----------------------------------------------------- def test_register_sync(): @@ -349,4 +245,4 @@ assert double_register.invalid assert not double_register.hi.invalid - assert not double_register.lo.invalid \ No newline at end of file + assert not double_register.lo.invalid From pedronis at codespeak.net Wed Mar 18 16:34:26 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 18 Mar 2009 16:34:26 +0100 (CET) Subject: [pypy-svn] r63039 - pypy/trunk/pypy/translator/c Message-ID: <20090318153426.50EA2168466@codespeak.net> Author: pedronis Date: Wed Mar 18 16:34:25 2009 New Revision: 63039 Modified: pypy/trunk/pypy/translator/c/genc.py Log: (iko, pedronis) fix the failure in test_ll_thread.py:TestUsingBoehm().test_gc_locking our "thread.h" needs to be included after gc.h and its controlling defines Modified: pypy/trunk/pypy/translator/c/genc.py ============================================================================== --- pypy/trunk/pypy/translator/c/genc.py (original) +++ pypy/trunk/pypy/translator/c/genc.py Wed Mar 18 16:34:25 2009 @@ -781,9 +781,9 @@ print >> fi, '#define Py_BUILD_CORE /* for Windows: avoid pulling libs in */' print >> fi, '#include "pyconfig.h"' - print >> fi, '#include "src/g_prerequisite.h"' eci.write_c_header(fi) + print >> fi, '#include "src/g_prerequisite.h"' fi.close() @@ -833,9 +833,9 @@ print >> fi, '#define %s %s' % (key, value) print >> fi, '#include "pyconfig.h"' - print >> fi, '#include "src/g_prerequisite.h"' eci.write_c_header(fi) + print >> fi, '#include "src/g_prerequisite.h"' fi.close() From pedronis at codespeak.net Wed Mar 18 17:07:25 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 18 Mar 2009 17:07:25 +0100 (CET) Subject: [pypy-svn] r63041 - pypy/build/bot2/pypybuildbot Message-ID: <20090318160725.E5BBA1683E3@codespeak.net> Author: pedronis Date: Wed Mar 18 17:07:25 2009 New Revision: 63041 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: (iko, pedronis) increase the timeout for our own test even more as a stop gap for now, we will need to do something temporary for rsocket or it will take all the three hours Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Wed Mar 18 17:07:25 2009 @@ -102,7 +102,7 @@ "--logfile=testrun.log", "--config=pypy/testrunner_cfg.py", "--config=~/machine_cfg.py", - "--root=pypy", "--timeout=3600"], + "--root=pypy", "--timeout=10800"], logfiles={'pytestLog': 'testrun.log'}, timeout = 4000, env={"PYTHONPATH": ['.']})) From pedronis at codespeak.net Wed Mar 18 17:19:31 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 18 Mar 2009 17:19:31 +0100 (CET) Subject: [pypy-svn] r63042 - pypy/trunk/pypy/rlib/test Message-ID: <20090318161931.9CE961683E3@codespeak.net> Author: pedronis Date: Wed Mar 18 17:19:29 2009 New Revision: 63042 Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py Log: (iko, pedronis) skip this one for now on wyvern where it hangs Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rsocket.py (original) +++ pypy/trunk/pypy/rlib/test/test_rsocket.py Wed Mar 18 17:19:29 2009 @@ -179,6 +179,9 @@ s2.close() def test_simple_udp(): + if cpy_socket.gethostname() == 'wyvern': + py.test.skip("this is currently hanging on wyvern") + s1 = RSocket(AF_INET, SOCK_DGRAM) try_ports = [1023] + range(20000, 30000, 437) for port in try_ports: From afa at codespeak.net Wed Mar 18 17:21:13 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Mar 2009 17:21:13 +0100 (CET) Subject: [pypy-svn] r63043 - pypy/trunk/pypy/objspace/std Message-ID: <20090318162113.B64AE1683F5@codespeak.net> Author: afa Date: Wed Mar 18 17:21:13 2009 New Revision: 63043 Modified: pypy/trunk/pypy/objspace/std/fake.py Log: Give a better assertion message when an object cannot be faked on top of py.py (because of a missing --withmod-_socket, for example) Modified: pypy/trunk/pypy/objspace/std/fake.py ============================================================================== --- pypy/trunk/pypy/objspace/std/fake.py (original) +++ pypy/trunk/pypy/objspace/std/fake.py Wed Mar 18 17:21:13 2009 @@ -105,7 +105,7 @@ baseobjspace.W_Root, argument.Arguments]) if cpy_type.__base__ is not object: - assert cpy_type.__base__ is basestring + assert cpy_type.__base__ is basestring, cpy_type from pypy.objspace.std.basestringtype import basestring_typedef base = basestring_typedef else: From afa at codespeak.net Wed Mar 18 17:23:05 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Mar 2009 17:23:05 +0100 (CET) Subject: [pypy-svn] r63044 - pypy/trunk/pypy/lib Message-ID: <20090318162305.125A516846A@codespeak.net> Author: afa Date: Wed Mar 18 17:23:04 2009 New Revision: 63044 Modified: pypy/trunk/pypy/lib/pyexpat.py Log: Typo: UseForeignDTD should call XML_UseForeignDTD... Modified: pypy/trunk/pypy/lib/pyexpat.py ============================================================================== --- pypy/trunk/pypy/lib/pyexpat.py (original) +++ pypy/trunk/pypy/lib/pyexpat.py Wed Mar 18 17:23:04 2009 @@ -427,7 +427,7 @@ flag = XML_TRUE else: flag = XML_FALSE - XML_SetParamEntityParsing(self.itself, flag) + XML_UseForeignDTD(self.itself, flag) def __getattr__(self, name): if name == 'buffer_text': From afa at codespeak.net Wed Mar 18 17:24:58 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Mar 2009 17:24:58 +0100 (CET) Subject: [pypy-svn] r63045 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090318162458.21F1B16846D@codespeak.net> Author: afa Date: Wed Mar 18 17:24:57 2009 New Revision: 63045 Modified: pypy/trunk/pypy/module/pyexpat/__init__.py pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: Make it pass test_sax. Modified: pypy/trunk/pypy/module/pyexpat/__init__.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/__init__.py (original) +++ pypy/trunk/pypy/module/pyexpat/__init__.py Wed Mar 18 17:24:57 2009 @@ -16,3 +16,8 @@ 'ErrorString': 'interp_pyexpat.ErrorString', } + for name in ['XML_PARAM_ENTITY_PARSING_NEVER', + 'XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE', + 'XML_PARAM_ENTITY_PARSING_ALWAYS']: + interpleveldefs[name] = 'space.wrap(interp_pyexpat.%s)' % (name,) + Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Wed Mar 18 17:24:57 2009 @@ -44,6 +44,10 @@ ('type', rffi.INT), ('quant', rffi.INT), ]) + for name in ['XML_PARAM_ENTITY_PARSING_NEVER', + 'XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE', + 'XML_PARAM_ENTITY_PARSING_ALWAYS']: + locals()[name] = rffi_platform.ConstantInteger(name) XML_COMBINED_VERSION = rffi_platform.ConstantInteger('XML_COMBINED_VERSION') XML_FALSE = rffi_platform.ConstantInteger('XML_FALSE') XML_TRUE = rffi_platform.ConstantInteger('XML_TRUE') @@ -174,22 +178,27 @@ post_code = '' src = py.code.Source(""" - def handler(ll_userdata, %(args)s): + def %(name)s_callback(ll_userdata, %(args)s): id = rffi.cast(lltype.Signed, ll_userdata) userdata = global_storage.get_object(id) space = userdata.space parser = userdata.parser + handler = parser.handlers[%(index)s] + if not handler: + return %(result_error)s + try: %(converters)s %(pre_code)s - w_result = space.call_function(parser.handlers[%(index)s], %(wargs)s) + w_result = space.call_function(handler, %(wargs)s) %(post_code)s except OperationError, e: parser._exc_info = e XML_StopParser(parser.itself, XML_FALSE) return %(result_error)s return %(result_converter)s + callback = %(name)s_callback """ % locals()) exec str(src) @@ -199,7 +208,7 @@ [rffi.VOIDP] + params, result_type)) func = expat_external(c_name, [XML_Parser, callback_type], lltype.Void) - SETTERS[name] = (index, func, handler) + SETTERS[name] = (index, func, callback) ENUMERATE_SETTERS = unrolling_iterable(SETTERS.items()) @@ -222,6 +231,10 @@ 'XML_SetReturnNSTriplet', [XML_Parser, rffi.INT], lltype.Void) XML_GetSpecifiedAttributeCount = expat_external( 'XML_GetSpecifiedAttributeCount', [XML_Parser], rffi.INT) +XML_SetParamEntityParsing = expat_external( + 'XML_SetParamEntityParsing', [XML_Parser, rffi.INT], lltype.Void) +XML_SetBase = expat_external( + 'XML_SetBase', [XML_Parser, rffi.CCHARP], lltype.Void) if XML_COMBINED_VERSION >= 19505: XML_UseForeignDTD = expat_external( 'XML_UseForeignDTD', [XML_Parser, rffi.INT], lltype.Void) @@ -242,10 +255,14 @@ XML_FreeContentModel = expat_external( 'XML_FreeContentModel', [XML_Parser, lltype.Ptr(XML_Content)], lltype.Void) +XML_ExternalEntityParserCreate = expat_external( + 'XML_ExternalEntityParserCreate', [XML_Parser, rffi.CCHARP, rffi.CCHARP], + XML_Parser) class W_XMLParserType(Wrappable): - def __init__(self, encoding, namespace_separator, w_intern): + def __init__(self, encoding, namespace_separator, w_intern, + _from_external_entity=False): if encoding: self.encoding = encoding else: @@ -258,10 +275,16 @@ self.ordered_attributes = False self.specified_attributes = False - if namespace_separator: - self.itself = XML_ParserCreateNS(self.encoding, namespace_separator) - else: - self.itself = XML_ParserCreate(self.encoding) + if not _from_external_entity: + if namespace_separator: + self.itself = XML_ParserCreateNS( + self.encoding, + rffi.cast(rffi.CHAR, namespace_separator)) + else: + self.itself = XML_ParserCreate(self.encoding) + if not self.itself: + raise OperationError(space.w_RuntimeError, + space.wrap('XML_ParserCreate failed')) self.handlers = [None] * NB_HANDLERS @@ -279,6 +302,16 @@ global_storage.free_nonmoving_id( rffi.cast(lltype.Signed, self.itself)) + def SetParamEntityParsing(self, space, flag): + """SetParamEntityParsing(flag) -> success +Controls parsing of parameter entities (including the external DTD +subset). Possible flag values are XML_PARAM_ENTITY_PARSING_NEVER, +XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE and +XML_PARAM_ENTITY_PARSING_ALWAYS. Returns true if setting the flag +was successful.""" + XML_SetParamEntityParsing(self.itself, flag) + SetParamEntityParsing.unwrap_spec = ['self', ObjSpace, int] + def UseForeignDTD(self, space, w_flag=True): """UseForeignDTD([flag]) Allows the application to provide an artificial external subset if one is @@ -412,9 +445,41 @@ def ParseFile(self, space, w_file): """ParseFile(file) Parse XML data from file-like object.""" - return + # XXX not the more efficient method + w_data = space.call_method(w_file, 'read') + data = space.str_w(w_data) + return self.Parse(space, data, isfinal=True) ParseFile.unwrap_spec = ['self', ObjSpace, W_Root] + def SetBase(self, space, base): + XML_SetBase(self.itself, base) + SetBase.unwrap_spec = ['self', ObjSpace, str] + + def ExternalEntityParserCreate(self, space, context, w_encoding=None): + """ExternalEntityParserCreate(context[, encoding]) +Create a parser for parsing an external entity based on the +information passed to the ExternalEntityRefHandler.""" + if space.is_w(w_encoding, space.w_None): + encoding = None + else: + encoding = space.str_w(w_encoding) + + parser = W_XMLParserType(encoding, '\0', space.newdict(), + _from_external_entity=True) + parser.itself = XML_ExternalEntityParserCreate(self.itself, + context, encoding) + global_storage.get_nonmoving_id( + CallbackData(space, parser), + id=rffi.cast(lltype.Signed, parser.itself)) + XML_SetUserData(parser.itself, parser.itself) + + # copy handlers from self + for i in range(NB_HANDLERS): + parser.handlers[i] = self.handlers[i] + + return space.wrap(parser) + ExternalEntityParserCreate.unwrap_spec = ['self', ObjSpace, str, W_Root] + def flush_character_buffer(self, space): if not self.buffer_w: return @@ -476,7 +541,8 @@ setattr(obj, name, space.bool_w(value)) return GetSetProperty(fget, fset, cls=cls, doc=doc) -XMLParser_methods = ['Parse', 'ParseFile'] +XMLParser_methods = ['Parse', 'ParseFile', 'SetBase', 'SetParamEntityParsing', + 'ExternalEntityParserCreate'] if XML_COMBINED_VERSION >= 19505: XMLParser_methods.append('UseForeignDTD') @@ -515,13 +581,13 @@ encoding = space.str_w(w_encoding) if space.is_w(w_namespace_separator, space.w_None): - namespace_separator = '\0' + namespace_separator = 0 else: separator = space.str_w(w_namespace_separator) if len(separator) == 0: - namespace_separator = '\0' + namespace_separator = 0 elif len(separator) == 1: - namespace_separator = separator[0] + namespace_separator = ord(separator[0]) else: raise OperationError( space.w_ValueError, From arigo at codespeak.net Wed Mar 18 17:44:21 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 18 Mar 2009 17:44:21 +0100 (CET) Subject: [pypy-svn] r63047 - pypy/branch/pyjitpl5/pypy/doc/jit Message-ID: <20090318164421.A38CF168472@codespeak.net> Author: arigo Date: Wed Mar 18 17:44:19 2009 New Revision: 63047 Modified: pypy/branch/pyjitpl5/pypy/doc/jit/index.txt pypy/branch/pyjitpl5/pypy/doc/jit/overview.txt pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt Log: Update (a little bit) to docs about the JIT. Modified: pypy/branch/pyjitpl5/pypy/doc/jit/index.txt ============================================================================== --- pypy/branch/pyjitpl5/pypy/doc/jit/index.txt (original) +++ pypy/branch/pyjitpl5/pypy/doc/jit/index.txt Wed Mar 18 17:44:19 2009 @@ -19,6 +19,13 @@ - Overview_: motivating our approach +- `Draft notes`_ about the current work in PyPy (Feb 08). + +Older stuff +------------------------------------------------------------ + +*The following documentation is no longer up-to-date!* + - Status_: using a pypy-c with a JIT - `How-to`_: make your own JIT compilers, with examples for tiny languages @@ -29,14 +36,6 @@ - Machine code Backends_ -- Current work and prototype in Prolog (!): see `this blog post`__. - -- `Draft notes`_ about the current work in PyPy (Feb 08). - -*(work and documentation in progress!)* - -.. __: http://morepypy.blogspot.com/2008/06/hi-all-some-news-from-jit-front.html - ------------------------------------------------------------ .. _Overview: overview.html Modified: pypy/branch/pyjitpl5/pypy/doc/jit/overview.txt ============================================================================== --- pypy/branch/pyjitpl5/pypy/doc/jit/overview.txt (original) +++ pypy/branch/pyjitpl5/pypy/doc/jit/overview.txt Wed Mar 18 17:44:19 2009 @@ -23,9 +23,9 @@ But coding in a high-level language has other benefits beyond the obvious ones. Perhaps most importantly, it allows the language -interpreter to be analyzed and turned into a compiler. This is -precisely what our JIT compiler generator does. Based on partial -evaluation techniques, **it can turn the interpreter of an arbitrary +interpreter to be analyzed when turned into a compiler. This is +precisely what our JIT compiler generator does. Based on tracing +JIT techniques, **it can turn the interpreter of an arbitrary dynamic language into a just-in-time compiler for the same language.** It works mostly automatically and only needs guidance by the language implementor in the form of a small number of hints in the source code of @@ -34,10 +34,11 @@ machine code for the user program while aggressively optimizing it, leading to a big performance boost. -Partial evaluation vs. manually-written JIT compilers ------------------------------------------------------ +The path we followed +-------------------- -Partial evaluation is a well-known and much-researched topic, considered +Our previous incarnations of PyPy's JIT generator were based on partial +evaluation. This is a well-known and much-researched topic, considered to be very promising. There have been many attempts to use it to automatically transform an interpreter into a compiler. However, none of them have lead to substantial speedups for real-world languages. We @@ -46,16 +47,22 @@ compilers. If this turns out to be correct, the practical speed of dynamic languages could be vastly improved. -By comparison, getting a JIT compiler today involves either manually -writing one, which is a huge amount of effort, or reusing an existing -well-tuned JIT (like that of the JVM). However, the latter is hard -because of concept mismatches between the implementor's language and the -host VM language: the former needs to be compiled to the target -environment in such a way that the JIT is able to speed it up -significantly - an approach which essentially has failed in Python so -far: even though CPython is a simple interpreter, its Java and .NET -re-implementations are not faster (and cannot run all existing Python -applications). +Today (beginning 2009), our prototype is no longer using partial +evaluation -- at least not in a way that would convince paper reviewers. +It is instead based on the notion of *tracing JIT,* recently studied for +Java and JavaScript. When compared to all existing tracing JITs so far, +however, partial evaluation gives us some extra techniques that we +already had in our previous JIT generators, notably how to optimize +structures by removing allocations. + +The closest comparison to our current JIT is Tamarin's TraceMonkey. +However, this JIT compiler is written manually, which is quite some +effort. In PyPy, we write a JIT generator at the level of RPython, +which means that our final JIT does not have to -- indeed, cannot -- be +written to encode all the details of the full Python language. These +details are automatically supplied by the fact that we have an +interpreter for full Python. + Practical results ----------------- @@ -82,8 +89,10 @@ * Fast enough: we think that we can get some rather good performance out of the generated JIT compilers. That's the whole point, of course. - Previous experience shows that it should be possible (our generated - JIT compilers are similar to the hand-written Psyco). + Previous experience shows that it should be possible. Our previous + generated JIT compilers were similar to the hand-written Psyco; due + to limits in automating the way Psyco works, our current generated + JIT compilers are instead similar to tracing JITs like TraceMonkey. Alternative approaches to improve speed @@ -131,7 +140,7 @@ encoding of language semantics - knowledge about Python behavior needs to be encoded by hand and kept up-to-date. At least, Psyco works correctly even when encountering one of the numerous Python constructs it does not support, by -falling back to CPython. The PyPy JIT can be seen as a metaprogrammatic, +falling back to CPython. The PyPy JIT started out as a metaprogrammatic, non-language-specific equivalent of Psyco. A different kind of prior art are self-hosting JIT compilers such as Jikes. @@ -142,6 +151,14 @@ parts of the JIT compiler would need retargetting in order to run in a different environment than the intended low-level one. +Simply reusing an existing well-tuned JIT like that of the JVM does not +really work, because of concept mismatches between the implementor's +language and the host VM language: the former needs to be compiled to +the target environment in such a way that the JIT is able to speed it up +significantly - an approach which essentially has failed in Python so +far: even though CPython is a simple interpreter, its Java and .NET +re-implementations are not significantly faster. + More recently, several larger projects have started in the JIT area. For instance, Sun Microsystems is investing in JRuby, which aims to use the Java Hotspot JIT to improve the performance of Ruby. However, this requires a lot of @@ -158,16 +175,16 @@ is contributing insights from our JIT research, in ways that will also benefit PyPy. +Finally, tracing JITs are now emerging for dynamic languages like +JavaScript with TraceMonkey. The code generated by PyPy is very similar +(but not hand-written) to the concepts of tracing JITs. + Further reading ======================================================================== -The basic ideas have been shown to work in our prototype JIT-enabled -``pypy-c``, as described in Status_. Further technical documentation is -in progress; see the Index_ page. You can also read more about the -`Theory of partial evaluation`_. - -.. _Index: index.html -.. _Status: status.html -.. _`Theory of partial evaluation`: theory.html#terminology +The description of the current PyPy JIT generator is given in PyJitPl5_ +(draft). + .. _`JSR 292`: http://jcp.org/en/jsr/detail?id=292 +.. _PyJitPl5: pyjitpl5.html Modified: pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt ============================================================================== --- pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt (original) +++ pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt Wed Mar 18 17:44:19 2009 @@ -2,3 +2,10 @@ PyJitPl5 ======================================================================== +Current information is available on blog posts (oldest first): + +* http://morepypy.blogspot.com/2008/06/hi-all-some-news-from-jit-front.html +* http://morepypy.blogspot.com/2008/10/prolog-jit-masters-thesis-finished.html +* http://morepypy.blogspot.com/2009/03/applying-tracing-jit-to-interpreter.html +* http://morepypy.blogspot.com/2009/03/jit-bit-of-look-inside.html +* http://morepypy.blogspot.com/2009/03/good-news-everyone.html From afa at codespeak.net Wed Mar 18 18:45:32 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Mar 2009 18:45:32 +0100 (CET) Subject: [pypy-svn] r63049 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090318174532.8923E168442@codespeak.net> Author: afa Date: Wed Mar 18 18:45:29 2009 New Revision: 63049 Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: Translation fixes. Now pypy-c passes test_sax. Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Wed Mar 18 18:45:29 2009 @@ -282,9 +282,6 @@ rffi.cast(rffi.CHAR, namespace_separator)) else: self.itself = XML_ParserCreate(self.encoding) - if not self.itself: - raise OperationError(space.w_RuntimeError, - space.wrap('XML_ParserCreate failed')) self.handlers = [None] * NB_HANDLERS @@ -464,7 +461,7 @@ else: encoding = space.str_w(w_encoding) - parser = W_XMLParserType(encoding, '\0', space.newdict(), + parser = W_XMLParserType(encoding, 0, space.newdict(), _from_external_entity=True) parser.itself = XML_ExternalEntityParserCreate(self.itself, context, encoding) @@ -597,6 +594,10 @@ w_intern = space.newdict() parser = W_XMLParserType(encoding, namespace_separator, w_intern) + if not parser.itself: + raise OperationError(space.w_RuntimeError, + space.wrap('XML_ParserCreate failed')) + global_storage.get_nonmoving_id( CallbackData(space, parser), id=rffi.cast(lltype.Signed, parser.itself)) From arigo at codespeak.net Thu Mar 19 10:14:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 10:14:10 +0100 (CET) Subject: [pypy-svn] r63058 - pypy/trunk/pypy/rlib/test Message-ID: <20090319091410.DAC3F168442@codespeak.net> Author: arigo Date: Thu Mar 19 10:14:09 2009 New Revision: 63058 Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py Log: Fix test_rsocket to also pass on wyvern, where it seems that even though we send packets to 127.0.0.1 they go via the real network interface. Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rsocket.py (original) +++ pypy/trunk/pypy/rlib/test/test_rsocket.py Thu Mar 19 10:14:09 2009 @@ -179,9 +179,6 @@ s2.close() def test_simple_udp(): - if cpy_socket.gethostname() == 'wyvern': - py.test.skip("this is currently hanging on wyvern") - s1 = RSocket(AF_INET, SOCK_DGRAM) try_ports = [1023] + range(20000, 30000, 437) for port in try_ports: @@ -198,18 +195,19 @@ addr = INETAddress('127.0.0.1', port) assert addr.eq(s1.getsockname()) s2 = RSocket(AF_INET, SOCK_DGRAM) - s2.connect(addr) + s2.bind(INETAddress('127.0.0.1', INADDR_ANY)) addr2 = s2.getsockname() s1.sendto('?', 0, addr2) buf = s2.recv(100) assert buf == '?' + s2.connect(addr) count = s2.send('x'*99) assert 1 <= count <= 99 buf, addr3 = s1.recvfrom(100) assert buf == 'x'*count print addr2, addr3 - assert addr3.eq(addr2) + assert addr2.get_port() == addr3.get_port() s1.close() s2.close() @@ -244,7 +242,7 @@ s1, addr2 = sock.accept() s1.setblocking(False) assert addr.eq(s2.getpeername()) - assert addr2.eq(s2.getsockname()) + assert addr2.get_port() == s2.getsockname().get_port() assert addr2.eq(s1.getpeername()) err = s2.connect_ex(addr) # should now work From arigo at codespeak.net Thu Mar 19 10:22:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 10:22:09 +0100 (CET) Subject: [pypy-svn] r63059 - pypy/trunk/pypy/translator/sandbox/test Message-ID: <20090319092209.1F23C168437@codespeak.net> Author: arigo Date: Thu Mar 19 10:22:07 2009 New Revision: 63059 Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py Log: Test with codespeak.net instead of google.com (which returned a 302 at least once). Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py (original) +++ pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py Thu Mar 19 10:22:07 2009 @@ -103,7 +103,7 @@ pass def entry_point(argv): - fd = os.open("tcp://google.com:80", os.O_RDONLY, 0777) + fd = os.open("tcp://codespeak.net:80", os.O_RDONLY, 0777) os.write(fd, 'GET /\n') print os.read(fd, 30) return 0 @@ -111,7 +111,7 @@ proc = SocketProc([exe]) output, error = proc.communicate("") - assert output.startswith('') + assert output.startswith(' Author: fijal Date: Thu Mar 19 11:12:51 2009 New Revision: 63062 Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_tl.py Log: skip those tests as well (they work on branch) Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_tl.py ============================================================================== --- pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_tl.py (original) +++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_tl.py Thu Mar 19 11:12:51 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("Fixed on branch") from pypy.jit.metainterp.test.test_tl import ToyLanguageTests from pypy.jit.backend.x86.test.test_zrpy_slist import Jit386Mixin from pypy.jit.tl import tlc From pedronis at codespeak.net Thu Mar 19 11:30:34 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 11:30:34 +0100 (CET) Subject: [pypy-svn] r63063 - in pypy/trunk/pypy/translator: . test Message-ID: <20090319103034.7670B168437@codespeak.net> Author: pedronis Date: Thu Mar 19 11:30:32 2009 New Revision: 63063 Modified: pypy/trunk/pypy/translator/geninterplevel.py pypy/trunk/pypy/translator/test/snippet.py pypy/trunk/pypy/translator/test/test_geninterp.py Log: (iko, pedronis) hopefully fix translation on 2.4 Modified: pypy/trunk/pypy/translator/geninterplevel.py ============================================================================== --- pypy/trunk/pypy/translator/geninterplevel.py (original) +++ pypy/trunk/pypy/translator/geninterplevel.py Thu Mar 19 11:30:32 2009 @@ -632,9 +632,10 @@ self.initcode.append1('%s = space.wrap(%s)' % (name, functionname)) return name - def nameof_instancemethod(self, meth): - if meth.im_func.func_globals is None: - # built-in methods (bound or not) on top of PyPy + def nameof_instancemethod(self, meth): + if (not hasattr(meth.im_func, 'func_globals') or + meth.im_func.func_globals is None): + # built-in methods (bound or not) on top of PyPy or possibly 2.4 return self.nameof_builtin_method(meth) if meth.im_self is None: # no error checking here Modified: pypy/trunk/pypy/translator/test/snippet.py ============================================================================== --- pypy/trunk/pypy/translator/test/snippet.py (original) +++ pypy/trunk/pypy/translator/test/snippet.py Thu Mar 19 11:30:32 2009 @@ -666,6 +666,17 @@ return 567 +class Exc(Exception): + def __init__(self, v): + Exception.__init__(self, v) + +def exception_subclass_sanity(x): + try: + raise Exc(x) + except Exception, e: + return e.args[0] + + # --------------------(Currently) Non runnable Functions --------------------- def _somebug1(n=int): Modified: pypy/trunk/pypy/translator/test/test_geninterp.py ============================================================================== --- pypy/trunk/pypy/translator/test/test_geninterp.py (original) +++ pypy/trunk/pypy/translator/test/test_geninterp.py Thu Mar 19 11:30:32 2009 @@ -299,3 +299,8 @@ fn = self.build_interpfunc(snippet.t_attrerror) result = fn(42) assert result == 567 + + def test_Exception_subclass(self): + fn = self.build_interpfunc(snippet.exception_subclass_sanity) + result = fn(7) + assert result == 7 From arigo at codespeak.net Thu Mar 19 11:43:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 11:43:26 +0100 (CET) Subject: [pypy-svn] r63064 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090319104326.746F3168458@codespeak.net> Author: arigo Date: Thu Mar 19 11:43:24 2009 New Revision: 63064 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Add an XXX. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 11:43:24 2009 @@ -781,6 +781,8 @@ def cleanup_field_caches(self, newoperations): # we need to invalidate everything + # XXX looping over self.nodes on each side-effecting operation + # XXX costs too much (quadratic time) for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): # XXX move to InstanceNode eventually From pedronis at codespeak.net Thu Mar 19 12:29:03 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 12:29:03 +0100 (CET) Subject: [pypy-svn] r63065 - in pypy/trunk/pypy/objspace: . test Message-ID: <20090319112903.AFB1816847C@codespeak.net> Author: pedronis Date: Thu Mar 19 12:29:01 2009 New Revision: 63065 Modified: pypy/trunk/pypy/objspace/descroperation.py pypy/trunk/pypy/objspace/test/test_binop_overriding.py Log: issue412 testing checking in the fix and enabling some of the corresponding tests even in non -A runs Modified: pypy/trunk/pypy/objspace/descroperation.py ============================================================================== --- pypy/trunk/pypy/objspace/descroperation.py (original) +++ pypy/trunk/pypy/objspace/descroperation.py Thu Mar 19 12:29:01 2009 @@ -267,10 +267,14 @@ w_right_impl = None else: w_right_src, w_right_impl = space.lookup_in_type_where(w_typ2, '__rpow__') - if (w_left_src is not w_right_src # XXX see binop_impl + # sse binop_impl + if (w_left_src is not w_right_src and space.is_true(space.issubtype(w_typ2, w_typ1))): - w_obj1, w_obj2 = w_obj2, w_obj1 - w_left_impl, w_right_impl = w_right_impl, w_left_impl + if (w_left_src and w_right_src and + not space.abstract_issubclass_w(w_left_src, w_right_src) and + not space.abstract_issubclass_w(w_typ1, w_right_src)): + w_obj1, w_obj2 = w_obj2, w_obj1 + w_left_impl, w_right_impl = w_right_impl, w_left_impl if w_left_impl is not None: if space.is_w(w_obj3, space.w_None): w_res = space.get_and_call_function(w_left_impl, w_obj1, w_obj2) @@ -551,8 +555,11 @@ w_typ1 = space.w_basestring # -- end of bug compatibility if space.is_true(space.issubtype(w_typ2, w_typ1)): - w_obj1, w_obj2 = w_obj2, w_obj1 - w_left_impl, w_right_impl = w_right_impl, w_left_impl + if (w_left_src and w_right_src and + not space.abstract_issubclass_w(w_left_src, w_right_src) and + not space.abstract_issubclass_w(w_typ1, w_right_src)): + w_obj1, w_obj2 = w_obj2, w_obj1 + w_left_impl, w_right_impl = w_right_impl, w_left_impl w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) if w_res is not None: Modified: pypy/trunk/pypy/objspace/test/test_binop_overriding.py ============================================================================== --- pypy/trunk/pypy/objspace/test/test_binop_overriding.py (original) +++ pypy/trunk/pypy/objspace/test/test_binop_overriding.py Thu Mar 19 12:29:01 2009 @@ -86,8 +86,6 @@ cls.w_appdirect = cls.space.wrap(option.runappdirect) def test_overriding_base_binop_explict(self): - if not self.appdirect: - skip("fails, issue412") class MulBase(object): def __init__(self, value): self.value = value @@ -118,8 +116,6 @@ assert not fail def test_binop_combinations_sub(self): - if not self.appdirect: - skip("fails, issue412") Base, do_test = self.helpers class X(Base): pass From arigo at codespeak.net Thu Mar 19 13:06:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 13:06:14 +0100 (CET) Subject: [pypy-svn] r63066 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090319120614.A4425168473@codespeak.net> Author: arigo Date: Thu Mar 19 13:06:12 2009 New Revision: 63066 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: Get rid of these intermediate classes Load, Store, Perform, etc. It's easy enough that I wonder why they have been introduced in the first place. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 19 13:06:12 2009 @@ -9,8 +9,7 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, - arg_pos, lower_byte, stack_pos, Perform, - RETURN) + arg_pos, lower_byte, stack_pos, RETURN) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.support import gc_malloc_fnaddr @@ -43,7 +42,6 @@ class Assembler386(object): MC_SIZE = 1024*1024 # 1MB, but assumed infinite for now generic_return_addr = 0 - position = -1 log_fd = -1 def __init__(self, cpu, translate_support_code=False): @@ -149,10 +147,10 @@ op0 = operations[0] op0.position = self.mc.tell() self.eventually_log_operations(operations, guard_op) - regalloc = RegAlloc(operations, guard_op, self.cpu.translate_support_code) + regalloc = RegAlloc(self, operations, guard_op, + self.cpu.translate_support_code) if not we_are_translated(): self._regalloc = regalloc # for debugging - computed_ops = regalloc.computed_ops if guard_op is not None: new_rel_addr = self.mc.tell() - guard_op._jmp_from TP = rffi.CArrayPtr(lltype.Signed) @@ -164,29 +162,9 @@ print pprint.pprint(operations) print - pprint.pprint(computed_ops) - print - for i in range(len(computed_ops)): - op = computed_ops[i] - if not we_are_translated(): - self.dump_op(op) - self.position = i - # XXX eventually change to numbers or kill - # alltogether - if op.opname == 'load': - self.regalloc_load(op) - elif op.opname == 'store': - self.regalloc_store(op) - elif op.opname == 'perform_discard': - self.regalloc_perform_discard(op) - elif op.opname == 'perform': - self.regalloc_perform(op) - elif op.opname == 'perform_with_guard': - self.regalloc_perform_with_guard(op) - else: - raise NotImplementedError(op.opname) - if not we_are_translated(): - self.dump_op('') + #pprint.pprint(computed_ops) + #print + regalloc.walk_operations(operations) self.mc.done() self.mc2.done() @@ -208,13 +186,13 @@ self.mc.done() return addr - def dump_op(self, op): + def dump(self, text): if not self.verbose: return _prev = Box._extended_display try: Box._extended_display = False - print >> sys.stderr, ' 0x%x %s' % (fixid(self.mc.tell()), op) + print >> sys.stderr, ' 0x%x %s' % (fixid(self.mc.tell()), text) finally: Box._extended_display = _prev @@ -242,42 +220,19 @@ self.mc.done() return addr - def copy_var_if_used(self, v, to_v): - """ Gives new loc - """ - loc = self.loc(v) - if isinstance(loc, REG): - if self.regalloc.used(v) > self.regalloc.position: - newloc = self.regalloc.allocate_loc(v) - self.regalloc.move(loc, newloc) - self.regalloc.force_loc(to_v, loc) - else: - newloc = self.regalloc.allocate_loc(to_v, force_reg=True) - self.mc.MOV(newloc, loc) - loc = newloc - return loc - - def next_stack_position(self): - position = self.current_stack_depth - self.current_stack_depth += 1 - return position - - def regalloc_load(self, op): - self.mc.MOV(op.to_loc, op.from_loc) + def regalloc_load(self, from_loc, to_loc): + self.mc.MOV(to_loc, from_loc) regalloc_store = regalloc_load - def regalloc_perform(self, op): - assert isinstance(op, Perform) - resloc = op.result_loc - genop_list[op.op.opnum](self, op.op, op.arglocs, resloc) - - def regalloc_perform_discard(self, op): - genop_discard_list[op.op.opnum](self, op.op, op.arglocs) - - def regalloc_perform_with_guard(self, op): - genop_guard_list[op.op.opnum](self, op.op, op.guard_op, op.arglocs, - op.result_loc) + def regalloc_perform(self, op, arglocs, resloc): + genop_list[op.opnum](self, op, arglocs, resloc) + + def regalloc_perform_discard(self, op, arglocs): + genop_discard_list[op.opnum](self, op, arglocs) + + def regalloc_perform_with_guard(self, op, guard_op, arglocs, resloc): + genop_guard_list[op.opnum](self, op, guard_op, arglocs, resloc) def _unaryop(asmop): def genop_unary(self, op, arglocs, resloc): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 19 13:06:12 2009 @@ -1,5 +1,5 @@ -""" Register allocation scheme. The idea is as follows: +""" Register allocation scheme. """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, @@ -26,58 +26,6 @@ def __repr__(self): return "" % (id(self),) -class PseudoOperation(object): - def __init__(self, v, from_loc, to_loc): - self.from_loc = from_loc - self.to_loc = to_loc - self.v = v - -# pseudo operations for loading/saving reg/mem -class Load(PseudoOperation): - opname = 'load' - - def __repr__(self): - return '%s <- %s(%s)' % (self.to_loc, self.v, self.from_loc) - -class Store(PseudoOperation): - opname = 'store' - - def __repr__(self): - return '%s(%s) -> %s' % (self.v, self.from_loc, self.to_loc) - -class Perform(PseudoOperation): - opname = 'perform' - - def __init__(self, op, arglocs, result_loc): - self.op = op - self.result_loc = result_loc - self.arglocs = arglocs - - def __repr__(self): - return '%s <- %s(%s)' % (self.result_loc, self.op, self.arglocs) - -class PerformWithGuard(PseudoOperation): - opname = 'perform_with_guard' - - def __init__(self, op, guard_op, arglocs, result_loc): - self.op = op - self.guard_op = guard_op - self.result_loc = result_loc - self.arglocs = arglocs - - def __repr__(self): - return '%s <- %s(%s) [GUARDED]' % (self.result_loc, self.op, self.arglocs) - -class PerformDiscard(PseudoOperation): - opname = 'perform_discard' - - def __init__(self, op, arglocs): - self.op = op - self.arglocs = arglocs - - def __repr__(self): - return '%s(%s)' % (self.op, self.arglocs) - class checkdict(dict): def __setitem__(self, key, value): assert isinstance(key, Box) @@ -99,8 +47,10 @@ raise ValueError("convert_to_imm: got a %s" % c) class RegAlloc(object): - def __init__(self, operations, guard_op=None, translate_support_code=False): + def __init__(self, assembler, operations, guard_op=None, + translate_support_code=False): # variables that have place in register + self.assembler = assembler self.translate_support_code = translate_support_code self.reg_bindings = newcheckdict() self.stack_bindings = {} @@ -116,9 +66,8 @@ loop_consts, sd = self._start_from_guard_op(guard_op, mp, jump) else: loop_consts, sd = self._compute_loop_consts(mp, jump) + self.loop_consts = loop_consts self.current_stack_depth = sd - self.computed_ops = self.walk_operations(operations, loop_consts) - assert not self.reg_bindings def _start_from_guard_op(self, guard_op, mp, jump): rev_stack_binds = {} @@ -206,6 +155,33 @@ self.longevity[v][0] <= self.position): assert not v in self.dirty_stack + def Load(self, v, from_loc, to_loc): + if not we_are_translated(): + self.assembler.dump('%s <- %s(%s)' % (to_loc, v, from_loc)) + self.assembler.regalloc_load(from_loc, to_loc) + + def Store(self, v, from_loc, to_loc): + if not we_are_translated(): + self.assembler.dump('%s(%s) -> %s' % (v, from_loc, to_loc)) + self.assembler.regalloc_store(from_loc, to_loc) + + def Perform(self, op, arglocs, result_loc): + if not we_are_translated(): + self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs)) + self.assembler.regalloc_perform(op, arglocs, result_loc) + + def PerformWithGuard(self, op, guard_op, arglocs, result_loc): + if not we_are_translated(): + self.assembler.dump('%s <- %s(%s) [GUARDED]' % (result_loc, op, + arglocs)) + self.assembler.regalloc_perform_with_guard(op, guard_op, arglocs, + result_loc) + + def PerformDiscard(self, op, arglocs): + if not we_are_translated(): + self.assembler.dump('%s(%s)' % (op, arglocs)) + self.assembler.regalloc_perform_discard(op, arglocs) + def can_optimize_cmp_op(self, op, i, operations): if not op.is_comparison(): return False @@ -218,11 +194,9 @@ return False return True - def walk_operations(self, operations, loop_consts): + def walk_operations(self, operations): # first pass - walk along the operations in order to find # load/store places - new_ops = [] - self.loop_consts = loop_consts i = 0 while i < len(operations): op = operations[i] @@ -235,19 +209,20 @@ # detect overflow ops if op.is_ovf(): assert operations[i + 1].opnum == rop.GUARD_NO_EXCEPTION - new_ops += oplist[op.opnum](self, op, operations[i + 1]) + nothing = oplist[op.opnum](self, op, operations[i + 1]) i += 1 elif self.can_optimize_cmp_op(op, i, operations): - new_ops += oplist[op.opnum](self, op, operations[i + 1]) + nothing = oplist[op.opnum](self, op, operations[i + 1]) i += 1 else: - new_ops += oplist[op.opnum](self, op, None) + nothing = oplist[op.opnum](self, op, None) + assert nothing is None # temporary, remove me self.eventually_free_var(op.result) self._check_invariants() else: self.eventually_free_vars(op.args) i += 1 - return new_ops + assert not self.reg_bindings def _compute_vars_longevity(self, operations): # compute a dictionary that maps variables to index in @@ -314,10 +289,12 @@ if selected_reg or not imm_fine: # this means we cannot have it in IMM, eh if selected_reg in self.free_regs: - return selected_reg, [Load(v, convert_to_imm(v), selected_reg)] + self.Load(v, convert_to_imm(v), selected_reg) + return selected_reg if selected_reg is None and self.free_regs: loc = self.free_regs.pop() - return loc, [Load(v, convert_to_imm(v), loc)] + self.Load(v, convert_to_imm(v), loc) + return loc v_to_spill = self.pick_variable_to_spill(v, forbidden_vars, selected_reg) loc = self.loc(v_to_spill) if v_to_spill not in self.stack_bindings or v_to_spill in self.dirty_stack: @@ -326,13 +303,12 @@ del self.dirty_stack[v_to_spill] except KeyError: pass - ops = [Store(v_to_spill, loc, newloc)] - else: - ops = [] + self.Store(v_to_spill, loc, newloc) del self.reg_bindings[v_to_spill] self.free_regs.append(loc) - return loc, ops+[Load(v, convert_to_imm(v), loc)] - return convert_to_imm(v), [] + self.Load(v, convert_to_imm(v), loc) + return loc + return convert_to_imm(v) def force_allocate_reg(self, v, forbidden_vars, selected_reg=None): if isinstance(v, Const): @@ -341,7 +317,7 @@ self.longevity[v] = (self.position, self.position) loc = self.try_allocate_reg(v, selected_reg) if loc: - return loc, [] + return loc return self._spill_var(v, forbidden_vars, selected_reg) def _spill_var(self, v, forbidden_vars, selected_reg): @@ -355,8 +331,8 @@ del self.dirty_stack[v_to_spill] except KeyError: pass - return loc, [Store(v_to_spill, loc, newloc)] - return loc, [] + self.Store(v_to_spill, loc, newloc) + return loc def _locs_from_liveboxes(self, guard_op): stacklocs = [] @@ -391,10 +367,10 @@ return self.return_constant(v, forbidden_vars, selected_reg, imm_fine) prev_loc = self.loc(v) - loc, ops = self.force_allocate_reg(v, forbidden_vars, selected_reg) - if prev_loc is loc: - return loc, ops - return loc, ops + [Load(v, prev_loc, loc)] + loc = self.force_allocate_reg(v, forbidden_vars, selected_reg) + if prev_loc is not loc: + self.Load(v, prev_loc, loc) + return loc def reallocate_from_to(self, from_v, to_v): reg = self.reg_bindings[from_v] @@ -441,7 +417,7 @@ del self.dirty_stack[v] except KeyError: pass - return Store(v, prev_loc, loc) + self.Store(v, prev_loc, loc) def force_result_in_reg(self, result_v, v, forbidden_vars, selected_reg=None): @@ -449,22 +425,20 @@ and v is copied away if it's further used """ if isinstance(v, Const): - loc, ops = self.make_sure_var_in_reg(v, forbidden_vars, - selected_reg, - imm_fine=False) + loc = self.make_sure_var_in_reg(v, forbidden_vars, + selected_reg, + imm_fine=False) assert not isinstance(loc, IMM8) self.reg_bindings[result_v] = loc self.free_regs = [reg for reg in self.free_regs if reg is not loc] - return loc, ops - ops = [] + return loc if v in self.reg_bindings and selected_reg: - _, ops = self.make_sure_var_in_reg(v, forbidden_vars, selected_reg) + self.make_sure_var_in_reg(v, forbidden_vars, selected_reg) elif v not in self.reg_bindings: assert v not in self.dirty_stack prev_loc = self.stack_bindings[v] - loc, o = self.force_allocate_reg(v, forbidden_vars, selected_reg) - ops += o - ops.append(Load(v, prev_loc, loc)) + loc = self.force_allocate_reg(v, forbidden_vars, selected_reg) + self.Load(v, prev_loc, loc) assert v in self.reg_bindings if self.longevity[v][1] > self.position: # we need to find a new place for variable x and @@ -472,18 +446,17 @@ loc = self.reg_bindings[v] del self.reg_bindings[v] if v not in self.stack_bindings or v in self.dirty_stack: - ops.append(self.move_variable_away(v, loc)) + self.move_variable_away(v, loc) self.reg_bindings[result_v] = loc else: self.reallocate_from_to(v, result_v) loc = self.reg_bindings[result_v] - return loc, ops + return loc def consider_merge_point(self, op, ignored): # XXX we can sort out here by longevity if we need something # more optimal - ops = [PerformDiscard(op, [])] locs = [None] * len(op.args) for i in range(len(op.args)): arg = op.args[i] @@ -502,11 +475,10 @@ locs[i] = loc # otherwise we have it saved on stack, so no worry op.arglocs = locs - ops[-1].arglocs = op.arglocs - op.stacklocs = [i for i in range(len(op.args))] + op.stacklocs = range(len(op.args)) + self.PerformDiscard(op, locs) # XXX be a bit smarter and completely ignore such vars self.eventually_free_vars(op.args) - return ops def consider_catch(self, op, ignored): locs = [] @@ -519,14 +491,14 @@ op.arglocs = locs op.stacklocs = [self.stack_loc(arg).position for arg in op.args] self.eventually_free_vars(op.args) - return [PerformDiscard(op, [])] + self.PerformDiscard(op, []) def _consider_guard(self, op, ignored): - loc, ops = self.make_sure_var_in_reg(op.args[0], []) + loc = self.make_sure_var_in_reg(op.args[0], []) locs = self._locs_from_liveboxes(op) self.eventually_free_var(op.args[0]) self.eventually_free_vars(op.liveboxes) - return ops + [PerformDiscard(op, [loc] + locs)] + self.PerformDiscard(op, [loc] + locs) consider_guard_true = _consider_guard consider_guard_false = _consider_guard @@ -536,31 +508,30 @@ locs = self._locs_from_liveboxes(op) self.eventually_free_var(op.args[0]) self.eventually_free_vars(op.liveboxes) - return [] def consider_guard_no_exception(self, op, ignored): box = TempBox() - loc, ops = self.force_allocate_reg(box, []) + loc = self.force_allocate_reg(box, []) locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes) self.eventually_free_var(box) - return ops + [PerformDiscard(op, [loc] + locs)] + self.PerformDiscard(op, [loc] + locs) def consider_guard_exception(self, op, ignored): - loc, ops = self.make_sure_var_in_reg(op.args[0], []) + loc = self.make_sure_var_in_reg(op.args[0], []) box = TempBox() - loc1, ops1 = self.force_allocate_reg(box, op.args) + loc1 = self.force_allocate_reg(box, op.args) if op.result in self.longevity: # this means, is it ever used - resloc, ops2 = self.force_allocate_reg(op.result, + resloc = self.force_allocate_reg(op.result, op.args + [box]) else: - resloc, ops2 = None, [] + resloc = None locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes) self.eventually_free_vars(op.args) self.eventually_free_var(box) - return ops + ops1 + ops2 + [Perform(op, [loc, loc1] + locs, resloc)] + self.Perform(op, [loc, loc1] + locs, resloc) #def consider_guard2(self, op, ignored): # loc1, ops1 = self.make_sure_var_in_reg(op.args[0], []) @@ -581,20 +552,18 @@ def consider_guard_value(self, op, ignored): x = self.loc(op.args[0]) if not (isinstance(x, REG) or isinstance(op.args[1], Const)): - x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) - else: - ops = [] + x = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) y = self.loc(op.args[1]) locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes + op.args) - return ops + [PerformDiscard(op, [x, y] + locs)] + self.PerformDiscard(op, [x, y] + locs) def consider_guard_class(self, op, ignored): - x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) + x = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) y = self.loc(op.args[1]) locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes + op.args) - return ops + [PerformDiscard(op, [x, y] + locs)] + self.PerformDiscard(op, [x, y] + locs) def consider_return(self, op, ignored): if op.args: @@ -602,25 +571,24 @@ self.eventually_free_var(op.args[0]) else: arglocs = [] - return [PerformDiscard(op, arglocs)] + self.PerformDiscard(op, arglocs) def _consider_binop_part(self, op, ignored): x = op.args[0] - ops = [] if isinstance(x, Const): - res, ops = self.force_allocate_reg(op.result, []) + res = self.force_allocate_reg(op.result, []) argloc = self.loc(op.args[1]) self.eventually_free_var(op.args[1]) - load_op = Load(x, self.loc(x), res) - return res, argloc, ops + [load_op] - loc, ops = self.force_result_in_reg(op.result, x, op.args) + self.Load(x, self.loc(x), res) + return res, argloc + loc = self.force_result_in_reg(op.result, x, op.args) argloc = self.loc(op.args[1]) self.eventually_free_var(op.args[1]) - return loc, argloc, ops + return loc, argloc def _consider_binop(self, op, ignored): - loc, argloc, ops = self._consider_binop_part(op, ignored) - return ops + [Perform(op, [loc, argloc], loc)] + loc, argloc = self._consider_binop_part(op, ignored) + self.Perform(op, [loc, argloc], loc) consider_int_add = _consider_binop consider_int_mul = _consider_binop @@ -634,12 +602,12 @@ #consider_uint_and = _consider_binop def _consider_binop_ovf(self, op, guard_op): - loc, argloc, ops = self._consider_binop_part(op, None) + loc, argloc = self._consider_binop_part(op, None) locs = self._locs_from_liveboxes(guard_op) self.position += 1 self.eventually_free_vars(guard_op.liveboxes) self.eventually_free_var(guard_op.result) - return ops + [PerformWithGuard(op, guard_op, [loc, argloc] + locs, loc)] + self.PerformWithGuard(op, guard_op, [loc, argloc] + locs, loc) consider_int_mul_ovf = _consider_binop_ovf consider_int_sub_ovf = _consider_binop_ovf @@ -647,54 +615,53 @@ # XXX ovf_neg op def consider_int_neg(self, op, ignored): - res, ops = self.force_result_in_reg(op.result, op.args[0], []) - return ops + [Perform(op, [res], res)] + res = self.force_result_in_reg(op.result, op.args[0], []) + self.Perform(op, [res], res) consider_bool_not = consider_int_neg def consider_int_rshift(self, op, ignored): tmpvar = TempBox() - reg, ops = self.force_allocate_reg(tmpvar, [], ecx) + reg = self.force_allocate_reg(tmpvar, [], ecx) y = self.loc(op.args[1]) - x, more_ops = self.force_result_in_reg(op.result, op.args[0], - op.args + [tmpvar]) + x = self.force_result_in_reg(op.result, op.args[0], + op.args + [tmpvar]) self.eventually_free_vars(op.args + [tmpvar]) - return ops + more_ops + [Perform(op, [x, y, reg], x)] + self.Perform(op, [x, y, reg], x) def consider_int_mod(self, op, ignored): - l0, ops0 = self.make_sure_var_in_reg(op.args[0], [], eax) - l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) - l2, ops2 = self.force_allocate_reg(op.result, [], edx) + l0 = self.make_sure_var_in_reg(op.args[0], [], eax) + l1 = self.make_sure_var_in_reg(op.args[1], [], ecx) + l2 = self.force_allocate_reg(op.result, [], edx) # eax is trashed after that operation tmpvar = TempBox() - _, ops3 = self.force_allocate_reg(tmpvar, [], eax) + self.force_allocate_reg(tmpvar, [], eax) assert (l0, l1, l2) == (eax, ecx, edx) self.eventually_free_vars(op.args + [tmpvar]) - return ops0 + ops1 + ops2 + ops3 + [Perform(op, [eax, ecx], edx)] + self.Perform(op, [eax, ecx], edx) def consider_int_mod_ovf(self, op, guard_op): - l0, ops0 = self.make_sure_var_in_reg(op.args[0], [], eax) - l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) - l2, ops2 = self.force_allocate_reg(op.result, [], edx) + l0 = self.make_sure_var_in_reg(op.args[0], [], eax) + l1 = self.make_sure_var_in_reg(op.args[1], [], ecx) + l2 = self.force_allocate_reg(op.result, [], edx) tmpvar = TempBox() - _, ops3 = self.force_allocate_reg(tmpvar, [], eax) + self.force_allocate_reg(tmpvar, [], eax) assert (l0, l1, l2) == (eax, ecx, edx) locs = self._locs_from_liveboxes(guard_op) self.eventually_free_vars(op.args + [tmpvar]) self.position += 1 self.eventually_free_vars(guard_op.liveboxes) - return (ops0 + ops1 + ops2 + ops3 + - [PerformWithGuard(op, guard_op, [eax, ecx] + locs, edx)]) + self.PerformWithGuard(op, guard_op, [eax, ecx] + locs, edx) def consider_int_floordiv(self, op, ignored): tmpvar = TempBox() - l0, ops0 = self.force_result_in_reg(op.result, op.args[0], [], eax) - l1, ops1 = self.make_sure_var_in_reg(op.args[1], [], ecx) + l0 = self.force_result_in_reg(op.result, op.args[0], [], eax) + l1 = self.make_sure_var_in_reg(op.args[1], [], ecx) # we need to make sure edx is empty, since we're going to use it - l2, ops2 = self.force_allocate_reg(tmpvar, [], edx) + l2 = self.force_allocate_reg(tmpvar, [], edx) assert (l0, l1, l2) == (eax, ecx, edx) self.eventually_free_vars(op.args + [tmpvar]) - return ops0 + ops1 + ops2 + [Perform(op, [eax, ecx], eax)] + self.Perform(op, [eax, ecx], eax) def _consider_compop(self, op, guard_op): vx = op.args[0] @@ -702,20 +669,20 @@ arglocs = [self.loc(vx), self.loc(vy)] if (vx in self.reg_bindings or vy in self.reg_bindings or isinstance(vx, Const) or isinstance(vy, Const)): - ops0 = [] + pass else: - arglocs[0], ops0 = self.make_sure_var_in_reg(vx, []) + arglocs[0] = self.make_sure_var_in_reg(vx, []) self.eventually_free_var(vx) self.eventually_free_var(vy) if guard_op is None: - loc, ops = self.force_allocate_reg(op.result, op.args) - return ops0 + ops + [Perform(op, arglocs, loc)] + loc = self.force_allocate_reg(op.result, op.args) + self.Perform(op, arglocs, loc) else: locs = self._locs_from_liveboxes(guard_op) self.position += 1 self.eventually_free_var(op.result) self.eventually_free_vars(guard_op.liveboxes) - return ops0 + [PerformWithGuard(op, guard_op, arglocs + locs, None)] + self.PerformWithGuard(op, guard_op, arglocs + locs, None) consider_int_lt = _consider_compop consider_int_gt = _consider_compop @@ -730,36 +697,31 @@ consider_uint_ge = _consider_compop def sync_var(self, v): - ops = [] if v in self.dirty_stack or v not in self.stack_bindings: reg = self.reg_bindings[v] - ops.append(Store(v, reg, self.stack_loc(v))) + self.Store(v, reg, self.stack_loc(v)) try: del self.dirty_stack[v] except KeyError: pass # otherwise it's clean - return ops def sync_var_if_survives(self, v): if self.longevity[v][1] > self.position: - return self.sync_var(v) - return [] + self.sync_var(v) def _call(self, op, arglocs, force_store=[]): - ops = [] # we need to store all variables which are now in registers for v, reg in self.reg_bindings.items(): if self.longevity[v][1] > self.position or v in force_store: - ops += self.sync_var(v) + self.sync_var(v) self.reg_bindings = newcheckdict() if op.result is not None: self.reg_bindings[op.result] = eax self.free_regs = [reg for reg in REGS if reg is not eax] - return ops + [Perform(op, arglocs, eax)] else: self.free_regs = REGS[:] - return ops + [Perform(op, arglocs, eax)] + self.Perform(op, arglocs, eax) def consider_call(self, op, ignored): from pypy.jit.backend.x86.runner import CPU386 @@ -784,41 +746,30 @@ def _malloc_varsize(self, ofs, ofs_items, ofs_length, size, v, res_v): if isinstance(v, Box): - loc, ops0 = self.make_sure_var_in_reg(v, [v]) - ops0 += self.sync_var(v) + loc = self.make_sure_var_in_reg(v, [v]) + self.sync_var(v) if size != 0: # XXX lshift? - ops0.append(Perform(ResOperation(rop.INT_MUL, [], None), - [loc, imm(1 << size)], loc)) - ops0.append(Perform(ResOperation(rop.INT_ADD, [], None), - [loc, imm(ofs + ofs_items)], loc)) + self.Perform(ResOperation(rop.INT_MUL, [], None), + [loc, imm(1 << size)], loc) + self.Perform(ResOperation(rop.INT_ADD, [], None), + [loc, imm(ofs + ofs_items)], loc) else: - ops0 = [] loc = imm(ofs + ofs_items + (v.getint() << size)) - ops = self._call(ResOperation(rop.NEW, [v], res_v) - , [loc], [v]) - loc, ops1 = self.make_sure_var_in_reg(v, [res_v]) + self._call(ResOperation(rop.NEW, [v], res_v), + [loc], [v]) + loc = self.make_sure_var_in_reg(v, [res_v]) assert self.loc(res_v) == eax # now we have to reload length to some reasonable place self.eventually_free_var(v) - res = (ops0 + ops + ops1 + - [PerformDiscard(ResOperation(rop.SETFIELD_GC, [], None), - [eax, imm(ofs + ofs_length), imm(WORD), loc])]) - return res + self.PerformDiscard(ResOperation(rop.SETFIELD_GC, [], None), + [eax, imm(ofs + ofs_length), imm(WORD), loc]) def consider_new_array(self, op, ignored): size_of_field, basesize, _ = self._unpack_arraydescr(op.descr) return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[0], op.result) - def consider_oononnull(self, op, ignored): - XXX # "consider_oononnull = _consider_nullity" below - argloc = self.loc(op.args[0]) - self.eventually_free_var(op.args[0]) - reg = self.try_allocate_reg(op.result) - assert reg - return [Perform(op, [argloc], reg)] - def _unpack_arraydescr(self, arraydescr): from pypy.jit.backend.x86.runner import CPU386 return CPU386.unpack_arraydescr(arraydescr) @@ -829,50 +780,44 @@ return imm(ofs), imm(size) def consider_setfield_gc(self, op, ignored): - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, size_loc = self._unpack_fielddescr(op.descr) - value_loc, ops2 = self.make_sure_var_in_reg(op.args[1], op.args) + value_loc = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars(op.args) - return (ops0 + ops2 + - [PerformDiscard(op, [base_loc, ofs_loc, size_loc, value_loc])]) + self.PerformDiscard(op, [base_loc, ofs_loc, size_loc, value_loc]) def consider_strsetitem(self, op, ignored): - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) - value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) + ofs_loc = self.make_sure_var_in_reg(op.args[1], op.args) + value_loc = self.make_sure_var_in_reg(op.args[2], op.args) self.eventually_free_vars([op.args[0], op.args[1], op.args[2]]) - return (ops0 + ops1 + ops2 + - [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) + self.PerformDiscard(op, [base_loc, ofs_loc, value_loc]) def consider_setarrayitem_gc(self, op, ignored): scale, ofs, _ = self._unpack_arraydescr(op.descr) - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) - value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) + value_loc = self.make_sure_var_in_reg(op.args[2], op.args) + ofs_loc = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars(op.args) - return (ops0 + ops2 + ops1 + - [PerformDiscard(op, [base_loc, ofs_loc, value_loc, - imm(scale), imm(ofs)])]) + self.PerformDiscard(op, [base_loc, ofs_loc, value_loc, + imm(scale), imm(ofs)]) def consider_getfield_gc(self, op, ignored): ofs_loc, size_loc = self._unpack_fielddescr(op.descr) - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) - result_loc, more_ops = self.force_allocate_reg(op.result, []) - return (ops0 + more_ops + - [Perform(op, [base_loc, ofs_loc, size_loc], result_loc)]) + result_loc = self.force_allocate_reg(op.result, []) + self.Perform(op, [base_loc, ofs_loc, size_loc], result_loc) consider_getfield_gc_pure = consider_getfield_gc def consider_getarrayitem_gc(self, op, ignored): scale, ofs, _ = self._unpack_arraydescr(op.descr) - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) + ofs_loc = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars(op.args) - result_loc, more_ops = self.force_allocate_reg(op.result, []) - return (ops0 + ops1 + more_ops + - [Perform(op, [base_loc, ofs_loc, imm(scale), imm(ofs)], - result_loc)]) + result_loc = self.force_allocate_reg(op.result, []) + self.Perform(op, [base_loc, ofs_loc, imm(scale), imm(ofs)], result_loc) consider_getfield_raw = consider_getfield_gc consider_getarrayitem_gc_pure = consider_getarrayitem_gc @@ -909,47 +854,43 @@ # xxx_consider_cast_int_to_ptr = consider_same_as def consider_int_is_true(self, op, ignored): - argloc, ops = self.force_allocate_reg(op.args[0], []) + argloc = self.force_allocate_reg(op.args[0], []) self.eventually_free_var(op.args[0]) - resloc, more_ops = self.force_allocate_reg(op.result, []) - return ops + more_ops + [Perform(op, [argloc], resloc)] + resloc = self.force_allocate_reg(op.result, []) + self.Perform(op, [argloc], resloc) def _consider_nullity(self, op, ignored): # doesn't need a register in arg argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) - resloc, ops = self.force_allocate_reg(op.result, []) - return ops + [Perform(op, [argloc], resloc)] + resloc = self.force_allocate_reg(op.result, []) + self.Perform(op, [argloc], resloc) consider_ooisnull = _consider_nullity consider_oononnull = _consider_nullity def consider_strlen(self, op, ignored): - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) - result_loc, more_ops = self.force_allocate_reg(op.result, []) - return ops0 + more_ops + [Perform(op, [base_loc], result_loc)] + result_loc = self.force_allocate_reg(op.result, []) + self.Perform(op, [base_loc], result_loc) def consider_arraylen_gc(self, op, ignored): _, ofs, _ = self._unpack_arraydescr(op.descr) - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) self.eventually_free_vars(op.args) - result_loc, more_ops = self.force_allocate_reg(op.result, []) - return ops0 + more_ops + [Perform(op, [base_loc, imm(ofs)], - result_loc)] + result_loc = self.force_allocate_reg(op.result, []) + self.Perform(op, [base_loc, imm(ofs)], result_loc) def consider_strgetitem(self, op, ignored): - base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) - ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) + base_loc = self.make_sure_var_in_reg(op.args[0], op.args) + ofs_loc = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) - result_loc, more_ops = self.force_allocate_reg(op.result, []) - return (ops0 + ops1 + more_ops + - [Perform(op, [base_loc, ofs_loc], result_loc)]) + result_loc = self.force_allocate_reg(op.result, []) + self.Perform(op, [base_loc, ofs_loc], result_loc) def consider_jump(self, op, ignored): - ops = [] - laterops = [] - middle_ops = [] + later_loads = [] reloaded = [] middle_busy_regs = [] for i in range(len(op.args)): @@ -961,7 +902,8 @@ assert mp.opnum == rop.MERGE_POINT if arg in self.reg_bindings: if not isinstance(res, REG): - ops.append(Store(arg, self.loc(arg), self.stack_bindings[arg])) + self.Store(arg, self.loc(arg), + self.stack_bindings[arg]) elif res is self.reg_bindings[arg]: middle_busy_regs.append(res) else: @@ -971,21 +913,23 @@ # if our register is free, easy for v, reg in self.reg_bindings.items(): if reg is res: - ops.append(Store(arg, self.loc(arg), self.stack_loc(arg))) - laterops.append(Load(arg, self.stack_loc(arg), res)) + self.Store(arg, self.loc(arg), + self.stack_loc(arg)) + later_loads.append((arg, self.stack_loc(arg), + res)) break else: - ops.append(Load(arg, self.loc(arg), res)) + self.Load(arg, self.loc(arg), res) else: if arg not in self.stack_bindings: # we can load it correctly, because we don't care # any more about the previous var staying there assert not isinstance(res, REG) - ops.append(Store(arg, self.loc(arg), res)) + self.Store(arg, self.loc(arg), res) else: assert arg not in self.dirty_stack if isinstance(res, REG): - laterops.append(Load(arg, self.loc(arg), res)) + later_loads.append((arg, self.loc(arg), res)) else: arg0 = self.loc(arg) assert isinstance(arg0, MODRM) @@ -993,13 +937,11 @@ if arg0.position != res.position: reloaded.append((arg, self.loc(arg), res)) elif isinstance(arg, Const): - laterops.append(Load(arg, self.loc(arg), res)) + later_loads.append((arg, self.loc(arg), res)) + self.eventually_free_vars(op.args) if reloaded: - self.eventually_free_vars(op.args) - middleops = [] # XXX performance free_reg = None - last_middle_op = None for reg in REGS: if reg not in middle_busy_regs: free_reg = reg @@ -1008,16 +950,14 @@ # a very rare case v = self.reg_bindings.keys()[0] free_reg = self.reg_bindings[v] - ops.append(Store(v, self.loc(v), self.stack_loc(v))) - last_middle_op = Load(v, self.stack_loc(v), self.loc(v)) + self.Store(v, self.loc(v), self.stack_loc(v)) + later_loads.insert(0, (v, self.stack_loc(v), self.loc(v))) for v, from_l, to_l in reloaded: - middleops.append(Load(v, from_l, free_reg)) - middleops.append(Store(v, free_reg, to_l)) - if last_middle_op is not None: - middleops.append(last_middle_op) - return ops + middleops + laterops + [PerformDiscard(op, [])] - self.eventually_free_vars(op.args) - return ops + laterops + [PerformDiscard(op, [])] + self.Load(v, from_l, free_reg) + self.Store(v, free_reg, to_l) + for v, from_l, to_l in later_loads: + self.Load(v, from_l, to_l) + self.PerformDiscard(op, []) def not_implemented_op(self, op, ignored): print "[regalloc] Not implemented operation: %s" % op.getopname() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 19 13:06:12 2009 @@ -148,7 +148,7 @@ res = cpu.execute_operations_in_new_frame('foo', ops, [arg0, arg1]) - assert len(cpu.assembler._regalloc.computed_ops) == 2 + #assert len(cpu.assembler._regalloc.computed_ops) == 2 assert meta_interp.gf # er, what to check here, assembler??? @@ -174,7 +174,7 @@ res = cpu.execute_operations_in_new_frame('foo', ops, [arg0, arg1]) - assert len(cpu.assembler._regalloc.computed_ops) == 5 + #assert len(cpu.assembler._regalloc.computed_ops) == 5 assert meta_interp.gf # er, what to check here, assembler??? From hpk at codespeak.net Thu Mar 19 13:32:50 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 19 Mar 2009 13:32:50 +0100 (CET) Subject: [pypy-svn] r63067 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090319123250.356D216847E@codespeak.net> Author: hpk Date: Thu Mar 19 13:32:48 2009 New Revision: 63067 Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox1.graffle (contents, props changed) pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox1.png (contents, props changed) Log: adding a dir and a picture that i used in a different talk Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox1.graffle ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox1.png ============================================================================== Binary file. No diff available. From antocuni at codespeak.net Thu Mar 19 13:57:31 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 19 Mar 2009 13:57:31 +0100 (CET) Subject: [pypy-svn] r63069 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090319125731.49118168483@codespeak.net> Author: antocuni Date: Thu Mar 19 13:57:29 2009 New Revision: 63069 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: add myself Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Thu Mar 19 13:57:29 2009 @@ -12,6 +12,7 @@ ==================== ============== ======================= Armin Rigo -- private Carl Friedrich Bolz 14th-21st Ermina +Antonio Cuni 14th-21st Ermina ==================== ============== ======================= People on the following list were present at previous sprints: @@ -19,7 +20,6 @@ ==================== ============== ===================== Name Arrive/Depart Accomodation ==================== ============== ===================== -Antonio Cuni ? ? Maciej Fijalkowski ? ? Toby Watson ? ? Paul deGrandis ? ? From pedronis at codespeak.net Thu Mar 19 15:17:27 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 15:17:27 +0100 (CET) Subject: [pypy-svn] r63070 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090319141727.8A69916801E@codespeak.net> Author: pedronis Date: Thu Mar 19 15:17:24 2009 New Revision: 63070 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: our names and dates Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Thu Mar 19 15:17:24 2009 @@ -13,6 +13,8 @@ Armin Rigo -- private Carl Friedrich Bolz 14th-21st Ermina Antonio Cuni 14th-21st Ermina +Samuele Pedroni 14th-22nd Ermina +Anders Hammarquist 14th-22nd Ermina ==================== ============== ======================= People on the following list were present at previous sprints: From pedronis at codespeak.net Thu Mar 19 15:28:11 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 15:28:11 +0100 (CET) Subject: [pypy-svn] r63071 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090319142811.F0D1A16849A@codespeak.net> Author: pedronis Date: Thu Mar 19 15:28:09 2009 New Revision: 63071 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: sharing info Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Thu Mar 19 15:28:09 2009 @@ -17,6 +17,8 @@ Anders Hammarquist 14th-22nd Ermina ==================== ============== ======================= +Samuele and Anders Hammarquist would like to share a two persons room. + People on the following list were present at previous sprints: ==================== ============== ===================== From cfbolz at codespeak.net Thu Mar 19 15:33:14 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 19 Mar 2009 15:33:14 +0100 (CET) Subject: [pypy-svn] r63072 - pypy/trunk/pypy/interpreter Message-ID: <20090319143314.942491684A4@codespeak.net> Author: cfbolz Date: Thu Mar 19 15:33:14 2009 New Revision: 63072 Modified: pypy/trunk/pypy/interpreter/baseobjspace.py pypy/trunk/pypy/interpreter/pyopcode.py Log: when bytecode logging is enabled, collect some more information Modified: pypy/trunk/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/trunk/pypy/interpreter/baseobjspace.py (original) +++ pypy/trunk/pypy/interpreter/baseobjspace.py Thu Mar 19 15:33:14 2009 @@ -249,8 +249,9 @@ from pypy.interpreter.pyframe import PyFrame self.FrameClass = PyFrame # can be overridden to a subclass -# if self.config.objspace.logbytecodes: -# self.bytecodecounts = {} + if self.config.objspace.logbytecodes: + self.bytecodecounts = [0] * 256 + self.bytecodetransitioncount = {} if self.config.objspace.timing: self.timer = Timer() @@ -297,8 +298,20 @@ def reportbytecodecounts(self): os.write(2, "Starting bytecode report.\n") fd = os.open('bytecode.txt', os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0644) - for opcode, count in self.bytecodecounts.items(): - os.write(fd, str(opcode) + ", " + str(count) + "\n") + os.write(fd, "bytecodecounts = {\n") + for opcode in range(len(self.bytecodecounts)): + count = self.bytecodecounts[opcode] + if not count: + continue + os.write(fd, " %s: %s,\n" % (opcode, count)) + os.write(fd, "}\n") + os.write(fd, "bytecodetransitioncount = {\n") + for opcode, probs in self.bytecodetransitioncount.iteritems(): + os.write(fd, " %s: {\n" % (opcode, )) + for nextcode, count in probs.iteritems(): + os.write(fd, " %s: %s,\n" % (nextcode, count)) + os.write(fd, " },\n") + os.write(fd, "}\n") os.close(fd) os.write(2, "Reporting done.\n") Modified: pypy/trunk/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/trunk/pypy/interpreter/pyopcode.py (original) +++ pypy/trunk/pypy/interpreter/pyopcode.py Thu Mar 19 15:33:14 2009 @@ -65,6 +65,9 @@ """A PyFrame that knows about interpretation of standard Python opcodes minus the ones related to nested scopes.""" + # for logbytecode: + last_opcode = -1 + ### opcode dispatch ### def dispatch(self, pycode, next_instr, ec): @@ -174,7 +177,13 @@ opcode = ord(co_code[next_instr]) next_instr += 1 if space.config.objspace.logbytecodes: - space.bytecodecounts[opcode] = space.bytecodecounts.get(opcode, 0) + 1 + space.bytecodecounts[opcode] += 1 + try: + probs = space.bytecodetransitioncount[self.last_opcode] + except KeyError: + probs = space.bytecodetransitioncount[self.last_opcode] = {} + probs[opcode] = probs.get(opcode, 0) + 1 + self.last_opcode = opcode if opcode >= HAVE_ARGUMENT: lo = ord(co_code[next_instr]) From arigo at codespeak.net Thu Mar 19 15:36:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 15:36:27 +0100 (CET) Subject: [pypy-svn] r63074 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090319143627.E7CDF168454@codespeak.net> Author: arigo Date: Thu Mar 19 15:36:26 2009 New Revision: 63074 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Make the liveboxes lists more compact, with a test, step 1. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Mar 19 15:36:26 2009 @@ -263,6 +263,9 @@ def make_bytecode_block(self, block): if block.exits == (): + # note: the same label might be generated multiple times, but a + # jump to this label is free to pick whichever target so it's fine + self.emit(label(block)) if len(block.inputargs) == 1: # return from function returnvar, = block.inputargs @@ -316,20 +319,19 @@ self.make_bytecode_block(link.target) elif (len(block.exits) == 2 and block.exitswitch.concretetype == lltype.Bool): - self.minimize_variables() linkfalse, linktrue = block.exits if linkfalse.llexitcase == True: linkfalse, linktrue = linktrue, linkfalse - truerenaming = self.insert_renaming(linktrue.args) - falserenaming = self.insert_renaming(linkfalse.args) + truelist = self.get_renaming_list(linktrue.args) + falselist = self.get_renaming_list(linkfalse.args) self.emit("goto_if_not", self.var_position(block.exitswitch), - tlabel(linkfalse)) - self.emit(*truerenaming) + tlabel(linkfalse.target)) + self.emit(len(truelist), *truelist) + self.emit(len(falselist), *falselist) self.make_bytecode_block(linktrue.target) - self.emit(label(linkfalse)) - self.emit(*falserenaming) - self.make_bytecode_block(linkfalse.target) + if linkfalse.target not in self.seen_blocks: + self.make_bytecode_block(linkfalse.target) else: self.minimize_variables() switches = [link for link in block.exits @@ -411,18 +413,18 @@ self.emit("put_last_exc_value", i) self.make_bytecode_block(link.target) - def insert_renaming(self, args, force=False): + def get_renaming_list(self, args): args = [v for v in args if v.concretetype is not lltype.Void] - if len(args) >= MAX_MAKE_NEW_VARS: - code = ["make_new_vars", len(args)] - else: - code = ["make_new_vars_%d" % len(args)] - for v in args: - code.append(self.var_position(v)) - if (not force and len(args) == self.free_vars and - code[len(code)-len(args):] == range(0, self.free_vars*2, 2)): + return [self.var_position(v) for v in args] + + def insert_renaming(self, args, force=False): + list = self.get_renaming_list(args) + if not force and list == range(0, self.free_vars*2, 2): return [] # no-op - return code + if len(list) >= MAX_MAKE_NEW_VARS: + return ["make_new_vars", len(list)] + list + else: + return ["make_new_vars_%d" % len(list)] + list def minimize_variables(self): if self.dont_minimize_variables: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 19 15:36:26 2009 @@ -279,22 +279,28 @@ def opimpl_goto(self, target): self.pc = target - @arguments("box", "jumptarget") - def opimpl_goto_if_not(self, box, target): + @arguments("box", "jumptarget", "varargs", "varargs") + def opimpl_goto_if_not(self, box, target, truelist, falselist): switchcase = box.getint() if switchcase: currentpc = self.pc + currentenv = truelist targetpc = target + targetenv = falselist opnum = rop.GUARD_TRUE const_if_fail = history.CONST_FALSE else: currentpc = target + currentenv = falselist targetpc = self.pc + targetenv = truelist opnum = rop.GUARD_FALSE const_if_fail = history.CONST_TRUE + self.env = targetenv self.generate_guard(targetpc, opnum, box, ignore_box=box, const_if_fail=const_if_fail) self.pc = currentpc + self.env = currentenv @arguments("orgpc", "box", "constargs", "jumptargets") def opimpl_switch(self, pc, valuebox, constargs, jumptargets): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Thu Mar 19 15:36:26 2009 @@ -142,9 +142,16 @@ return res res = self.meta_interp(f, [6, 7]) assert res == 42 + self.check_loop_count(1) self.check_loops({'merge_point': 1, 'guard_true': 1, 'int_add': 1, 'int_sub': 1, 'int_gt': 1, 'jump': 1}) + if self.basic: + for op in get_stats().loops[0].operations: + if op.getopname() == 'guard_true': + liveboxes = op.liveboxes + assert len(liveboxes) == 1 + assert isinstance(liveboxes[0], history.BoxInt) def test_string(self): def f(n): From cami at codespeak.net Thu Mar 19 15:44:56 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 19 Mar 2009 15:44:56 +0100 (CET) Subject: [pypy-svn] r63075 - pypy/trunk/pypy/translator/goal Message-ID: <20090319144456.DFFE0168466@codespeak.net> Author: cami Date: Thu Mar 19 15:44:53 2009 New Revision: 63075 Modified: pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py Log: added exectuion count as arg to the target Modified: pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py (original) +++ pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py Thu Mar 19 15:44:53 2009 @@ -8,9 +8,11 @@ def entry_point(argv=None): if argv is not None and len(argv) > 1: filename = argv[1] + execution_seconds = int(argv[2]) else: pos = str(9) filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" + execution_seconds = 600 gameBoy = GameBoyProfiler() try: gameBoy.load_cartridge_file(str(filename)) @@ -18,7 +20,7 @@ gameBoy.load_cartridge_file(str(filename), verify=False) start = time.time() - gameBoy.mainLoop() + gameBoy.mainLoop(execution_seconds) print time.time() - start return 0 From cami at codespeak.net Thu Mar 19 15:45:15 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 19 Mar 2009 15:45:15 +0100 (CET) Subject: [pypy-svn] r63076 - pypy/trunk/pypy/lang/gameboy/profiling Message-ID: <20090319144515.CA338168466@codespeak.net> Author: cami Date: Thu Mar 19 15:45:14 2009 New Revision: 63076 Modified: pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Log: added execution time as target option Modified: pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Thu Mar 19 15:45:14 2009 @@ -27,10 +27,10 @@ self.video_driver = VideoDriver() self.sound_driver = SoundDriver() - def mainLoop(self): + def mainLoop(self, execution_seconds): self.reset() self.is_running = True - for i in range(600 * FPS): + for i in range(execution_seconds * FPS): self.emulate_cycle() def emulate_cycle(self): From pedronis at codespeak.net Thu Mar 19 15:46:57 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 15:46:57 +0100 (CET) Subject: [pypy-svn] r63077 - in pypy/trunk/pypy/objspace/std: . test Message-ID: <20090319144657.A619C168466@codespeak.net> Author: pedronis Date: Thu Mar 19 15:46:57 2009 New Revision: 63077 Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py pypy/trunk/pypy/objspace/std/unicodeobject.py Log: (iko, pedronis) given RPython agreed behavior is not worth trying to hard to separate OverflowErrors from MemoryError conditions in these unicode ops Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Thu Mar 19 15:46:57 2009 @@ -415,7 +415,7 @@ import sys if sys.maxint > (1 << 32): skip("Wrong platform") - raises(OverflowError, u't\tt\t'.expandtabs, sys.maxint) + raises((OverflowError, MemoryError), u't\tt\t'.expandtabs, sys.maxint) def test_translate(self): assert u'bbbc' == u'abababc'.translate({ord('a'):None}) Modified: pypy/trunk/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/unicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/unicodeobject.py Thu Mar 19 15:46:57 2009 @@ -266,7 +266,7 @@ try: result_size = ovfcheck(length * times) result = u''.join([uni] * times) - except (OverflowError, MemoryError): + except OverflowError: raise OperationError(space.w_OverflowError, space.wrap('repeated string is too long')) return W_UnicodeObject(result) @@ -850,7 +850,7 @@ totalsize = ovfcheck(totalsize + pad) totalsize = ovfcheck(totalsize + len(nextpart)) result.append(u' ' * pad) - except (OverflowError, MemoryError): + except OverflowError: raise OperationError(space.w_OverflowError, space.wrap('new string is too long')) result.append(nextpart) prevsize = 0 From arigo at codespeak.net Thu Mar 19 15:55:19 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 15:55:19 +0100 (CET) Subject: [pypy-svn] r63078 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090319145519.7CF7B16847F@codespeak.net> Author: arigo Date: Thu Mar 19 15:55:18 2009 New Revision: 63078 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Kill the const_if_fail hack. It's not needed any more because the value we "goto_if_not" on is typically not passed further, so it won't appear in the liveboxes. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 19 15:55:18 2009 @@ -288,17 +288,14 @@ targetpc = target targetenv = falselist opnum = rop.GUARD_TRUE - const_if_fail = history.CONST_FALSE else: currentpc = target currentenv = falselist targetpc = self.pc targetenv = truelist opnum = rop.GUARD_FALSE - const_if_fail = history.CONST_TRUE self.env = targetenv - self.generate_guard(targetpc, opnum, box, ignore_box=box, - const_if_fail=const_if_fail) + self.generate_guard(targetpc, opnum, box) self.pc = currentpc self.env = currentenv @@ -626,8 +623,7 @@ if stop: break - def generate_guard(self, pc, opnum, box, extraargs=[], ignore_box=None, - const_if_fail=None): + def generate_guard(self, pc, opnum, box, extraargs=[]): if isinstance(box, Const): # no need for a guard return if isinstance(self.metainterp.history, history.BlackHole): @@ -636,11 +632,7 @@ for frame in self.metainterp.framestack: for framebox in frame.env: assert framebox is not None - if framebox is not ignore_box: - liveboxes.append(framebox) - else: - assert const_if_fail is not None - liveboxes.append(const_if_fail) + liveboxes.append(framebox) if box is not None: extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opnum, extraargs, None) @@ -992,11 +984,6 @@ exception_target) assert nbindex == len(newboxes), "too many newboxes!" - def record_compiled_merge_point(self, mp): - pass - #mplist = self.compiled_merge_points.setdefault(mp.greenkey, []) - #mplist.append(mp) - def record_state(self): # XXX this whole function should do a sharing key = [] From cfbolz at codespeak.net Thu Mar 19 16:02:12 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 19 Mar 2009 16:02:12 +0100 (CET) Subject: [pypy-svn] r63079 - in pypy/branch/spy-graphic/pypy: lang/smalltalk translator/goal Message-ID: <20090319150212.CCF1A168486@codespeak.net> Author: cfbolz Date: Thu Mar 19 16:02:12 2009 New Revision: 63079 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py Log: shuffle stuff around a bit Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Thu Mar 19 16:02:12 2009 @@ -38,8 +38,7 @@ def interpret(self): try: - while True: - self.step() + self.loop() except ReturnFromTopLevel, e: return e.object @@ -51,38 +50,44 @@ return option.prim_trace def step(self): + """NOT_RPYTHON: only for testing""" s_active_context = self.s_active_context() next = s_active_context.getNextBytecode() - # we_are_translated returns false on top of CPython and true when - # translating the interpreter - if not objectmodel.we_are_translated(): - bytecodeimpl = BYTECODE_TABLE[next] + bytecodeimpl = BYTECODE_TABLE[next] - if self.should_trace(): - if self._w_last_active_context != self.w_active_context(): - cnt = 0 - p = self.w_active_context() - # AK make method - while not p.is_same_object(self.space.w_nil): - cnt += 1 - # Do not update the context - # for this action. - p = p.as_context_get_shadow(self.space).w_sender() - self._last_indent = " " * cnt - self._w_last_active_context = self.w_active_context() - - print "%sStack=%s" % ( - self._last_indent, - repr(s_active_context.stack()),) - print "%sBytecode at %d (%d:%s):" % ( - self._last_indent, - s_active_context.pc(), - next, bytecodeimpl.__name__,) + if self.should_trace(): + if self._w_last_active_context != self.w_active_context(): + cnt = 0 + p = self.w_active_context() + # AK make method + while not p.is_same_object(self.space.w_nil): + cnt += 1 + # Do not update the context + # for this action. + p = p.as_context_get_shadow(self.space).w_sender() + self._last_indent = " " * cnt + self._w_last_active_context = self.w_active_context() + + print "%sStack=%s" % ( + self._last_indent, + repr(s_active_context.stack()),) + print "%sBytecode at %d (%d:%s):" % ( + self._last_indent, + s_active_context.pc(), + next, bytecodeimpl.__name__,) - bytecodeimpl(s_active_context, self) + bytecodeimpl(s_active_context, self) + def loop(self): + # we_are_translated returns false on top of CPython and true when + # translating the interpreter + if not objectmodel.we_are_translated(): + while True: + self.step() else: - bytecode_dispatch_translated(self, s_active_context, next) + s_active_context = self.s_active_context() + next = s_active_context.getNextBytecode() + bytecode_loop_translated(self, s_active_context, next) class ReturnFromTopLevel(Exception): @@ -550,7 +555,8 @@ # interpreter, the bytecode dispatching is not implemented as a # list lookup and an indirect call but as a switch. - code = ["def bytecode_dispatch_translated(self, context, bytecode):"] + code = ["def bytecode_loop_translated(self, context, bytecode):"] + code.append(" while 1:") prefix = "" for entry in BYTECODE_RANGES: if len(entry) == 2: @@ -559,14 +565,16 @@ numbers = range(entry[0], entry[1]+1) cond = " or ".join(["bytecode == %s" % (i, ) for i in numbers]) - code.append(" %sif %s:" % (prefix, cond, )) - code.append(" context.%s(self)" % (entry[-1], )) + code.append(" %sif %s:" % (prefix, cond, )) + code.append(" context.%s(self)" % (entry[-1], )) + code.append(" context = self.s_active_context()") + code.append(" bytecode = context.getNextBytecode()") prefix = "el" - code.append("bytecode_dispatch_translated._always_inline_ = True") + code.append("bytecode_loop_translated._always_inline_ = True") source = py.code.Source("\n".join(code)) print source miniglob = {} exec source.compile() in miniglob - return miniglob["bytecode_dispatch_translated"] + return miniglob["bytecode_loop_translated"] -bytecode_dispatch_translated = make_bytecode_dispatch_translated() +bytecode_loop_translated = make_bytecode_dispatch_translated() Modified: pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py ============================================================================== --- pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py (original) +++ pypy/branch/spy-graphic/pypy/translator/goal/targetimageloadingsmalltalk.py Thu Mar 19 16:02:12 2009 @@ -28,18 +28,14 @@ def run_benchmarks(interp): counter = 0 try: - while True: - counter += 1 - interp.step() - if counter == 100000: - counter = 0 - os.write(2, '#') + interp.loop() except interpreter.ReturnFromTopLevel, e: w_result = e.object - assert isinstance(w_result, model.W_BytesObject) - print w_result.as_string() - return 0 + assert isinstance(w_result, model.W_BytesObject) + print w_result.as_string() + return 0 + return -1 from pypy.lang.smalltalk import objspace space = objspace.ObjSpace() From pedronis at codespeak.net Thu Mar 19 16:02:27 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 16:02:27 +0100 (CET) Subject: [pypy-svn] r63080 - pypy/trunk/pypy/lib/app_test Message-ID: <20090319150227.D003F168486@codespeak.net> Author: pedronis Date: Thu Mar 19 16:02:26 2009 New Revision: 63080 Modified: pypy/trunk/pypy/lib/app_test/test_functools.py Log: (iko, pedronis) applying the same fixes from lib-python/modified-2.5.2/ to the app_test variant of test_functools.py Modified: pypy/trunk/pypy/lib/app_test/test_functools.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/test_functools.py (original) +++ pypy/trunk/pypy/lib/app_test/test_functools.py Thu Mar 19 16:02:26 2009 @@ -122,7 +122,7 @@ p = self.thetype(hex) try: del p.__dict__ - except TypeError: + except (TypeError, AttributeError): pass else: raise AssertionError, 'partial object allowed __dict__ to be deleted' @@ -132,6 +132,8 @@ p = proxy(f) assert f.func == p.func f = None + import gc + gc.collect() py.test.raises(ReferenceError, getattr, p, 'func') def test_with_bound_and_unbound_methods(self): @@ -217,7 +219,7 @@ pass functools.update_wrapper(wrapper, max) assert wrapper.__name__ == 'max' - assert wrapper.__doc__.startswith('max(') + assert wrapper.__doc__ == max.__doc__ class TestWraps(TestUpdateWrapper): From hpk at codespeak.net Thu Mar 19 16:12:34 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 19 Mar 2009 16:12:34 +0100 (CET) Subject: [pypy-svn] r63081 - pypy/extradoc/talk/openbossa2009/pypy-mobile Message-ID: <20090319151234.9E7A5168464@codespeak.net> Author: hpk Date: Thu Mar 19 16:12:33 2009 New Revision: 63081 Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Log: talk as it was given Modified: pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt ============================================================================== --- pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt (original) +++ pypy/extradoc/talk/openbossa2009/pypy-mobile/talk.txt Thu Mar 19 16:12:33 2009 @@ -28,9 +28,9 @@ * Status of PyPy / 1.1 release -* resource usage +* resource usage, measurements on N810 -* ideas, visions, next steps +* ideas and next steps PyPy? ======== @@ -346,8 +346,10 @@ * PyPy can generate a virtualized Python! -* all IO and OS external calls serialized to - separate process +* IO and OS calls controled by separate process + +* RAM and CPU time control + .. image:: sandboxed.png :scale: 30 @@ -356,8 +358,8 @@ Current priorities and interests ================================== -- expect PyPy 1.1 release in around 2 months -- then: JIT to surpass CPython speed +- PyPy 1.1 release in around 2 months +- afterwards: JIT to surpass CPython speed - perfect/commoditize Python sandboxing - help/do compatibility work, ext modules From cfbolz at codespeak.net Thu Mar 19 16:15:59 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 19 Mar 2009 16:15:59 +0100 (CET) Subject: [pypy-svn] r63082 - pypy/trunk/pypy/lib Message-ID: <20090319151559.97274168464@codespeak.net> Author: cfbolz Date: Thu Mar 19 16:15:56 2009 New Revision: 63082 Removed: pypy/trunk/pypy/lib/stackless_old.py Log: kill this old version of the stackless module From arigo at codespeak.net Thu Mar 19 17:03:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 17:03:26 +0100 (CET) Subject: [pypy-svn] r63085 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090319160326.A9E32168487@codespeak.net> Author: arigo Date: Thu Mar 19 17:03:25 2009 New Revision: 63085 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py Log: Add a check. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/targetpypyjit.py Thu Mar 19 17:03:25 2009 @@ -45,6 +45,7 @@ global space, w_dict # config = driver.config + assert config.translation.jit, "you forgot the '--jit' option :-)" parser = opt_parser(config) parser.parse_args(args) # From pedronis at codespeak.net Thu Mar 19 17:14:47 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Mar 2009 17:14:47 +0100 (CET) Subject: [pypy-svn] r63086 - pypy/trunk/pypy/interpreter/test Message-ID: <20090319161447.754D5168459@codespeak.net> Author: pedronis Date: Thu Mar 19 17:14:43 2009 New Revision: 63086 Modified: pypy/trunk/pypy/interpreter/test/test_exec.py Log: (iko, pedronis) test about the compiler issue :( that is the root of the test_code test_code_extra failure Modified: pypy/trunk/pypy/interpreter/test/test_exec.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_exec.py (original) +++ pypy/trunk/pypy/interpreter/test/test_exec.py Thu Mar 19 17:14:43 2009 @@ -201,3 +201,19 @@ eval("'unmatched_quote") except SyntaxError, msg: assert msg.filename == '' + + def test_exec_and_name_lookups(self): + ns = {} + exec """def f(): + exec 'x=1' in locals() + return x +""" in ns + + f = ns['f'] + + try: + res = f() + except NameError, e: # keep py.test from exploding confused + raise e + + assert res == 1 From arigo at codespeak.net Thu Mar 19 17:32:06 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 17:32:06 +0100 (CET) Subject: [pypy-svn] r63087 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090319163206.75C721683E7@codespeak.net> Author: arigo Date: Thu Mar 19 17:32:04 2009 New Revision: 63087 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Fix the failing test_virtualizable the slow way. Now trying to kill AllocationStorage completely... Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 17:32:04 2009 @@ -549,6 +549,13 @@ items = [box for box in liveboxes if isinstance(box, Box)] assert len(dict.fromkeys(items)) == len(items) storage.indices = indices + + # XXX sloooooow! + for node in self.nodes.values(): + if node.virtualized: + storage.deal_with_box(node.source, self.nodes, + liveboxes, memo) + op.args = self.new_arguments(op) op.liveboxes = liveboxes op.storage_info = storage From arigo at codespeak.net Thu Mar 19 19:29:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 19:29:31 +0100 (CET) Subject: [pypy-svn] r63092 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090319182931.26F66168459@codespeak.net> Author: arigo Date: Thu Mar 19 19:29:30 2009 New Revision: 63092 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Remove AllocationStorage, and replace it with a list of operations to interpret when the guard fails. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 19:29:30 2009 @@ -1,5 +1,5 @@ from pypy.jit.metainterp.resoperation import rop -from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, +from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, BoxPtr, ResOperation, AbstractDescr, Options, AbstractValue, ConstPtr) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, @@ -35,77 +35,6 @@ class CancelInefficientLoop(Exception): pass -FLAG_ALLOCATIONS = 0x0 -FLAG_LIST_ALLOCATIONS = 0x1 -FLAG_BOXES_FROM_FRAME = 0x3 -FLAG_SHIFT = 2 -FLAG_MASK = 0x3 - -class AllocationStorage(object): - def __init__(self): - # allocations: list of vtables to allocate - # setfields: list of triples - # (index_of_parent, ofs, index_of_child) - # indexes have two least significant bits representing - # where they're living, look above. - self.allocations = [] - self.setfields = [] - # the same as above, but for lists and for running setitem - self.list_allocations = [] - self.setitems = [] - - def deal_with_box(self, box, nodes, liveboxes, memo): - if isinstance(box, Const) or box not in nodes: - virtual = False - virtualized = False - else: - prevbox = box - instnode = nodes[box] - box = instnode.source - if box in memo: - return memo[box] - virtual = instnode.virtual - virtualized = instnode.virtualized - if virtual: - if isinstance(instnode.cls.source, FixedList): - ld = instnode.cls.source - assert isinstance(ld, FixedList) - alloc_offset = len(self.list_allocations) - ad = ld.arraydescr - self.list_allocations.append((ad, instnode.cursize)) - res = (alloc_offset << FLAG_SHIFT) | FLAG_LIST_ALLOCATIONS - else: - alloc_offset = len(self.allocations) - self.allocations.append(instnode.cls.source.getint()) - res = (alloc_offset << FLAG_SHIFT) | FLAG_ALLOCATIONS - memo[box] = res - for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo) - if isinstance(instnode.cls.source, FixedList): - ld = instnode.cls.source - assert isinstance(ld, FixedList) - self.setitems.append((res, ld.arraydescr, ofs, num)) - else: - self.setfields.append((res, ofs, num)) - elif virtualized: - res = (len(liveboxes) << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME - memo[box] = res - liveboxes.append(box) - for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, - memo) - if instnode.cls and isinstance(instnode.cls.source, FixedList): - ld = instnode.cls.source - assert isinstance(ld, FixedList) - self.setitems.append((res, ld.arraydescr, ofs, num)) - else: - self.setfields.append((res, ofs, num)) - else: - res = (len(liveboxes) << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME - memo[box] = res - liveboxes.append(box) - return res - def av_eq(self, other): return self.sort_key() == other.sort_key() @@ -510,55 +439,118 @@ specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) return newboxlist + def prepare_rebuild_ops(self, instnode, liveboxes, rebuild_ops, memo): + box = instnode.source + if box in memo: + return memo[box] + if instnode.virtual: + newbox = BoxPtr() + ld = instnode.cls.source + if isinstance(ld, FixedList): + ad = ld.arraydescr + sizebox = ConstInt(instnode.cursize) + op = ResOperation(rop.NEW_ARRAY, [sizebox], newbox, + descr=ad) + else: + vtable = ld.getint() + if self.cpu is None: + size = ConstInt(-1) # for tests only! + elif self.cpu.translate_support_code: + vtable_addr = self.cpu.cast_int_to_adr(vtable) + size = self.cpu.class_sizes[vtable_addr] + else: + size = self.cpu.class_sizes[vtable] + op = ResOperation(rop.NEW_WITH_VTABLE, [ld], newbox, + descr=size) + rebuild_ops.append(op) + memo[box] = newbox + for ofs, node in instnode.curfields.items(): + fieldbox = self.prepare_rebuild_ops(node, liveboxes, + rebuild_ops, memo) + if isinstance(ld, FixedList): + op = ResOperation(rop.SETARRAYITEM_GC, + [newbox, ofs, fieldbox], + None, descr=ld.arraydescr) + else: + op = ResOperation(rop.SETFIELD_GC, [newbox, fieldbox], + None, descr=ofs) + rebuild_ops.append(op) + return newbox + liveboxes.append(box) + memo[box] = box + if instnode.virtualized: + for ofs, node in instnode.curfields.items(): + fieldbox = self.prepare_rebuild_ops(node, liveboxes, + rebuild_ops, memo) + if instnode.cls and isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + assert isinstance(ld, FixedList) + op = ResOperation(rop.SETARRAYITEM_GC, + [box, ofs, fieldbox], + None, descr=ld.arraydescr) + else: + op = ResOperation(rop.SETFIELD_GC, [box, fieldbox], + None, descr=ofs) + rebuild_ops.append(op) + return box + def optimize_guard(self, op): + # Make a list of operations to run to rebuild the unoptimized objects. + # The ops assume that the Boxes in 'liveboxes' have been reloaded. liveboxes = [] - storage = AllocationStorage() + rebuild_ops = [] memo = {} - indices = [] old_boxes = op.liveboxes op = op.clone() + unoptboxes = [] for box in old_boxes: - indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo)) - rev_boxes = {} - for i in range(len(liveboxes)): - box = liveboxes[i] - rev_boxes[box] = i + if isinstance(box, Const): + unoptboxes.append(box) + continue + unoptboxes.append(self.prepare_rebuild_ops(self.nodes[box], + liveboxes, rebuild_ops, + memo)) + # XXX sloooooow! + for node in self.nodes.values(): + if node.virtualized: + self.prepare_rebuild_ops(node, liveboxes, rebuild_ops, memo) + + # start of code for dirtyfields support for node in self.nodes.values(): for ofs, subnode in node.dirtyfields.items(): box = node.source - if box not in rev_boxes: - rev_boxes[box] = len(liveboxes) + if box not in memo: liveboxes.append(box) - index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME + memo[box] = box + #index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME fieldbox = subnode.source - if fieldbox not in rev_boxes: - rev_boxes[fieldbox] = len(liveboxes) + if fieldbox not in memo: liveboxes.append(fieldbox) - fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | - FLAG_BOXES_FROM_FRAME) + memo[fieldbox] = fieldbox + #fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | + # FLAG_BOXES_FROM_FRAME) if (node.cls is not None and isinstance(node.cls.source, FixedList)): ld = node.cls.source assert isinstance(ld, FixedList) ad = ld.arraydescr - storage.setitems.append((index, ad, ofs, fieldindex)) + op1 = ResOperation(rop.SETARRAYITEM_GC, + [box, ofs, fieldbox], + None, descr=ad) else: - storage.setfields.append((index, ofs, fieldindex)) + op1 = ResOperation(rop.SETFIELD_GC, [box, fieldbox], + None, descr=ofs) + rebuild_ops.append(op1) + # end of code for dirtyfields support + if not we_are_translated(): items = [box for box in liveboxes if isinstance(box, Box)] assert len(dict.fromkeys(items)) == len(items) - storage.indices = indices - - # XXX sloooooow! - for node in self.nodes.values(): - if node.virtualized: - storage.deal_with_box(node.source, self.nodes, - liveboxes, memo) op.args = self.new_arguments(op) op.liveboxes = liveboxes - op.storage_info = storage + op.rebuild_ops = rebuild_ops + op.unoptboxes = unoptboxes return op def new_arguments(self, op): @@ -839,61 +831,35 @@ new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode) -class Chooser(object): - def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists): - self.boxes_from_frame = boxes_from_frame - self.allocated_lists = allocated_lists - self.allocated_boxes = allocated_boxes - - def box_from_index(self, index): - ofs = index >> FLAG_SHIFT - where_from = index & FLAG_MASK - if where_from == FLAG_BOXES_FROM_FRAME: - return self.boxes_from_frame[ofs] - elif where_from == FLAG_ALLOCATIONS: - return self.allocated_boxes[ofs] - elif where_from == FLAG_LIST_ALLOCATIONS: - return self.allocated_lists[ofs] - else: - assert 0, "Should not happen" +def get_in_list(dict, boxes_or_consts): + result = [] + for box in boxes_or_consts: + if isinstance(box, Box): + box = dict[box] + result.append(box) + return result def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): - allocated_boxes = [] - allocated_lists = [] - storage = guard_op.storage_info - - for vtable in storage.allocations: - if metainterp.cpu.translate_support_code: - vtable_addr = metainterp.cpu.cast_int_to_adr(vtable) - size = metainterp.class_sizes[vtable_addr] - else: - size = metainterp.class_sizes[vtable] - vtablebox = ConstInt(vtable) - instbox = metainterp.execute_and_record(rop.NEW_WITH_VTABLE, - [vtablebox], size) - allocated_boxes.append(instbox) - for ad, lgt in storage.list_allocations: - sizebox = ConstInt(lgt) - listbox = metainterp.execute_and_record(rop.NEW_ARRAY, - [sizebox], ad) - allocated_lists.append(listbox) - chooser = Chooser(boxes_from_frame, allocated_boxes, allocated_lists) - for index_in_alloc, ofs, index_in_arglist in storage.setfields: - fieldbox = chooser.box_from_index(index_in_arglist) - box = chooser.box_from_index(index_in_alloc) - assert isinstance(ofs, AbstractDescr) - metainterp.execute_and_record(rop.SETFIELD_GC, - [box, fieldbox], ofs) - for index_in_alloc, ad, ofs, index_in_arglist in storage.setitems: - itembox = chooser.box_from_index(index_in_arglist) - box = chooser.box_from_index(index_in_alloc) - metainterp.execute_and_record(rop.SETARRAYITEM_GC, - [box, ofs, itembox], ad) - newboxes = [] - for index in storage.indices: - newboxes.append(chooser.box_from_index(index)) - - return newboxes +## print +## print guard_op.liveboxes +## for op in guard_op.rebuild_ops: +## print op +## print guard_op.unoptboxes +## print '^'*79 +## import pdb; pdb.set_trace() + currentvalues = {} + assert len(boxes_from_frame) == len(guard_op.liveboxes) + for i in range(len(boxes_from_frame)): + currentvalues[guard_op.liveboxes[i]] = boxes_from_frame[i] + + # interpret the operations stored in 'rebuild_ops' + for op in guard_op.rebuild_ops: + argboxes = get_in_list(currentvalues, op.args) + resbox = metainterp.execute_and_record(op.opnum, argboxes, op.descr) + if resbox is not None: + currentvalues[op.result] = resbox + # done + return get_in_list(currentvalues, guard_op.unoptboxes) def partition(array, left, right): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 19 19:29:30 2009 @@ -681,7 +681,6 @@ class OOMetaInterp(object): num_green_args = 0 - class_sizes = None def __init__(self, portal_graph, graphs, cpu, stats, options): self.portal_graph = portal_graph @@ -696,16 +695,18 @@ self.opname_to_index = {} self._class_sizes = populate_type_cache(graphs, self.cpu) if not cpu.translate_support_code: - self.class_sizes = self._class_sizes + self.cpu.class_sizes = self._class_sizes + else: + self.cpu.class_sizes = None self._virtualizabledescs = {} self._debug_history = [] def _recompute_class_sizes(self): - if self.class_sizes is None: + if self.cpu.class_sizes is None: cs = {} for key, value in self._class_sizes: cs[key] = value - self.class_sizes = cs + self.cpu.class_sizes = cs def generate_bytecode(self, policy): self._codewriter = codewriter.CodeWriter(self, policy) @@ -718,7 +719,6 @@ return not we_are_translated() def newframe(self, jitcode): - self._recompute_class_sizes() if not we_are_translated(): self._debug_history.append(['enter', jitcode, None]) f = MIFrame(self, jitcode) @@ -919,6 +919,7 @@ *args[1:]) def initialize_state_from_start(self, *args): + self._recompute_class_sizes() self.create_empty_history() num_green_args = self.num_green_args original_boxes = [] @@ -947,7 +948,7 @@ else: newbox = box boxes_from_frame.append(newbox) - if guard_op.storage_info is not None: + if guard_op.rebuild_ops is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( guard_op, self, boxes_from_frame) else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Thu Mar 19 19:29:30 2009 @@ -11,8 +11,9 @@ # for 'guard_*' counter = 0 - storage_info = None liveboxes = None + rebuild_ops = None + unoptboxes = None # for 'guard_nonvirtualizable' vdesc = None Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_list_optimize.py Thu Mar 19 19:29:30 2009 @@ -4,8 +4,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, - rebuild_boxes_from_guard_failure, AllocationStorage, - NotSpecNode, FixedList) + rebuild_boxes_from_guard_failure, NotSpecNode, FixedList) from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from pypy.jit.metainterp.test.test_optimize import Loop, equaloplists, cpu from pypy.jit.metainterp.specnode import DelayedFixedListSpecNode Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 19 19:29:30 2009 @@ -11,8 +11,7 @@ ConstAddr) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, - rebuild_boxes_from_guard_failure, AllocationStorage, - NotSpecNode) + rebuild_boxes_from_guard_failure, NotSpecNode) cpu = runner.CPU(None) @@ -308,8 +307,14 @@ assert guard_op.getopname() == 'guard_true' assert guard_op.liveboxes == [E.sum2, E.v2] vt = cpu.cast_adr_to_int(node_vtable_adr) - assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, E.ofs_value, 7)] + assert len(guard_op.unoptboxes) == 2 + assert guard_op.unoptboxes[0] == E.sum2 + assert len(guard_op.rebuild_ops) == 2 + assert guard_op.rebuild_ops[0].opnum == rop.NEW_WITH_VTABLE + assert guard_op.rebuild_ops[1].opnum == rop.SETFIELD_GC + assert guard_op.rebuild_ops[1].args[0] == guard_op.rebuild_ops[0].result + assert guard_op.rebuild_ops[1].descr == E.ofs_value + assert guard_op.unoptboxes[1] == guard_op.rebuild_ops[1].args[0] def test_E_rebuild_after_failure(): class FakeMetaInterp(object): @@ -323,7 +328,7 @@ def execute_and_record(self, opnum, args, descr): self.ops.append((opnum, args, descr)) return 'stuff' - + spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -331,12 +336,12 @@ guard_op = spec.loop.operations[-2] v_sum_b = BoxInt(13) v_v_b = BoxInt(14) - vt = cpu.cast_adr_to_int(node_vtable_adr) fake_metainterp = FakeMetaInterp() newboxes = rebuild_boxes_from_guard_failure(guard_op, fake_metainterp, [v_sum_b, v_v_b]) + v_vt = ConstAddr(node_vtable_adr, cpu) expected = [ - (rop.NEW_WITH_VTABLE, [ConstInt(vt)], E.size_of_node), + (rop.NEW_WITH_VTABLE, [v_vt], ConstInt(-1)), # "-1" is for testing (rop.SETFIELD_GC, ['stuff', v_v_b], E.ofs_value) ] assert expected == fake_metainterp.ops @@ -460,8 +465,8 @@ assert guard_op.getopname() == 'guard_true' assert guard_op.liveboxes == [G.sum2, ConstInt(124)] vt = cpu.cast_adr_to_int(node_vtable_adr) - assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, G.ofs_value, 7)] + assert ([op.getopname() for op in guard_op.rebuild_ops] == + ['new_with_vtable', 'setfield_gc']) # ____________________________________________________________ From arigo at codespeak.net Thu Mar 19 19:37:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 19:37:27 +0100 (CET) Subject: [pypy-svn] r63093 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090319183727.4F4C4168466@codespeak.net> Author: arigo Date: Thu Mar 19 19:37:26 2009 New Revision: 63093 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: RPython fixes. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Thu Mar 19 19:37:26 2009 @@ -218,3 +218,8 @@ func = get_execute_function(cpu, opnum) return func(cpu, argboxes, descr) execute._annspecialcase_ = 'specialize:arg(1)' + +def execute_nonspec(cpu, opnum, argboxes, descr=None): + check_descr(descr) + func = cpu._execute_list[opnum] + return func(cpu, argboxes, descr) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 19:37:26 2009 @@ -472,6 +472,7 @@ [newbox, ofs, fieldbox], None, descr=ld.arraydescr) else: + assert isinstance(ofs, AbstractDescr) op = ResOperation(rop.SETFIELD_GC, [newbox, fieldbox], None, descr=ofs) rebuild_ops.append(op) @@ -489,6 +490,7 @@ [box, ofs, fieldbox], None, descr=ld.arraydescr) else: + assert isinstance(ofs, AbstractDescr) op = ResOperation(rop.SETFIELD_GC, [box, fieldbox], None, descr=ofs) rebuild_ops.append(op) @@ -538,6 +540,7 @@ [box, ofs, fieldbox], None, descr=ad) else: + assert isinstance(ofs, AbstractDescr) op1 = ResOperation(rop.SETFIELD_GC, [box, fieldbox], None, descr=ofs) rebuild_ops.append(op1) @@ -853,9 +856,10 @@ currentvalues[guard_op.liveboxes[i]] = boxes_from_frame[i] # interpret the operations stored in 'rebuild_ops' + cpu = metainterp.cpu for op in guard_op.rebuild_ops: argboxes = get_in_list(currentvalues, op.args) - resbox = metainterp.execute_and_record(op.opnum, argboxes, op.descr) + resbox = executor.execute_nonspec(cpu, op.opnum, argboxes, op.descr) if resbox is not None: currentvalues[op.result] = resbox # done From arigo at codespeak.net Thu Mar 19 19:53:21 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 19:53:21 +0100 (CET) Subject: [pypy-svn] r63094 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090319185321.AACBD16847C@codespeak.net> Author: arigo Date: Thu Mar 19 19:53:18 2009 New Revision: 63094 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Fixes for test_optimize.py. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 19:53:18 2009 @@ -453,9 +453,7 @@ descr=ad) else: vtable = ld.getint() - if self.cpu is None: - size = ConstInt(-1) # for tests only! - elif self.cpu.translate_support_code: + if self.cpu.translate_support_code: vtable_addr = self.cpu.cast_int_to_adr(vtable) size = self.cpu.class_sizes[vtable_addr] else: @@ -842,7 +840,7 @@ result.append(box) return result -def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): +def rebuild_boxes_from_guard_failure(guard_op, cpu, boxes_from_frame): ## print ## print guard_op.liveboxes ## for op in guard_op.rebuild_ops: @@ -856,7 +854,6 @@ currentvalues[guard_op.liveboxes[i]] = boxes_from_frame[i] # interpret the operations stored in 'rebuild_ops' - cpu = metainterp.cpu for op in guard_op.rebuild_ops: argboxes = get_in_list(currentvalues, op.args) resbox = executor.execute_nonspec(cpu, op.opnum, argboxes, op.descr) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 19 19:53:18 2009 @@ -950,7 +950,7 @@ boxes_from_frame.append(newbox) if guard_op.rebuild_ops is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( - guard_op, self, boxes_from_frame) + guard_op, self.cpu, boxes_from_frame) else: # xxx for tests only newboxes = boxes_from_frame Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 19 19:53:18 2009 @@ -29,6 +29,8 @@ node2_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) node2_vtable_adr = llmemory.cast_ptr_to_adr(node2_vtable) +cpu.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE)} + # ____________________________________________________________ @@ -291,7 +293,7 @@ ops[-2].liveboxes = [sum2, n2] def test_E_optimize_loop(): - spec = PerfectSpecializer(Loop(E.ops)) + spec = PerfectSpecializer(Loop(E.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() @@ -317,35 +319,19 @@ assert guard_op.unoptboxes[1] == guard_op.rebuild_ops[1].args[0] def test_E_rebuild_after_failure(): - class FakeMetaInterp(object): - def __init__(self): - self.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): - E.size_of_node} - self.cpu = cpu - self.cpu.translate_support_code = False - self.ops = [] - - def execute_and_record(self, opnum, args, descr): - self.ops.append((opnum, args, descr)) - return 'stuff' - - spec = PerfectSpecializer(Loop(E.ops)) + spec = PerfectSpecializer(Loop(E.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() guard_op = spec.loop.operations[-2] v_sum_b = BoxInt(13) v_v_b = BoxInt(14) - fake_metainterp = FakeMetaInterp() - newboxes = rebuild_boxes_from_guard_failure(guard_op, fake_metainterp, + newboxes = rebuild_boxes_from_guard_failure(guard_op, cpu, [v_sum_b, v_v_b]) - v_vt = ConstAddr(node_vtable_adr, cpu) - expected = [ - (rop.NEW_WITH_VTABLE, [v_vt], ConstInt(-1)), # "-1" is for testing - (rop.SETFIELD_GC, ['stuff', v_v_b], E.ofs_value) - ] - assert expected == fake_metainterp.ops - assert newboxes == [v_sum_b, 'stuff'] + assert len(newboxes) == 2 + assert newboxes[0] == v_sum_b + p = newboxes[1].getptr(lltype.Ptr(NODE)) + assert p.value == 14 # ____________________________________________________________ @@ -386,7 +372,7 @@ assert not spec.nodes[F.n2].escaped def test_F_optimize_loop(): - spec = PerfectSpecializer(Loop(F.ops)) + spec = PerfectSpecializer(Loop(F.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped @@ -419,7 +405,7 @@ ops[2].liveboxes = [n2] def test_F2_optimize_loop(): - spec = PerfectSpecializer(Loop(F2.ops)) + spec = PerfectSpecializer(Loop(F2.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() @@ -449,7 +435,7 @@ ops[-2].liveboxes = [sum2, n2] def test_G_optimize_loop(): - spec = PerfectSpecializer(Loop(G.ops)) + spec = PerfectSpecializer(Loop(G.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() From arigo at codespeak.net Thu Mar 19 20:02:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 20:02:11 +0100 (CET) Subject: [pypy-svn] r63095 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090319190211.7CB7B168473@codespeak.net> Author: arigo Date: Thu Mar 19 20:02:10 2009 New Revision: 63095 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: More small fixes. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 20:02:10 2009 @@ -840,7 +840,7 @@ result.append(box) return result -def rebuild_boxes_from_guard_failure(guard_op, cpu, boxes_from_frame): +def rebuild_boxes_from_guard_failure(guard_op, cpu, history, boxes_from_frame): ## print ## print guard_op.liveboxes ## for op in guard_op.rebuild_ops: @@ -856,7 +856,9 @@ # interpret the operations stored in 'rebuild_ops' for op in guard_op.rebuild_ops: argboxes = get_in_list(currentvalues, op.args) + # similar to execute_and_record, but not specialized on op.opnum resbox = executor.execute_nonspec(cpu, op.opnum, argboxes, op.descr) + history.record(op.opnum, argboxes, resbox, op.descr) if resbox is not None: currentvalues[op.result] = resbox # done Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 19 20:02:10 2009 @@ -950,7 +950,7 @@ boxes_from_frame.append(newbox) if guard_op.rebuild_ops is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( - guard_op, self.cpu, boxes_from_frame) + guard_op, self.cpu, self.history, boxes_from_frame) else: # xxx for tests only newboxes = boxes_from_frame Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 19 20:02:10 2009 @@ -8,7 +8,7 @@ from pypy.jit.metainterp import resoperation from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - ConstAddr) + ConstAddr, History) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, rebuild_boxes_from_guard_failure, NotSpecNode) @@ -326,12 +326,16 @@ guard_op = spec.loop.operations[-2] v_sum_b = BoxInt(13) v_v_b = BoxInt(14) - newboxes = rebuild_boxes_from_guard_failure(guard_op, cpu, + history = History(cpu) + newboxes = rebuild_boxes_from_guard_failure(guard_op, cpu, history, [v_sum_b, v_v_b]) assert len(newboxes) == 2 assert newboxes[0] == v_sum_b p = newboxes[1].getptr(lltype.Ptr(NODE)) assert p.value == 14 + assert len(history.operations) == 2 + assert ([op.getopname() for op in history.operations] == + ['new_with_vtable', 'setfield_gc']) # ____________________________________________________________ From arigo at codespeak.net Thu Mar 19 20:12:51 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 20:12:51 +0100 (CET) Subject: [pypy-svn] r63096 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090319191251.301B1168487@codespeak.net> Author: arigo Date: Thu Mar 19 20:12:50 2009 New Revision: 63096 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Change 'liveboxes' to not be allowed to contain Consts any more. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Mar 19 20:12:50 2009 @@ -134,8 +134,8 @@ llimpl.compile_add_failnum(c, len(self.guard_ops)) self.guard_ops.append(op) for box in op.liveboxes: - if isinstance(box, history.Box): - llimpl.compile_add_livebox(c, var2index[box]) + assert isinstance(box, history.Box) + llimpl.compile_add_livebox(c, var2index[box]) if op.opnum == rop.MERGE_POINT: self.jumptarget2loop[op] = c, i if from_guard is not None: @@ -175,19 +175,8 @@ if gf.returns: return gf.retbox - def getrealbox(self, guard_op, argindex): - box = None - i = 0 - j = argindex - while j >= 0: - box = guard_op.liveboxes[i] - i += 1 - if isinstance(box, history.Box): - j -= 1 - return box - def getvaluebox(self, frame, guard_op, argindex): - box = self.getrealbox(guard_op, argindex) + box = guard_op.liveboxes[argindex] if isinstance(box, history.BoxInt): value = llimpl.frame_int_getvalue(frame, argindex) return history.BoxInt(value) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Mar 19 20:12:50 2009 @@ -441,6 +441,8 @@ def prepare_rebuild_ops(self, instnode, liveboxes, rebuild_ops, memo): box = instnode.source + if not isinstance(box, Box): + return box if box in memo: return memo[box] if instnode.virtual: @@ -519,12 +521,12 @@ for node in self.nodes.values(): for ofs, subnode in node.dirtyfields.items(): box = node.source - if box not in memo: + if box not in memo and isinstance(box, Box): liveboxes.append(box) memo[box] = box #index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME fieldbox = subnode.source - if fieldbox not in memo: + if fieldbox not in memo and isinstance(fieldbox, Box): liveboxes.append(fieldbox) memo[fieldbox] = fieldbox #fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | @@ -545,8 +547,9 @@ # end of code for dirtyfields support if not we_are_translated(): - items = [box for box in liveboxes if isinstance(box, Box)] - assert len(dict.fromkeys(items)) == len(items) + for box in liveboxes: + assert isinstance(box, Box) + assert len(dict.fromkeys(liveboxes)) == len(liveboxes) op.args = self.new_arguments(op) op.liveboxes = liveboxes @@ -862,7 +865,7 @@ if resbox is not None: currentvalues[op.result] = resbox # done - return get_in_list(currentvalues, guard_op.unoptboxes) + return [currentvalues[box] for box in guard_op.unoptboxes] def partition(array, left, right): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Mar 19 20:12:50 2009 @@ -598,15 +598,19 @@ #self.starts_with_greens() #assert len(argboxes) == len(self.graph.getargs()) - def setup_resume_at_op(self, pc, envlength, liveboxes, lbindex, + def setup_resume_at_op(self, pc, const_part, liveboxes, lbindex, exception_target): if not we_are_translated(): check_args(*liveboxes) self.pc = pc - self.env = liveboxes[lbindex:lbindex+envlength] self.exception_target = exception_target - assert len(self.env) == envlength - return lbindex + envlength + self.env = [] + for box in const_part: + if box is None: + box = liveboxes[lbindex] + lbindex += 1 + self.env.append(box) + return lbindex def run_one_step(self): # Execute the frame forward. This method contains a loop that leaves @@ -628,18 +632,26 @@ return if isinstance(self.metainterp.history, history.BlackHole): return + saved_pc = self.pc + self.pc = pc + # XXX 'key' should be shared, either partially or if possible totally + key = [] liveboxes = [] for frame in self.metainterp.framestack: + const_part = [] for framebox in frame.env: assert framebox is not None - liveboxes.append(framebox) + if isinstance(framebox, Box): + liveboxes.append(framebox) + framebox = None + const_part.append(framebox) + key.append((frame.jitcode, frame.pc, const_part, + frame.exception_target)) if box is not None: extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opnum, extraargs, None) guard_op.liveboxes = liveboxes - saved_pc = self.pc - self.pc = pc - guard_op.key = self.metainterp.record_state() + guard_op.key = key self.pc = saved_pc return guard_op @@ -941,12 +953,10 @@ boxes_from_frame = [] index = 0 for box in guard_op.liveboxes: - if isinstance(box, Box): - newbox = self.cpu.getvaluebox(guard_failure.frame, - guard_op, index) - index += 1 - else: - newbox = box + assert isinstance(box, Box) + newbox = self.cpu.getvaluebox(guard_failure.frame, + guard_op, index) + index += 1 boxes_from_frame.append(newbox) if guard_op.rebuild_ops is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( @@ -979,20 +989,12 @@ self._debug_history.append(['guard_failure', None, None]) self.framestack = [] nbindex = 0 - for jitcode, pc, envlength, exception_target in key: + for jitcode, pc, const_part, exception_target in key: f = self.newframe(jitcode) - nbindex = f.setup_resume_at_op(pc, envlength, newboxes, nbindex, + nbindex = f.setup_resume_at_op(pc, const_part, newboxes, nbindex, exception_target) assert nbindex == len(newboxes), "too many newboxes!" - def record_state(self): - # XXX this whole function should do a sharing - key = [] - for frame in self.framestack: - key.append((frame.jitcode, frame.pc, len(frame.env), - frame.exception_target)) - return key - # ____________________________________________________________ # construction-time interface Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Thu Mar 19 20:12:50 2009 @@ -5,6 +5,7 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp import history class TestLoop(LLJitMixin): specialize = False @@ -163,6 +164,13 @@ self.check_loop_count(1) # the 'char_eq' and following 'guard' should be constant-folded self.check_loops(char_eq=0, guard_true=1, guard_false=0) + if self.basic: + for op in get_stats().loops[0].operations: + if op.getopname() == 'guard_true': + liveboxes = op.liveboxes + assert len(liveboxes) == 2 # x, y (in some order) + assert isinstance(liveboxes[0], history.BoxInt) + assert isinstance(liveboxes[1], history.BoxInt) def test_interp_many_paths(self): myjitdriver = JitDriver(greens = ['i'], reds = ['x', 'node']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Mar 19 20:12:50 2009 @@ -453,10 +453,11 @@ ]) guard_op = spec.loop.operations[-2] assert guard_op.getopname() == 'guard_true' - assert guard_op.liveboxes == [G.sum2, ConstInt(124)] + assert guard_op.liveboxes == [G.sum2] vt = cpu.cast_adr_to_int(node_vtable_adr) assert ([op.getopname() for op in guard_op.rebuild_ops] == ['new_with_vtable', 'setfield_gc']) + assert guard_op.rebuild_ops[1].args[1] == ConstInt(124) # ____________________________________________________________ From arigo at codespeak.net Thu Mar 19 20:17:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 19 Mar 2009 20:17:49 +0100 (CET) Subject: [pypy-svn] r63097 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090319191749.6AA64168052@codespeak.net> Author: arigo Date: Thu Mar 19 20:17:46 2009 New Revision: 63097 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: Fixes to the x86 backend to handle the Const-less liveboxes. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 19 20:17:46 2009 @@ -117,14 +117,11 @@ if self._log_fd == -1: return os.write(self._log_fd, 'xxxxxxxxxx\n') - j = 0 memo = {} reprs = [] - for box in gf.guard_op.liveboxes: - if isinstance(box, Box): - valuebox = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j) - reprs.append(repr_of_arg(memo, valuebox)) - j += 1 + for j in range(len(gf.guard_op.liveboxes)): + valuebox = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j) + reprs.append(repr_of_arg(memo, valuebox)) jmp = gf.guard_op._jmp_from os.write(self._log_fd, "%d %d %s\n" % (guard_index, jmp, ",".join(reprs))) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 19 20:17:46 2009 @@ -240,8 +240,8 @@ longevity[arg] = (start_live[arg], i) if op.is_guard(): for arg in op.liveboxes: - if isinstance(arg, Box): - longevity[arg] = (start_live[arg], i) + assert isinstance(arg, Box) + longevity[arg] = (start_live[arg], i) self.longevity = longevity def try_allocate_reg(self, v, selected_reg=None): @@ -338,11 +338,11 @@ stacklocs = [] locs = [] for arg in guard_op.liveboxes: - if isinstance(arg, Box): - if arg not in self.stack_bindings: - self.dirty_stack[arg] = True - stacklocs.append(self.stack_loc(arg).position) - locs.append(self.loc(arg)) + assert isinstance(arg, Box) + if arg not in self.stack_bindings: + self.dirty_stack[arg] = True + stacklocs.append(self.stack_loc(arg).position) + locs.append(self.loc(arg)) if not we_are_translated(): assert len(dict.fromkeys(stacklocs)) == len(stacklocs) guard_op.stacklocs = stacklocs Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Thu Mar 19 20:17:46 2009 @@ -395,7 +395,7 @@ def getvaluebox(self, frameadr, guard_op, argindex): # XXX that's plain stupid, do we care about the return value??? - box = [b for b in guard_op.liveboxes if isinstance(b, Box)][argindex] + box = guard_op.liveboxes[argindex] frame = getframe(frameadr) pos = guard_op.stacklocs[argindex] intvalue = frame[pos] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 19 20:17:46 2009 @@ -246,43 +246,15 @@ None) ] ops[-5].descr = cpu.fielddescrof(TP, 'y') - ops[1].liveboxes = [ConstInt(21), const_code, p0, i11, i5, i2, i3, i4, p1, - p6, p7, i8, i9, i10, p12, p13, const_name] - ops[3].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, i3, - i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, - const_name, const_name, ConstInt(21), - const_name, ConstInt(24), ConstInt(16), ConstInt(16), - ConstInt(24), ConstInt(346), ConstInt(0)] - ops[5].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, i3, - i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, - const_name, const_name, ConstInt(21), const_name, - ConstInt(24), ConstInt(16), ConstInt(16), - ConstInt(24), ConstInt(346), ConstInt(1)] - ops[7].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, - i3, i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, - const_name, const_name, ConstInt(21), const_name, - ConstInt(24), ConstInt(16), ConstInt(16), - ConstInt(24), ConstInt(346), ConstInt(1)] - ops[9].liveboxes = [ConstInt(21), const_code, p0, ConstInt(21), i5, i2, - i3, i4, p1, p6, p7, i8, i9, ConstInt(1), p12, p13, - const_name, const_name, ConstInt(21), const_name, - ConstInt(24), ConstInt(16), ConstInt(16), - ConstInt(24), ConstInt(346), ConstInt(1)] - ops[14].liveboxes = [ConstInt(33), const_code, p0, ConstInt(33), i20, - i2, i3, i4, p1, none_ptr, none_ptr, i8, i19, - ConstInt(1), p12, p13, const_name, const_name, - ConstInt(33), const_name, ConstInt(34), - ConstInt(0), ConstInt(347), i21] - ops[17].liveboxes = [ConstInt(37), const_code, p0, ConstInt(37), i20, i2, - i3, i4, p1, none_ptr, none_ptr, i21, i19, - ConstInt(1), p12, p13, const_name, const_name, - ConstInt(37), const_name, ConstInt(40), ConstInt(21), - ConstInt(21), p22, ConstInt(1)] - ops[-2].liveboxes = [ConstInt(37), const_code, p0, ConstInt(37), i20, i2, - i3, i4, p1, none_ptr, none_ptr, i21, i19, - ConstInt(1), p12, p13, const_name, const_name, - ConstInt(37), const_name, ConstInt(40), ConstInt(21), - ConstInt(21), p22] + ops[1].liveboxes = [p0, i11, i5, i2, i3, i4, p1, p6, p7, i8, + i9, i10, p12, p13] + ops[3].liveboxes = [p0, i5, i2, i3, i4, p1, p6, p7, i8, i9, p12, p13] + ops[5].liveboxes = [p0, i5, i2, i3, i4, p1, p6, p7, i8, i9, p12, p13] + ops[7].liveboxes = [p0, i5, i2, i3, i4, p1, p6, p7, i8, i9, p12, p13] + ops[9].liveboxes = [p0, i5, i2, i3, i4, p1, p6, p7, i8, i9, p12, p13] + ops[14].liveboxes = [p0, i20, i2, i3, i4, p1, i8, i19, p12, p13, i21] + ops[17].liveboxes = [p0, i20, i2, i3, i4, p1, i21, i19, p12, p13, p22] + ops[-2].liveboxes = [p0, i20, i2, i3, i4, p1, i21, i19, p12, p13, p22] ops[-1].jump_target = ops[0] cpu.compile_operations(ops) From antocuni at codespeak.net Thu Mar 19 21:07:55 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 19 Mar 2009 21:07:55 +0100 (CET) Subject: [pypy-svn] r63098 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090319200755.8B088168406@codespeak.net> Author: antocuni Date: Thu Mar 19 21:07:51 2009 New Revision: 63098 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: add a note Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Thu Mar 19 21:07:51 2009 @@ -19,6 +19,8 @@ Samuele and Anders Hammarquist would like to share a two persons room. +Antonio would like to share a room with someone, volunteers are welcome :-) + People on the following list were present at previous sprints: ==================== ============== ===================== From cami at codespeak.net Fri Mar 20 09:05:11 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 20 Mar 2009 09:05:11 +0100 (CET) Subject: [pypy-svn] r63108 - pypy/trunk/pypy/translator/goal Message-ID: <20090320080511.9BB9616843E@codespeak.net> Author: cami Date: Fri Mar 20 09:05:10 2009 New Revision: 63108 Modified: pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py Log: added float input support Modified: pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py (original) +++ pypy/trunk/pypy/translator/goal/targetgbfullprofiling.py Fri Mar 20 09:05:10 2009 @@ -8,7 +8,7 @@ def entry_point(argv=None): if argv is not None and len(argv) > 1: filename = argv[1] - execution_seconds = int(argv[2]) + execution_seconds = float(argv[2]) else: pos = str(9) filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" From cami at codespeak.net Fri Mar 20 09:05:32 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 20 Mar 2009 09:05:32 +0100 (CET) Subject: [pypy-svn] r63109 - pypy/trunk/pypy/lang/gameboy/profiling Message-ID: <20090320080532.5503E16844C@codespeak.net> Author: cami Date: Fri Mar 20 09:05:31 2009 New Revision: 63109 Modified: pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Log: added float input support Modified: pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Fri Mar 20 09:05:31 2009 @@ -30,7 +30,7 @@ def mainLoop(self, execution_seconds): self.reset() self.is_running = True - for i in range(execution_seconds * FPS): + for i in range(int(execution_seconds * FPS)): self.emulate_cycle() def emulate_cycle(self): From fijal at codespeak.net Fri Mar 20 09:47:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 09:47:00 +0100 (CET) Subject: [pypy-svn] r63111 - pypy/branch/virtualizable-specnodes-2 Message-ID: <20090320084700.21369168440@codespeak.net> Author: fijal Date: Fri Mar 20 09:46:57 2009 New Revision: 63111 Added: pypy/branch/virtualizable-specnodes-2/ - copied from r63110, pypy/branch/pyjitpl5/ Log: branch again From pedronis at codespeak.net Fri Mar 20 09:49:19 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 09:49:19 +0100 (CET) Subject: [pypy-svn] r63112 - pypy/trunk/pypy/interpreter/test Message-ID: <20090320084919.CBB98168440@codespeak.net> Author: pedronis Date: Fri Mar 20 09:49:19 2009 New Revision: 63112 Modified: pypy/trunk/pypy/interpreter/test/test_code.py Log: (iko, pedronis) make this test test what it intended instead of other subtle differences between pypy and cpython Modified: pypy/trunk/pypy/interpreter/test/test_code.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_code.py (original) +++ pypy/trunk/pypy/interpreter/test/test_code.py Fri Mar 20 09:49:19 2009 @@ -1,4 +1,3 @@ - from pypy.conftest import gettestobjspace from pypy.interpreter import gateway import py @@ -174,7 +173,7 @@ "docstring" 'stuff' 56 - """ in locals() +""" # check for new flag, CO_NOFREE assert f.func_code.co_flags & 0x40 @@ -184,7 +183,7 @@ def g(y): return x+y return g - """ in locals() +""" # CO_NESTED assert f(4).func_code.co_flags & 0x10 From fijal at codespeak.net Fri Mar 20 09:49:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 09:49:35 +0100 (CET) Subject: [pypy-svn] r63113 - in pypy/branch/virtualizable-specnodes/pypy/jit/metainterp: . test Message-ID: <20090320084935.2F0F0168440@codespeak.net> Author: fijal Date: Fri Mar 20 09:49:34 2009 New Revision: 63113 Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_tl.py Log: an in-progress checkin of changes so-far Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py Fri Mar 20 09:49:34 2009 @@ -151,15 +151,6 @@ metainterp.cpu.compile_operations(loop.operations, guard_op) metainterp.stats.loops.append(loop) -def update_loop(metainterp, loop, guard_op, newboxlist): - mp = loop.operations[0] - mp.args += newboxlist - jump = loop.operations[-1] - jump.args += newboxlist - guard_op.liveboxes += newboxlist - guard_op.storage = None - metainterp.cpu.update_loop(loop, mp, guard_op, newboxlist) - # ____________________________________________________________ def matching_merge_point(metainterp, targetmp, endliveboxes): @@ -176,14 +167,14 @@ op = ResOperation(rop.JUMP, endliveboxes, None) operations.append(op) # - old_loop, newboxlist = optimize.optimize_bridge(metainterp.options, - old_loops, bridge, - metainterp.cpu) + old_loop, newboxlist, storage = optimize.optimize_bridge(metainterp.options, + old_loops, bridge, + metainterp.cpu) if old_loop is None: return None bridge.jump_to = old_loop if newboxlist: # recompile loop - update_loop(metainterp, old_loop, guard_op, newboxlist) + optimize.update_loop(metainterp, old_loop, newboxlist, storage) finish_loop_or_bridge(metainterp, bridge, old_loop.operations[0], guard_op) return bridge Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py Fri Mar 20 09:49:34 2009 @@ -27,6 +27,9 @@ assert isinstance(other, FixedClass) return True + def _getrepr_(self): + return "FixedClass" + class CancelInefficientLoop(Exception): pass @@ -48,6 +51,8 @@ # the same as above, but for lists and for running setitem self.list_allocations = [] self.setitems = [] + # used for merging + self.extras = [] def deal_with_box(self, box, nodes, liveboxes, memo): if isinstance(box, Const) or box not in nodes: @@ -281,13 +286,13 @@ for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): num = len(old_loop.extensions) - newlist, newspecnodes = perfect_specializer.adapt_for_match( + newlist, newspecnodes, s = perfect_specializer.adapt_for_match( old_loop.operations, num) if newlist: old_loop.extensions.append(newspecnodes) perfect_specializer.loop.operations[0].args.extend(newlist) perfect_specializer.optimize_loop() - return old_loop, newlist + return old_loop, newlist, s return None # no loop matches class PerfectSpecializer(object): @@ -831,12 +836,14 @@ jump_op = self.loop.operations[-1] self.specnodes = old_mp.specnodes newboxlist = BoxRetriever() + storage = AllocationStorage() extensions = [] for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] new_instnode = self.nodes[jump_op.args[i]] - old_specnode.adapt_to(new_instnode, newboxlist, extensions, num) - return newboxlist.flatten(), extensions + old_specnode.adapt_to(new_instnode, newboxlist, extensions, num, + storage) + return newboxlist.flatten(), extensions, storage class Chooser(object): def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists): @@ -895,6 +902,19 @@ return newboxes +def update_loop(metainterp, loop, newboxlist, add_storage): + mp = loop.operations[0] + mp.args += newboxlist + jump = loop.operations[-1] + jump.args += newboxlist + for op in loop.operations: + if op.is_guard(): + import pdb + pdb.set_trace() + metainterp.cpu.update_loop(loop, mp, newboxlist) + +# ---------------------------------------------------------------------- + def partition(array, left, right): last_item = array[right] pivot = last_item.sort_key() Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py Fri Mar 20 09:49:34 2009 @@ -38,7 +38,7 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) - def adapt_to(self, instnode, newboxlist, newspecnodes, num): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, storage): instnode.escaped = True def mutate_nodes(self, instnode): @@ -50,6 +50,9 @@ def matches(self, other): raise NotImplementedError + def create_extra_storage(self, storage): + pass + class RedirectingSpecNode(SpecNode): def __init__(self, specnode, group): self.redirect_to = specnode @@ -181,10 +184,10 @@ [valuebox], ofs) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - def adapt_to(self, instnode, newboxlist, newspecnodes, num): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, storage): for ofs, subspecnode in self.fields: subspecnode.adapt_to(instnode.curfields[ofs], newboxlist, - newspecnodes, num) + newspecnodes, num, storage) class VirtualizedOrDelayedSpecNode(SpecNodeWithFields): @@ -196,10 +199,10 @@ resultlist.append(valuebox) SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist) - def adapt_to(self, instnode, newboxlist, newspecnodes, num): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, storage): instnode.escaped = True SpecNodeWithFields.adapt_to(self, instnode, newboxlist, newspecnodes, - num) + num, storage) class DelayedSpecNode(VirtualizedOrDelayedSpecNode): @@ -276,7 +279,7 @@ return False return True - def adapt_to(self, instnode, newboxlist, newspecnodes, num): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, storage): instnode.virtualized = True fields = [] for ofs, subspecnode in self.fields: @@ -286,13 +289,15 @@ node = instnode.curfields[ofs] subspecnode = orignode.intersect(node, {}) subspecnode.mutate_nodes(orignode) + res = subspecnode.create_extra_storage(storage) + self.add_to_storage(ofs, res, storage) subspecnode = RedirectingSpecNode(subspecnode, num) subspecnode.expand_boxlist(orignode, newboxlist, None) newspecnodes.append(subspecnode) # otherwise we simply ignore unused field else: subspecnode.adapt_to(instnode.curfields[ofs], newboxlist, - newspecnodes, num) + newspecnodes, num, storage) fields.append((ofs, subspecnode)) self.fields = fields @@ -303,6 +308,9 @@ return False return VirtualizedSpecNode.equals(self, other) + def create_extra_storage(self, storage): + raise NotImplementedError + class VirtualizableListSpecNode(VirtualizedSpecNode): def equals(self, other): @@ -328,10 +336,10 @@ class VirtualSpecNode(SpecNodeWithFields): - def adapt_to(self, instnode, newboxlist, newspecnodes, num): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, storage): instnode.virtual = True return SpecNodeWithFields.adapt_to(self, instnode, newboxlist, - newspecnodes, num) + newspecnodes, num, storage) def mutate_nodes(self, instnode): SpecNodeWithFields.mutate_nodes(self, instnode) @@ -344,30 +352,37 @@ return False return SpecNodeWithFields.equals(self, other) + def create_extra_storage(self, storage): + xxx + class VirtualFixedListSpecNode(VirtualSpecNode): - def __init__(self, known_class, fields, known_length): - VirtualSpecNode.__init__(self, known_class, fields) - self.known_length = known_length - - def mutate_nodes(self, instnode): - VirtualSpecNode.mutate_nodes(self, instnode) - instnode.cursize = self.known_length - - def equals(self, other): - if not isinstance(other, VirtualFixedListSpecNode): - return False - return SpecNodeWithFields.equals(self, other) + def __init__(self, known_class, fields, known_length): + VirtualSpecNode.__init__(self, known_class, fields) + self.known_length = known_length + + def mutate_nodes(self, instnode): + VirtualSpecNode.mutate_nodes(self, instnode) + instnode.cursize = self.known_length + + def equals(self, other): + if not isinstance(other, VirtualFixedListSpecNode): + return False + return SpecNodeWithFields.equals(self, other) - def extract_runtime_data(self, cpu, valuebox, resultlist): - from pypy.jit.metainterp.resoperation import rop - from pypy.jit.metainterp.optimize import FixedList - from pypy.jit.metainterp.history import check_descr - cls = self.known_class - assert isinstance(cls, FixedList) - arraydescr = cls.arraydescr - check_descr(arraydescr) - for ofs, subspecnode in self.fields: - fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ofs], arraydescr) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.resoperation import rop + from pypy.jit.metainterp.optimize import FixedList + from pypy.jit.metainterp.history import check_descr + cls = self.known_class + assert isinstance(cls, FixedList) + arraydescr = cls.arraydescr + check_descr(arraydescr) + for ofs, subspecnode in self.fields: + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ofs], arraydescr) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + + def create_extra_storage(self, storage): + xxx + Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_tl.py Fri Mar 20 09:49:34 2009 @@ -107,6 +107,96 @@ 'int_is_true':1, 'guard_false':1, 'jump':1, 'guard_value':1}) + def test_example(self): + jitdriver = JitDriver(greens = ['code', 'i'], reds = ['v1', 'v2', 'v3']) + + class IntObject(object): + def __init__(self, value): + self.value = value + + def add(self, other): + return IntObject(self.value + other.value) + + def gt(self, other): + return self.value > other.value + + def store_into_variable(num, v1, v2, v3, value_to_store): + if num == 0: + return value_to_store, v2, v3 + elif num == 1: + return v1, value_to_store, v3 + elif num == 2: + return v1, v2, value_to_store + else: + raise Exception("Wrong num") + + def load_variable(num, v1, v2, v3): + if num == 0: + return v1 + elif num == 1: + return v2 + elif num == 2: + return v3 + else: + raise Exception("Wrong num") + + def interpret(code, i0, i1, i2): + v1 = IntObject(i0) + v2 = IntObject(i1) + v3 = IntObject(i2) + i = 0 + while i < len(code): + jitdriver.jit_merge_point(code=code, i=i, v1=v1, v2=v2, v3=v3) + if code[i] == ADD: + a = load_variable(code[i + 1], v1, v2, v3) + b = load_variable(code[i + 2], v1, v2, v3) + res_num = code[i + 3] + res = a.add(b) + v1, v2, v3 = store_into_variable(res_num, v1, v2, v3, + res) + i += 4 + elif code[i] == JUMP_IF_GT: + a = load_variable(code[i + 1], v1, v2, v3) + b = load_variable(code[i + 2], v1, v2, v3) + where = code[i + 3] + if a.gt(b): + i = where + jitdriver.can_enter_jit(code=code, i=i, v1=v1, v2=v2, + v3=v3) + else: + i += 4 + elif code[i] == JUMP: + i = code[i + 1] + jitdriver.can_enter_jit(code=code, i=i, v1=v1, v2=v2, v3=v3) + else: + raise Exception("bytecode corruption") + return v1.value + + ADD = 0 + JUMP = 1 + JUMP_IF_GT = 2 + + code = [ + ADD, 0, 1, 0, + ADD, 0, 1, 0, + ADD, 0, 1, 0, + JUMP_IF_GT, 0, 2, 18, + JUMP, 0 + ] + + # v0 += v1 + # v0 += v1 + # v0 += v1 + # if v1 > v2: jump 18 (after the end of the loop) + # jump 0 + + def runner(num, i0, i1, i2): + return interpret([code, []][num], i0, i1, i2) + + assert interpret(code, 0, 1, 20) == 21 + res = self.meta_interp(runner, [0, 0, 1, 20]) + assert res == 21 + class TestOOtype(ToyLanguageTests, OOJitMixin): pass From fijal at codespeak.net Fri Mar 20 10:05:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 10:05:43 +0100 (CET) Subject: [pypy-svn] r63114 - pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test Message-ID: <20090320090543.7B12C168466@codespeak.net> Author: fijal Date: Fri Mar 20 10:05:42 2009 New Revision: 63114 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_tl.py Log: some example for blog, skip so far Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_tl.py Fri Mar 20 10:05:42 2009 @@ -107,6 +107,97 @@ 'int_is_true':1, 'guard_false':1, 'jump':1, 'guard_value':1}) + def test_example(self): + py.test.skip("bugs") + jitdriver = JitDriver(greens = ['code', 'i'], reds = ['v1', 'v2', 'v3']) + + class IntObject(object): + def __init__(self, value): + self.value = value + + def add(self, other): + return IntObject(self.value + other.value) + + def gt(self, other): + return self.value > other.value + + def store_into_variable(num, v1, v2, v3, value_to_store): + if num == 0: + return value_to_store, v2, v3 + elif num == 1: + return v1, value_to_store, v3 + elif num == 2: + return v1, v2, value_to_store + else: + raise Exception("Wrong num") + + def load_variable(num, v1, v2, v3): + if num == 0: + return v1 + elif num == 1: + return v2 + elif num == 2: + return v3 + else: + raise Exception("Wrong num") + + def interpret(code, i0, i1, i2): + v1 = IntObject(i0) + v2 = IntObject(i1) + v3 = IntObject(i2) + i = 0 + while i < len(code): + jitdriver.jit_merge_point(code=code, i=i, v1=v1, v2=v2, v3=v3) + if code[i] == ADD: + a = load_variable(code[i + 1], v1, v2, v3) + b = load_variable(code[i + 2], v1, v2, v3) + res_num = code[i + 3] + res = a.add(b) + v1, v2, v3 = store_into_variable(res_num, v1, v2, v3, + res) + i += 4 + elif code[i] == JUMP_IF_GT: + a = load_variable(code[i + 1], v1, v2, v3) + b = load_variable(code[i + 2], v1, v2, v3) + where = code[i + 3] + if a.gt(b): + i = where + jitdriver.can_enter_jit(code=code, i=i, v1=v1, v2=v2, + v3=v3) + else: + i += 4 + elif code[i] == JUMP: + i = code[i + 1] + jitdriver.can_enter_jit(code=code, i=i, v1=v1, v2=v2, v3=v3) + else: + raise Exception("bytecode corruption") + return v1.value + + ADD = 0 + JUMP = 1 + JUMP_IF_GT = 2 + + code = [ + ADD, 0, 1, 0, + ADD, 0, 1, 0, + ADD, 0, 1, 0, + JUMP_IF_GT, 0, 2, 18, + JUMP, 0 + ] + + # v0 += v1 + # v0 += v1 + # v0 += v1 + # if v1 > v2: jump 18 (after the end of the loop) + # jump 0 + + def runner(num, i0, i1, i2): + return interpret([code, []][num], i0, i1, i2) + + assert interpret(code, 0, 1, 20) == 21 + res = self.meta_interp(runner, [0, 0, 1, 20]) + assert res == 21 + class TestOOtype(ToyLanguageTests, OOJitMixin): pass From fijal at codespeak.net Fri Mar 20 10:11:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 10:11:19 +0100 (CET) Subject: [pypy-svn] r63115 - pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test Message-ID: <20090320091119.7E0F41683DD@codespeak.net> Author: fijal Date: Fri Mar 20 10:11:18 2009 New Revision: 63115 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py Log: fix test Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py Fri Mar 20 10:11:18 2009 @@ -59,8 +59,10 @@ heaptracker.set_testing_vtable_for_gcstruct(XYSUB, xysub_vtable) # ____________________________________________________________ +ofs_node = runner.CPU.fielddescrof(XY, 'node') xy_desc = VirtualizableDesc(cpu, XY, XY) +xy_desc.fields = [ofs_node] # ____________________________________________________________ From pedronis at codespeak.net Fri Mar 20 10:24:13 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 10:24:13 +0100 (CET) Subject: [pypy-svn] r63116 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090320092413.26A34168494@codespeak.net> Author: pedronis Date: Fri Mar 20 10:24:12 2009 New Revision: 63116 Modified: pypy/trunk/pypy/objspace/std/test/test_obj.py Log: (iko, pedronis) some of the checks make only sense on top of cpython (to be precise on top on non moving gc, but I'm not sure we care that much) Modified: pypy/trunk/pypy/objspace/std/test/test_obj.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_obj.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_obj.py Fri Mar 20 10:24:12 2009 @@ -1,7 +1,18 @@ # -*- coding: iso-8859-1 -*- +from pypy.conftest import option -class AppTestObject: +class AppTestObject: + + def setup_class(cls): + import sys + cpython_behavior = (not option.runappdirect + or not hasattr(sys, 'pypy_translation_info')) + + cls.w_cpython_behavior = cls.space.wrap(cpython_behavior) + def test_hash_builtin(self): + if not self.cpython_behavior: + skip("on pypy-c id == hash is not guaranteed") import sys o = object() assert (hash(o) & sys.maxint) == (id(o) & sys.maxint) @@ -23,7 +34,8 @@ class X(object): pass x = X() - assert (hash(x) & sys.maxint) == (id(x) & sys.maxint) + if self.cpython_behavior: + assert (hash(x) & sys.maxint) == (id(x) & sys.maxint) assert hash(x) == object.__hash__(x) def test_reduce_recursion_bug(self): From afa at codespeak.net Fri Mar 20 10:28:40 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Mar 2009 10:28:40 +0100 (CET) Subject: [pypy-svn] r63118 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090320092840.92C9116847F@codespeak.net> Author: afa Date: Fri Mar 20 10:28:40 2009 New Revision: 63118 Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: Give more precise error messages in ParseCreate This fixes the output of test_pyexpat. Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Fri Mar 20 10:28:40 2009 @@ -574,12 +574,18 @@ Return a new XML parser object.""" if space.is_w(w_encoding, space.w_None): encoding = None - else: + elif space.is_true(space.isinstance(w_encoding, space.w_str)): encoding = space.str_w(w_encoding) + else: + type_name = space.type(w_encoding).getname(space, '?') + raise OperationError( + space.w_TypeError, + space.wrap('ParserCreate() argument 1 must be string or None,' + ' not %s' % (type_name,))) if space.is_w(w_namespace_separator, space.w_None): namespace_separator = 0 - else: + elif space.is_true(space.isinstance(w_namespace_separator, space.w_str)): separator = space.str_w(w_namespace_separator) if len(separator) == 0: namespace_separator = 0 @@ -590,6 +596,13 @@ space.w_ValueError, space.wrap('namespace_separator must be at most one character,' ' omitted, or None')) + else: + type_name = space.type(w_namespace_separator).getname(space, '?') + raise OperationError( + space.w_TypeError, + space.wrap('ParserCreate() argument 2 must be string or None,' + ' not %s' % (type_name,))) + if w_intern is None: w_intern = space.newdict() From pedronis at codespeak.net Fri Mar 20 10:44:58 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 10:44:58 +0100 (CET) Subject: [pypy-svn] r63119 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090320094458.966381683DE@codespeak.net> Author: pedronis Date: Fri Mar 20 10:44:55 2009 New Revision: 63119 Modified: pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Log: (iko, pedronis) more testing of unicode string comparisons they are broken under the builtinshortcut opt Modified: pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py Fri Mar 20 10:44:55 2009 @@ -61,6 +61,25 @@ assert x == 'foo' assert 5 + 6.5 == 11.5 + def test_unicode_string_compares(self): + skip("FAILING") + assert u'a' == 'a' + assert 'a' == u'a' + assert not u'a' == 'b' + assert not 'a' == u'b' + assert u'a' != 'b' + assert 'a' != u'b' + assert not (u'a' == 5) + assert u'a' != 5 + assert u'a' < 5 or u'a' > 5 + + s = chr(128) + u = unichr(128) + assert not s == u # UnicodeWarning + assert s != u + assert not u == s + assert u != s + class AppTestSet(test_set.AppTestAppSetTest): # this tests tons of funny comparison combinations that can easily go wrong Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Fri Mar 20 10:44:55 2009 @@ -35,9 +35,14 @@ assert not (u'a' == 5) assert u'a' != 5 assert u'a' < 5 or u'a' > 5 - assert not chr(128) == unichr(128) # UnicodeWarning - assert chr(128) != unichr(128) + s = chr(128) + u = unichr(128) + assert not s == u # UnicodeWarning + assert s != u + assert not u == s + assert u != s + class AppTestUnicodeString: def setup_class(cls): From afa at codespeak.net Fri Mar 20 11:02:07 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Mar 2009 11:02:07 +0100 (CET) Subject: [pypy-svn] r63120 - in pypy/trunk/pypy/module/rctime: . test Message-ID: <20090320100207.925A916844A@codespeak.net> Author: afa Date: Fri Mar 20 11:02:06 2009 New Revision: 63120 Modified: pypy/trunk/pypy/module/rctime/__init__.py pypy/trunk/pypy/module/rctime/test/test_rctime.py Log: time.tzname should be a tuple. (time.tzset sets it to a tuple, btw) This fixes test_rctime when called with the -A option Modified: pypy/trunk/pypy/module/rctime/__init__.py ============================================================================== --- pypy/trunk/pypy/module/rctime/__init__.py (original) +++ pypy/trunk/pypy/module/rctime/__init__.py Fri Mar 20 11:02:06 2009 @@ -38,7 +38,7 @@ Module.interpleveldefs['timezone'] = 'space.wrap(%r)' % timezone Module.interpleveldefs['daylight'] = 'space.wrap(%r)' % daylight Module.interpleveldefs['tzname'] = \ - 'space.newlist([space.wrap(%r), space.wrap(%r)])' % tuple(tzname) + 'space.newtuple([space.wrap(%r), space.wrap(%r)])' % tuple(tzname) Module.interpleveldefs['altzone'] = 'space.wrap(%r)' % altzone super(Module, cls).buildloaders() buildloaders = classmethod(buildloaders) Modified: pypy/trunk/pypy/module/rctime/test/test_rctime.py ============================================================================== --- pypy/trunk/pypy/module/rctime/test/test_rctime.py (original) +++ pypy/trunk/pypy/module/rctime/test/test_rctime.py Fri Mar 20 11:02:06 2009 @@ -12,7 +12,7 @@ assert isinstance(rctime.altzone, int) assert isinstance(rctime.daylight, int) assert isinstance(rctime.timezone, int) - assert isinstance(rctime.tzname, list) + assert isinstance(rctime.tzname, tuple) assert isinstance(rctime.__doc__, str) def test_sleep(self): From arigo at codespeak.net Fri Mar 20 11:19:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 20 Mar 2009 11:19:37 +0100 (CET) Subject: [pypy-svn] r63121 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090320101937.BAA01168487@codespeak.net> Author: arigo Date: Fri Mar 20 11:19:36 2009 New Revision: 63121 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: Missing case to support rop.NEW. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Mar 20 11:19:36 2009 @@ -548,6 +548,9 @@ else: return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast) + def op_new(self, size): + return do_new(size.ofs) + def op_new_with_vtable(self, size, vtable): result = do_new(size.ofs) value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result) From arigo at codespeak.net Fri Mar 20 11:20:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 20 Mar 2009 11:20:07 +0100 (CET) Subject: [pypy-svn] r63122 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/metainterp/test rpython Message-ID: <20090320102007.2F715168487@codespeak.net> Author: arigo Date: Fri Mar 20 11:20:06 2009 New Revision: 63122 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/rpython/rlist.py Log: Minimal support for "print" in RPython. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Fri Mar 20 11:20:06 2009 @@ -7,6 +7,10 @@ # explicitly pure functions are always opaque if getattr(func, '_pure_function_', False): return False + # pypy.rpython.module.* are opaque helpers + mod = func.__module__ or '?' + if mod.startswith('pypy.rpython.module.'): + return False return True def look_inside_graph(self, graph): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Fri Mar 20 11:20:06 2009 @@ -119,6 +119,7 @@ _ll_2_list_append = rlist.ll_append _ll_2_list_extend = rlist.ll_extend _ll_3_list_insert = rlist.ll_insert_nonneg +_ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly _ll_2_list_getitem_foldable = _ll_2_list_getitem _ll_1_list_len_foldable = _ll_1_list_len Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Fri Mar 20 11:20:06 2009 @@ -319,6 +319,18 @@ res = self.meta_interp(f, [20, 1, 2]) assert res == 0 + def test_print(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + def f(n): + while n > 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + print n + n -= 1 + return n + res = self.meta_interp(f, [7]) + assert res == 0 + class TestOOtype(BasicTests, OOJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/rpython/rlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rlist.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rlist.py Fri Mar 20 11:20:06 2009 @@ -897,6 +897,7 @@ l.ll_setitem_fast(j, null) j -= 1 l._ll_resize_le(newlength) +ll_listdelslice_startonly.oopspec = 'list.delslice_startonly(l, start)' def ll_listdelslice_startstop(l, start, stop): length = l.ll_length() From fijal at codespeak.net Fri Mar 20 11:40:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 11:40:17 +0100 (CET) Subject: [pypy-svn] r63123 - in pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp: . test Message-ID: <20090320104017.28EE1168466@codespeak.net> Author: fijal Date: Fri Mar 20 11:40:16 2009 New Revision: 63123 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/virtualizable.py Log: hopefully fix the virtualizable spec node issue. there is still one outstanding change to support already compiled bridges Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py Fri Mar 20 11:40:16 2009 @@ -112,6 +112,7 @@ else: name = 'Loop #%d' % len(metainterp.stats.loops) graph = Graph(name, '#f084c2') + graph.extensions = [None] return graph def create_empty_bridge(metainterp): @@ -120,6 +121,7 @@ else: name = 'Bridge #%d' % len(metainterp.stats.loops) graph = Graph(name, '#84f0c2') + graph.extensions = [None] return graph # ____________________________________________________________ @@ -165,10 +167,14 @@ op = ResOperation(rop.JUMP, endliveboxes, None) operations.append(op) # - old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge, - metainterp.cpu) + res = optimize.optimize_bridge(metainterp.options, old_loops, bridge, + metainterp.cpu) + old_loop, newboxlist, storage = res if old_loop is None: return None bridge.jump_to = old_loop + if newboxlist: + # recompile loop + optimize.update_loop(metainterp, old_loop, bridge, newboxlist, storage) finish_loop_or_bridge(metainterp, bridge, old_loop.operations[0], guard_op) return bridge Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py Fri Mar 20 11:40:16 2009 @@ -3,15 +3,10 @@ ResOperation, AbstractDescr, Options, AbstractValue, ConstPtr) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, - VirtualInstanceSpecNode, - VirtualizableSpecNode, - NotSpecNode, - DelayedSpecNode, - SpecNodeWithBox, - DelayedFixedListSpecNode, - VirtualFixedListSpecNode, - VirtualizableListSpecNode, - ) + VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, + DelayedSpecNode, SpecNodeWithBox, DelayedFixedListSpecNode, + VirtualFixedListSpecNode, MatchEverythingSpecNode, + VirtualizableListSpecNode, av_eq, av_hash, BoxRetriever) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype, llmemory @@ -32,15 +27,12 @@ assert isinstance(other, FixedClass) return True + def _getrepr_(self): + return "FixedClass" + class CancelInefficientLoop(Exception): pass -def av_eq(self, other): - return self.sort_key() == other.sort_key() - -def av_hash(self): - return self.sort_key() - def av_list_in(lst, key): # lst is a list of about 2 elements in the typical case, so no # point in making a dict lookup @@ -68,6 +60,7 @@ self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables + self.allfields = None def is_nonzero(self): return self.cls is not None or self.nonzero @@ -75,7 +68,7 @@ def is_zero(self): return self.const and not self.source.getptr_base() - def escape_if_startbox(self, memo): + def escape_if_startbox(self, memo, cpu): if self in memo: return memo[self] = None @@ -83,23 +76,32 @@ self.escaped = True if not self.virtualized: for node in self.curfields.values(): - node.escape_if_startbox(memo) + node.escape_if_startbox(memo, cpu) else: for key, node in self.curfields.items(): if self.vdesc is not None and av_list_in(self.vdesc, key): - node.virtualized = True - if node.cls is None: - node.cls = InstanceNode(FixedClass(), const=True) - node.escape_if_startbox(memo) + node.initialize_virtualizable(cpu) + node.escape_if_startbox(memo, cpu) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: if self.vdesc is not None and av_list_in(self.vdesc, key): - node.virtualized = True - if node.cls is None: - node.cls = InstanceNode(FixedClass(), const=True) - node.escape_if_startbox(memo) + node.initialize_virtualizable(cpu) + node.escape_if_startbox(memo, cpu) + + def initialize_virtualizable(self, cpu): + self.virtualized = True + if self.cls is None or not isinstance(self.cls.source, FixedList): + # XXX this is of course wrong, but let's at least not + # explode + self.allfields = self.origfields.keys() + if self.cls is None: + self.cls = InstanceNode(FixedClass(), const=True) + else: + ad = self.cls.source.arraydescr + lgtbox = cpu.do_arraylen_gc([self.source], ad) + self.allfields = [ConstInt(i) for i in range(lgtbox.getint())] def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) @@ -157,9 +159,7 @@ return DelayedSpecNode(known_class, fields) else: assert self is other - d = self.origfields.copy() - d.update(other.curfields) - offsets = d.keys() + offsets = self.allfields sort_descrs(offsets) fields = [] for ofs in offsets: @@ -171,15 +171,73 @@ self.origfields[ofs].cls = node.cls nodes[box] = self.origfields[ofs] specnode = self.origfields[ofs].intersect(node, nodes) - else: - # ofs in self.origfields: + elif ofs in self.origfields: node = self.origfields[ofs] specnode = node.intersect(node, nodes) + else: + specnode = MatchEverythingSpecNode() fields.append((ofs, specnode)) if isinstance(known_class, FixedList): return VirtualizableListSpecNode(known_class, fields) return VirtualizableSpecNode(known_class, fields) + def prepare_rebuild_ops(instnode, liveboxes, rebuild_ops, memo, cpu): + box = instnode.source + if not isinstance(box, Box): + return box + if box in memo: + return memo[box] + if instnode.virtual: + newbox = BoxPtr() + ld = instnode.cls.source + if isinstance(ld, FixedList): + ad = ld.arraydescr + sizebox = ConstInt(instnode.cursize) + op = ResOperation(rop.NEW_ARRAY, [sizebox], newbox, + descr=ad) + else: + vtable = ld.getint() + if cpu.translate_support_code: + vtable_addr = cpu.cast_int_to_adr(vtable) + size = cpu.class_sizes[vtable_addr] + else: + size = cpu.class_sizes[vtable] + op = ResOperation(rop.NEW_WITH_VTABLE, [ld], newbox, + descr=size) + rebuild_ops.append(op) + memo[box] = newbox + for ofs, node in instnode.curfields.items(): + fieldbox = node.prepare_rebuild_ops(liveboxes, rebuild_ops, + memo, cpu) + if isinstance(ld, FixedList): + op = ResOperation(rop.SETARRAYITEM_GC, + [newbox, ofs, fieldbox], + None, descr=ld.arraydescr) + else: + assert isinstance(ofs, AbstractDescr) + op = ResOperation(rop.SETFIELD_GC, [newbox, fieldbox], + None, descr=ofs) + rebuild_ops.append(op) + return newbox + liveboxes.append(box) + memo[box] = box + if instnode.virtualized: + for ofs, node in instnode.curfields.items(): + fieldbox = node.prepare_rebuild_ops(liveboxes, + rebuild_ops, memo, cpu) + if instnode.cls and isinstance(instnode.cls.source, FixedList): + ld = instnode.cls.source + assert isinstance(ld, FixedList) + op = ResOperation(rop.SETARRAYITEM_GC, + [box, ofs, fieldbox], + None, descr=ld.arraydescr) + else: + assert isinstance(ofs, AbstractDescr) + op = ResOperation(rop.SETFIELD_GC, [box, fieldbox], + None, descr=ofs) + rebuild_ops.append(op) + return box + def __repr__(self): flags = '' if self.escaped: flags += 'e' @@ -208,15 +266,20 @@ def optimize_bridge(options, old_loops, bridge, cpu=None): if not options.specialize: # for tests only - return old_loops[0] + return old_loops[0], None, None perfect_specializer = PerfectSpecializer(bridge, options, cpu) perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): - perfect_specializer.adapt_for_match(old_loop.operations) + num = len(old_loop.extensions) + newlist, newspecnodes, s = perfect_specializer.adapt_for_match( + old_loop.operations, num) + if newlist: + old_loop.extensions.append(newspecnodes) + perfect_specializer.loop.operations[0].args.extend(newlist) perfect_specializer.optimize_loop() - return old_loop + return old_loop, newlist, s return None # no loop matches class PerfectSpecializer(object): @@ -368,7 +431,8 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1], const=True) if op.vdesc: - instnode.vdesc = op.vdesc.virtuals + instnode.vdesc = op.vdesc.virtuals + instnode.allfields = op.vdesc.fields continue elif op.is_always_pure(): for arg in op.args: @@ -398,7 +462,7 @@ for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): - self.nodes[end_box].escape_if_startbox(memo) + self.nodes[end_box].escape_if_startbox(memo, self.cpu) for i in range(len(end_args)): box = self.loop.operations[0].args[i] other_box = end_args[i] @@ -431,76 +495,21 @@ def expanded_version_of(self, boxlist, oplist): # oplist is None means at the start - newboxlist = [] + newboxes = BoxRetriever() assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) - return newboxlist - - def prepare_rebuild_ops(self, instnode, liveboxes, rebuild_ops, memo): - box = instnode.source - if not isinstance(box, Box): - return box - if box in memo: - return memo[box] - if instnode.virtual: - newbox = BoxPtr() - ld = instnode.cls.source - if isinstance(ld, FixedList): - ad = ld.arraydescr - sizebox = ConstInt(instnode.cursize) - op = ResOperation(rop.NEW_ARRAY, [sizebox], newbox, - descr=ad) - else: - vtable = ld.getint() - if self.cpu.translate_support_code: - vtable_addr = self.cpu.cast_int_to_adr(vtable) - size = self.cpu.class_sizes[vtable_addr] - else: - size = self.cpu.class_sizes[vtable] - op = ResOperation(rop.NEW_WITH_VTABLE, [ld], newbox, - descr=size) - rebuild_ops.append(op) - memo[box] = newbox - for ofs, node in instnode.curfields.items(): - fieldbox = self.prepare_rebuild_ops(node, liveboxes, - rebuild_ops, memo) - if isinstance(ld, FixedList): - op = ResOperation(rop.SETARRAYITEM_GC, - [newbox, ofs, fieldbox], - None, descr=ld.arraydescr) - else: - assert isinstance(ofs, AbstractDescr) - op = ResOperation(rop.SETFIELD_GC, [newbox, fieldbox], - None, descr=ofs) - rebuild_ops.append(op) - return newbox - liveboxes.append(box) - memo[box] = box - if instnode.virtualized: - for ofs, node in instnode.curfields.items(): - fieldbox = self.prepare_rebuild_ops(node, liveboxes, - rebuild_ops, memo) - if instnode.cls and isinstance(instnode.cls.source, FixedList): - ld = instnode.cls.source - assert isinstance(ld, FixedList) - op = ResOperation(rop.SETARRAYITEM_GC, - [box, ofs, fieldbox], - None, descr=ld.arraydescr) - else: - assert isinstance(ofs, AbstractDescr) - op = ResOperation(rop.SETFIELD_GC, [box, fieldbox], - None, descr=ofs) - rebuild_ops.append(op) - return box + specnode.expand_boxlist(self.nodes[box], newboxes, oplist) + return newboxes.flatten() def optimize_guard(self, op): # Make a list of operations to run to rebuild the unoptimized objects. # The ops assume that the Boxes in 'liveboxes' have been reloaded. liveboxes = [] rebuild_ops = [] + newboxes = [] + indices = [] memo = {} old_boxes = op.liveboxes op = op.clone() @@ -509,13 +518,14 @@ if isinstance(box, Const): unoptboxes.append(box) continue - unoptboxes.append(self.prepare_rebuild_ops(self.nodes[box], - liveboxes, rebuild_ops, - memo)) + node = self.nodes[box] + unoptboxes.append(node.prepare_rebuild_ops(liveboxes, rebuild_ops, + memo, self.cpu)) # XXX sloooooow! for node in self.nodes.values(): if node.virtualized: - self.prepare_rebuild_ops(node, liveboxes, rebuild_ops, memo) + node.prepare_rebuild_ops(liveboxes, rebuild_ops, memo, + self.cpu) # start of code for dirtyfields support for node in self.nodes.values(): @@ -826,14 +836,19 @@ return False return True - def adapt_for_match(self, old_operations): + def adapt_for_match(self, old_operations, num): old_mp = old_operations[0] jump_op = self.loop.operations[-1] self.specnodes = old_mp.specnodes + newboxlist = BoxRetriever() + rebuild_ops = [] + extensions = [] for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] new_instnode = self.nodes[jump_op.args[i]] - old_specnode.adapt_to(new_instnode) + old_specnode.adapt_to(new_instnode, newboxlist, extensions, num, + rebuild_ops, self.cpu) + return newboxlist.flatten(), extensions, rebuild_ops def get_in_list(dict, boxes_or_consts): result = [] @@ -867,6 +882,41 @@ # done return [currentvalues[box] for box in guard_op.unoptboxes] +def rename_ops(ops, renaming): + res = [] + for op in ops: + newargs = [] + changed = False + for arg in op.args: + if arg in renaming: + newargs.append(renaming[arg]) + changed = True + else: + newargs.append(arg) + if changed: + op = op.clone() + op.args = newargs + res.append(op) + else: + res.append(op) + return res + +def update_loop(metainterp, loop, bridge, newboxlist, newrebuildops): + mp = loop.operations[0] + mp.args += newboxlist + jump = loop.operations[-1] + jump.args += newboxlist + renaming = {} + jump = bridge.operations[-1] + for i in range(len(mp.args)): + renaming[jump.args[i]] = mp.args[i] + for op in loop.operations: + if op.is_guard(): + op.liveboxes += newboxlist + op.rebuild_ops += rename_ops(newrebuildops, renaming) + metainterp.cpu.update_loop(loop, mp, newboxlist) + +# ---------------------------------------------------------------------- def partition(array, left, right): last_item = array[right] Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py Fri Mar 20 11:40:16 2009 @@ -17,6 +17,7 @@ from pypy.jit.metainterp import codewriter, optimize, executor from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize +from pypy.jit.metainterp.specnode import BoxRetriever # ____________________________________________________________ @@ -904,11 +905,11 @@ if mp.specnodes is None: # it is None only for tests return args assert len(mp.specnodes) == len(args) - expanded_args = [] + expanded_args = BoxRetriever() for i in range(len(mp.specnodes)): specnode = mp.specnodes[i] specnode.extract_runtime_data(self.cpu, args[i], expanded_args) - return expanded_args + return expanded_args.flatten() def _initialize_from_start(self, original_boxes, num_green_args, *args): if args: Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py Fri Mar 20 11:40:16 2009 @@ -1,15 +1,45 @@ from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp import executor +from pypy.rlib.objectmodel import r_dict + +def av_eq(self, other): + return self.sort_key() == other.sort_key() + +def av_hash(self): + return self.sort_key() + +class BoxRetriever(object): + def __init__(self): + self.lists = [[]] + self.current = self.lists[0] + + def flatten(self): + res = self.lists[0] + for i in range(1, len(self.lists)): + res.extend(self.lists[i]) + return res + + def extend(self, group): + while len(self.lists) <= group: + self.lists.append([]) + self.current = self.lists[group] + + def append(self, box): + self.current.append(box) + + def reset(self): + self.current = self.lists[0] class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist, start): - newboxlist.append(instnode.source) + def expand_boxlist(self, instnode, newboxes, start): + newboxes.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, rebuild_ops, + cpu): instnode.escaped = True def mutate_nodes(self, instnode): @@ -21,6 +51,33 @@ def matches(self, other): raise NotImplementedError +class RedirectingSpecNode(SpecNode): + def __init__(self, specnode, group): + self.redirect_to = specnode + self.group = group + + def expand_boxlist(self, instnode, newboxes, start): + newboxes.extend(self.group) + self.redirect_to.expand_boxlist(instnode, newboxes, start) + newboxes.reset() + + def extract_runtime_data(self, cpu, valuebox, result): + result.extend(self.group) + self.redirect_to.extract_runtime_data(cpu, valuebox, result) + result.reset() + + def adapt_to(self, *args): + self.redirect_to.adapt_to(*args) + + def equals(self, other): + return self.redirect_to.equals(other) + + def matches(self, other): + return self.redirect_to.matches(other) + +class MatchEverythingSpecNode(SpecNode): + pass + class NotSpecNode(SpecNode): def mutate_nodes(self, instnode): instnode.cursize = -1 @@ -68,31 +125,20 @@ return False return instnode.cls.source.equals(self.known_class) -##class FixedListSpecNode(FixedClassSpecNode): - -## def equals(self, other): -## if type(other) is not FixedListSpecNode: -## return False -## else: -## assert isinstance(other, FixedListSpecNode) # make annotator happy -## return self.known_class.equals(other.known_class) - class SpecNodeWithFields(FixedClassSpecNode): def __init__(self, known_class, fields): FixedClassSpecNode.__init__(self, known_class) self.fields = fields def mutate_nodes(self, instnode): - from pypy.jit.metainterp.optimize import av_eq, av_hash - from pypy.rlib.objectmodel import r_dict - FixedClassSpecNode.mutate_nodes(self, instnode) curfields = r_dict(av_eq, av_hash) for ofs, subspecnode in self.fields: - subinstnode = instnode.origfields[ofs] - # should really be there - subspecnode.mutate_nodes(subinstnode) - curfields[ofs] = subinstnode + if not isinstance(subspecnode, MatchEverythingSpecNode): + subinstnode = instnode.origfields[ofs] + # should really be there + subspecnode.mutate_nodes(subinstnode) + curfields[ofs] = subinstnode instnode.curfields = curfields def equals(self, other): @@ -111,34 +157,38 @@ return True def matches(self, instnode): - # XXX think about details of virtual vs virtualizable if not FixedClassSpecNode.matches(self, instnode): return False for key, value in self.fields: - if key not in instnode.curfields: - return False - if value is not None and not value.matches(instnode.curfields[key]): - return False + if not isinstance(value, MatchEverythingSpecNode): + if key not in instnode.curfields: + return False + if value is not None and not value.matches(instnode.curfields[key]): + return False return True def expand_boxlist(self, instnode, newboxlist, start): for ofs, subspecnode in self.fields: - subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start) + if not isinstance(subspecnode, MatchEverythingSpecNode): + subinstnode = instnode.curfields[ofs] # should really be there + subspecnode.expand_boxlist(subinstnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: from pypy.jit.metainterp.history import AbstractDescr assert isinstance(ofs, AbstractDescr) - fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox], ofs) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + if not isinstance(subspecnode, MatchEverythingSpecNode): + fieldbox = executor.execute(cpu, rop.GETFIELD_GC, + [valuebox], ofs) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, rebuild_ops, + cpu): for ofs, subspecnode in self.fields: - subspecnode.adapt_to(instnode.curfields[ofs]) + subspecnode.adapt_to(instnode.curfields[ofs], newboxlist, + newspecnodes, num, rebuild_ops, cpu) -class VirtualizedSpecNode(SpecNodeWithFields): +class VirtualizedOrDelayedSpecNode(SpecNodeWithFields): def expand_boxlist(self, instnode, newboxlist, start): newboxlist.append(instnode.source) @@ -148,11 +198,13 @@ resultlist.append(valuebox) SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, rebuild_ops, + cpu): instnode.escaped = True - SpecNodeWithFields.adapt_to(self, instnode) + SpecNodeWithFields.adapt_to(self, instnode, newboxlist, newspecnodes, + num, rebuild_ops, cpu) -class DelayedSpecNode(VirtualizedSpecNode): +class DelayedSpecNode(VirtualizedOrDelayedSpecNode): def expand_boxlist(self, instnode, newboxlist, oplist): from pypy.jit.metainterp.history import AbstractDescr @@ -212,23 +264,67 @@ [valuebox, ofs], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) +class VirtualizedSpecNode(VirtualizedOrDelayedSpecNode): + + def equals(self, other): + if not self.known_class.equals(other.known_class): + return False + assert len(self.fields) == len(other.fields) + for i in range(len(self.fields)): + if (isinstance(self.fields[i][1], MatchEverythingSpecNode) or + isinstance(other.fields[i][1], MatchEverythingSpecNode)): + continue + assert self.fields[i][0].equals(other.fields[i][0]) + if not self.fields[i][1].equals(other.fields[i][1]): + return False + return True + + def adapt_to(self, instnode, newboxlist, newspecnodes, num, rebuild_ops, + cpu): + instnode.virtualized = True + fields = [] + for ofs, subspecnode in self.fields: + if isinstance(subspecnode, MatchEverythingSpecNode): + if ofs in instnode.curfields: + orignode = instnode.origfields[ofs] + node = instnode.curfields[ofs] + subspecnode = orignode.intersect(node, {}) + subspecnode.mutate_nodes(orignode) + memo = {} + box = orignode.prepare_rebuild_ops(newboxlist, rebuild_ops, + memo, cpu) + rebuild_ops.append(self.add_setfield(box, instnode.source, + ofs)) + subspecnode = RedirectingSpecNode(subspecnode, num) + newspecnodes.append(subspecnode) + # otherwise we simply ignore unused field + else: + subspecnode.adapt_to(instnode.curfields[ofs], newboxlist, + newspecnodes, num, rebuild_ops, + cpu) + fields.append((ofs, subspecnode)) + self.fields = fields + class VirtualizableSpecNode(VirtualizedSpecNode): def equals(self, other): if not isinstance(other, VirtualizableSpecNode): return False - return SpecNodeWithFields.equals(self, other) + return VirtualizedSpecNode.equals(self, other) - def adapt_to(self, instnode): - instnode.virtualized = True - VirtualizedSpecNode.adapt_to(self, instnode) + def add_setfield(self, box, parentbox, ofs): + return ResOperation(rop.SETFIELD_GC, [parentbox, box], None, ofs) class VirtualizableListSpecNode(VirtualizedSpecNode): + def add_setfield(self, box, parentbox, ofs): + return ResOperation(rop.SETARRAYITEM_GC, [parentbox, ofs, box], None, + self.known_class.arraydescr) + def equals(self, other): if not isinstance(other, VirtualizableListSpecNode): return False - return SpecNodeWithFields.equals(self, other) + return VirtualizedSpecNode.equals(self, other) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop @@ -241,19 +337,18 @@ arraydescr = cls.arraydescr check_descr(arraydescr) for ofs, subspecnode in self.fields: - fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ofs], arraydescr) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - - def adapt_to(self, instnode): - instnode.virtualized = True - VirtualizedSpecNode.adapt_to(self, instnode) + if not isinstance(subspecnode, MatchEverythingSpecNode): + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ofs], arraydescr) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualSpecNode(SpecNodeWithFields): - def adapt_to(self, instnode): + def adapt_to(self, instnode, newboxlist, newspecnodes, num, rebuild_ops, + cpu): instnode.virtual = True - SpecNodeWithFields.adapt_to(self, instnode) + return SpecNodeWithFields.adapt_to(self, instnode, newboxlist, + newspecnodes, num, rebuild_ops, cpu) def mutate_nodes(self, instnode): SpecNodeWithFields.mutate_nodes(self, instnode) @@ -268,28 +363,29 @@ class VirtualFixedListSpecNode(VirtualSpecNode): - def __init__(self, known_class, fields, known_length): - VirtualSpecNode.__init__(self, known_class, fields) - self.known_length = known_length - - def mutate_nodes(self, instnode): - VirtualSpecNode.mutate_nodes(self, instnode) - instnode.cursize = self.known_length - - def equals(self, other): - if not isinstance(other, VirtualFixedListSpecNode): - return False - return SpecNodeWithFields.equals(self, other) + def __init__(self, known_class, fields, known_length): + VirtualSpecNode.__init__(self, known_class, fields) + self.known_length = known_length + + def mutate_nodes(self, instnode): + VirtualSpecNode.mutate_nodes(self, instnode) + instnode.cursize = self.known_length + + def equals(self, other): + if not isinstance(other, VirtualFixedListSpecNode): + return False + return SpecNodeWithFields.equals(self, other) - def extract_runtime_data(self, cpu, valuebox, resultlist): - from pypy.jit.metainterp.resoperation import rop - from pypy.jit.metainterp.optimize import FixedList - from pypy.jit.metainterp.history import check_descr - cls = self.known_class - assert isinstance(cls, FixedList) - arraydescr = cls.arraydescr - check_descr(arraydescr) - for ofs, subspecnode in self.fields: - fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ofs], arraydescr) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.resoperation import rop + from pypy.jit.metainterp.optimize import FixedList + from pypy.jit.metainterp.history import check_descr + cls = self.known_class + assert isinstance(cls, FixedList) + arraydescr = cls.arraydescr + check_descr(arraydescr) + for ofs, subspecnode in self.fields: + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ofs], arraydescr) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_vable_optimize.py Fri Mar 20 11:40:16 2009 @@ -24,13 +24,13 @@ ('parent', rclass.OBJECT), ('vable_base', llmemory.Address), ('vable_rti', VABLERTIPTR), - ('x', lltype.Signed), - ('l', lltype.Ptr(lltype.GcArray(lltype.Signed))), - ('node', lltype.Ptr(NODE)), + ('inst_x', lltype.Signed), + ('inst_l', lltype.Ptr(lltype.GcArray(lltype.Signed))), + ('inst_node', lltype.Ptr(NODE)), hints = {'virtualizable2': True, 'virtuals':()}, adtmeths = {'access': VirtualizableAccessor()}) -XY._adtmeths['access'].initialize(XY, ['x', 'node', 'l']) +XY._adtmeths['access'].initialize(XY, ['inst_x', 'inst_node', 'inst_l']) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True) @@ -59,32 +59,30 @@ heaptracker.set_testing_vtable_for_gcstruct(XYSUB, xysub_vtable) # ____________________________________________________________ -ofs_node = runner.CPU.fielddescrof(XY, 'node') xy_desc = VirtualizableDesc(cpu, XY, XY) -xy_desc.fields = [ofs_node] # ____________________________________________________________ class A: - ofs_node = runner.CPU.fielddescrof(XY, 'node') - ofs_l = runner.CPU.fielddescrof(XY, 'l') + ofs_node = runner.CPU.fielddescrof(XY, 'inst_node') + ofs_l = runner.CPU.fielddescrof(XY, 'inst_l') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # frame = lltype.malloc(XY) frame.vable_rti = lltype.nullptr(XY.vable_rti.TO) - frame.node = lltype.malloc(NODE) - frame.node.value = 20 + frame.inst_node = lltype.malloc(NODE) + frame.inst_node.value = 20 sum = BoxInt(0) fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) - n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) nextnode = lltype.malloc(NODE) nextnode.value = 19 n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) - v = BoxInt(frame.node.value) + v = BoxInt(frame.inst_node.value) v2 = BoxInt(nextnode.value) - sum2 = BoxInt(0 + frame.node.value) + sum2 = BoxInt(0 + frame.inst_node.value) ops = [ ResOperation('merge_point', [sum, fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], @@ -131,16 +129,16 @@ # ____________________________________________________________ class B: - ofs_node = runner.CPU.fielddescrof(XY, 'node') + ofs_node = runner.CPU.fielddescrof(XY, 'inst_node') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # frame = lltype.malloc(XY) frame.vable_rti = lltype.nullptr(XY.vable_rti.TO) - frame.node = lltype.malloc(NODE) - frame.node.value = 20 + frame.inst_node = lltype.malloc(NODE) + frame.inst_node.value = 20 fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) - n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) v = BoxInt(13) ops = [ ResOperation('merge_point', [fr], None), @@ -160,15 +158,15 @@ assert spec.nodes[B.fr].virtualized assert spec.nodes[B.n1].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) - assert len(spec.specnodes[0].fields) == 1 - assert spec.specnodes[0].fields[0][0] == B.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) + assert len(spec.specnodes[0].fields) == 3 + assert spec.specnodes[0].fields[2][0] == B.ofs_node + assert isinstance(spec.specnodes[0].fields[2][1], NotSpecNode) # ____________________________________________________________ class C: locals().update(B.__dict__) - n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) v2 = BoxInt(13) ops = [ ResOperation('merge_point', [fr], None), @@ -196,9 +194,9 @@ assert spec.nodes[C.n1].escaped assert spec.nodes[C.n2].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) - assert len(spec.specnodes[0].fields) == 1 - assert spec.specnodes[0].fields[0][0] == C.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], DelayedSpecNode) + assert len(spec.specnodes[0].fields) == 3 + assert spec.specnodes[0].fields[2][0] == C.ofs_node + assert isinstance(spec.specnodes[0].fields[2][1], DelayedSpecNode) # ____________________________________________________________ Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py Fri Mar 20 11:40:16 2009 @@ -25,62 +25,65 @@ return xy def test_preexisting_access(self): + py.test.skip("bugs") myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) def f(n): xy = self.setup() - xy.x = 10 + xy.inst_x = 10 while n > 0: myjitdriver.can_enter_jit(xy=xy, n=n) myjitdriver.jit_merge_point(xy=xy, n=n) - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 1 + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x + xy.inst_x = x + 1 n -= 1 - return xy.x + return xy.inst_x res = self.meta_interp(f, [20]) assert res == 30 self.check_loops(getfield_gc=0, setfield_gc=0) def test_preexisting_access_2(self): + py.test.skip("bugs") myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) def f(n): xy = self.setup() - xy.x = 100 + xy.inst_x = 100 while n > -8: myjitdriver.can_enter_jit(xy=xy, n=n) myjitdriver.jit_merge_point(xy=xy, n=n) if n > 0: - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 1 + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x + xy.inst_x = x + 1 else: - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 10 + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x + xy.inst_x = x + 10 n -= 1 - return xy.x + return xy.inst_x res = self.meta_interp(f, [5]) assert res == 185 self.check_loops(getfield_gc=0, setfield_gc=0) def test_two_paths_access(self): + py.test.skip("bugs") myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) def f(n): xy = self.setup() - xy.x = 100 + xy.inst_x = 100 while n > 0: myjitdriver.can_enter_jit(xy=xy, n=n) myjitdriver.jit_merge_point(xy=xy, n=n) - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x if n <= 10: x += 1000 - xy.x = x + 1 + xy.inst_x = x + 1 n -= 1 - return xy.x + return xy.inst_x res = self.meta_interp(f, [18]) assert res == 10118 self.check_loops(getfield_gc=0, setfield_gc=0) @@ -394,7 +397,6 @@ assert res == 2 def test_pass_always_virtual_to_bridge(self): - py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) @@ -423,7 +425,6 @@ assert res == 3 def test_virtual_obj_on_always_virtual(self): - py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) @@ -452,7 +453,7 @@ s += frame.l[1].elem frame.l[1] = Stuff(n) n -= 1 - return s + return (frame.l[0].elem << 16) + frame.l[1].elem res = self.meta_interp(f, [30], listops=True) self.check_loops(getfield_gc=0) Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/virtualizable.py Fri Mar 20 11:40:16 2009 @@ -10,5 +10,18 @@ def __init__(self, cpu, TOPSTRUCT, STRUCTTYPE): "NOT_RPYTHON" - self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for - name in TOPSTRUCT._hints['virtuals']] + self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for + name in TOPSTRUCT._hints['virtuals']] + self.fields = self.catch_all_fields(cpu, STRUCTTYPE) + + def catch_all_fields(self, cpu, S): + lst = [] + p = S + while True: + lst.extend(p._names) + if getattr(p, 'super', None) is not None: + p = p.super + else: + break + return [cpu.fielddescrof(S, name) for name in lst if + name.startswith('inst_')] From fijal at codespeak.net Fri Mar 20 11:41:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 11:41:49 +0100 (CET) Subject: [pypy-svn] r63124 - pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph Message-ID: <20090320104149.C6C4A168489@codespeak.net> Author: fijal Date: Fri Mar 20 11:41:49 2009 New Revision: 63124 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/llimpl.py pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py Log: missing backend updates Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/llimpl.py Fri Mar 20 11:41:49 2009 @@ -554,6 +554,9 @@ value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable, self.memocast) return result + def op_new(self, size): + return do_new(size.ofs) + def op_setarrayitem_gc(self, arraydescr, array, index, newvalue): if arraydescr.type == 'p': do_setarrayitem_gc_ptr(array, index, newvalue) Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py Fri Mar 20 11:41:49 2009 @@ -37,6 +37,11 @@ def sort_key(self): return self.ofs + def equals(self, other): + if not isinstance(other, Descr): + return False + return self.sort_key() == other.sort_key() + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): @@ -74,6 +79,19 @@ def set_meta_interp(self, metainterp): self.metainterp = metainterp # to handle guard failures + def compile_arg(self, x, c, op, var2index): + if isinstance(x, history.Box): + llimpl.compile_add_var(c, var2index[x]) + elif isinstance(x, history.ConstInt): + llimpl.compile_add_int_const(c, x.value) + elif isinstance(x, history.ConstPtr): + llimpl.compile_add_ptr_const(c, x.value) + elif isinstance(x, history.ConstAddr): + llimpl.compile_add_int_const(c, x.getint()) + else: + raise Exception("%s args contain: %r" % (op.getopname(), + x)) + def compile_operations(self, operations, from_guard=None): """In a real assembler backend, this should assemble the given list of operations. Here we just generate a similar LoopOrBridge @@ -105,17 +123,7 @@ if op.descr is not None: llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type) for x in op.args: - if isinstance(x, history.Box): - llimpl.compile_add_var(c, var2index[x]) - elif isinstance(x, history.ConstInt): - llimpl.compile_add_int_const(c, x.value) - elif isinstance(x, history.ConstPtr): - llimpl.compile_add_ptr_const(c, x.value) - elif isinstance(x, history.ConstAddr): - llimpl.compile_add_int_const(c, x.getint()) - else: - raise Exception("%s args contain: %r" % (op.getopname(), - x)) + self.compile_arg(x, c, op, var2index) x = op.result if x is not None: if isinstance(x, history.BoxInt): @@ -142,6 +150,9 @@ llimpl.compile_from_guard(c, from_guard._compiled, from_guard._opindex) + def update_loop(self, loop, mp, newboxlist): + self.compile_operations(loop.operations) + def execute_operations_in_new_frame(self, name, operations, valueboxes): """Perform a 'call' to the given merge point, i.e. create a new CPU frame and use it to execute the operations that From pedronis at codespeak.net Fri Mar 20 11:44:48 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 11:44:48 +0100 (CET) Subject: [pypy-svn] r63125 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090320104448.7068D168493@codespeak.net> Author: pedronis Date: Fri Mar 20 11:44:46 2009 New Revision: 63125 Modified: pypy/trunk/pypy/objspace/std/test/test_stringobject.py Log: (iko, pedronis) adjust the test consistently with what we did for unicode instead of skipping it Modified: pypy/trunk/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_stringobject.py Fri Mar 20 11:44:46 2009 @@ -372,11 +372,10 @@ assert ''.expandtabs() =='' def test_expandtabs_overflows_gracefully(self): - skip("XXX fix me") import sys if sys.maxint > (1 << 32): skip("Wrong platform") - raises(OverflowError, 't\tt\t'.expandtabs, sys.maxint) + raises((MemoryError, OverflowError), 't\tt\t'.expandtabs, sys.maxint) def test_splitlines(self): s = "" From fijal at codespeak.net Fri Mar 20 11:55:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 11:55:47 +0100 (CET) Subject: [pypy-svn] r63126 - pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp Message-ID: <20090320105547.82224168473@codespeak.net> Author: fijal Date: Fri Mar 20 11:55:46 2009 New Revision: 63126 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py Log: add an XXX Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py Fri Mar 20 11:55:46 2009 @@ -910,6 +910,7 @@ jump = bridge.operations[-1] for i in range(len(mp.args)): renaming[jump.args[i]] = mp.args[i] + # XXX also walk all already created bridges for op in loop.operations: if op.is_guard(): op.liveboxes += newboxlist From pedronis at codespeak.net Fri Mar 20 12:04:14 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 12:04:14 +0100 (CET) Subject: [pypy-svn] r63127 - pypy/trunk/pypy/module/_rawffi/test Message-ID: <20090320110414.54F2B168486@codespeak.net> Author: pedronis Date: Fri Mar 20 12:04:14 2009 New Revision: 63127 Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Log: (iko, pedronis) this seems to fix the test which was failing because things from before the test were alived and then collected during it. collect more before the test Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Fri Mar 20 12:04:14 2009 @@ -866,13 +866,13 @@ def test_structure_autofree(self): import gc, _rawffi gc.collect() + gc.collect() S = _rawffi.Structure([('x', 'i')]) oldnum = _rawffi._num_of_allocated_objects() s = S(autofree=True) s.x = 3 s = None gc.collect() - gc.collect() assert oldnum == _rawffi._num_of_allocated_objects() def test_array_autofree(self): From arigo at codespeak.net Fri Mar 20 12:34:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 20 Mar 2009 12:34:17 +0100 (CET) Subject: [pypy-svn] r63128 - in pypy/trunk/pypy/objspace/std: . test Message-ID: <20090320113417.E2D6116847F@codespeak.net> Author: arigo Date: Fri Mar 20 12:34:15 2009 New Revision: 63128 Modified: pypy/trunk/pypy/objspace/std/rangeobject.py pypy/trunk/pypy/objspace/std/test/test_rangeobject.py Log: Missing += and *= on range() objects. Modified: pypy/trunk/pypy/objspace/std/rangeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/rangeobject.py (original) +++ pypy/trunk/pypy/objspace/std/rangeobject.py Fri Mar 20 12:34:15 2009 @@ -128,6 +128,14 @@ n += 1 return space.wrap("[" + ", ".join(result) + "]") +def inplace_add__RangeList_ANY(space, w_rangelist, w_iterable2): + space.inplace_add(w_rangelist.force(space), w_iterable2) + return w_rangelist + +def inplace_mul__RangeList_ANY(space, w_rangelist, w_number): + space.inplace_mul(w_rangelist.force(space), w_number) + return w_rangelist + def list_pop__RangeList_ANY(space, w_rangelist, w_idx=-1): if w_rangelist.w_list is not None: Modified: pypy/trunk/pypy/objspace/std/test/test_rangeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_rangeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_rangeobject.py Fri Mar 20 12:34:15 2009 @@ -132,3 +132,19 @@ def test_no_len_on_range_iter(self): iterable = range(10) raises(TypeError, len, iter(iterable)) + + def test_inplace_add(self): + r1 = r2 = range(5) + assert r1 is r2 + r1 += [15] + assert r1 is r2 + assert r1 == [0, 1, 2, 3, 4, 15] + assert r2 == [0, 1, 2, 3, 4, 15] + + def test_inplace_mul(self): + r1 = r2 = range(3) + assert r1 is r2 + r1 *= 2 + assert r1 is r2 + assert r1 == [0, 1, 2, 0, 1, 2] + assert r2 == [0, 1, 2, 0, 1, 2] From fijal at codespeak.net Fri Mar 20 12:52:45 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 12:52:45 +0100 (CET) Subject: [pypy-svn] r63129 - in pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp: . test Message-ID: <20090320115245.B39BF168487@codespeak.net> Author: fijal Date: Fri Mar 20 12:52:44 2009 New Revision: 63129 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py Log: A test and a partial fix Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py Fri Mar 20 12:52:44 2009 @@ -169,9 +169,9 @@ # res = optimize.optimize_bridge(metainterp.options, old_loops, bridge, metainterp.cpu) - old_loop, newboxlist, storage = res - if old_loop is None: + if res is None: return None + old_loop, newboxlist, storage = res bridge.jump_to = old_loop if newboxlist: # recompile loop Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py Fri Mar 20 12:52:44 2009 @@ -266,6 +266,15 @@ class VirtualizedSpecNode(VirtualizedOrDelayedSpecNode): + def matches(self, instnode): + for key, value in self.fields: + if not isinstance(value, MatchEverythingSpecNode): + if key not in instnode.curfields: + return False + if value is not None and not value.matches(instnode.curfields[key]): + return False + return True + def equals(self, other): if not self.known_class.equals(other.known_class): return False Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py Fri Mar 20 12:52:44 2009 @@ -459,6 +459,45 @@ self.check_loops(getfield_gc=0) assert res == f(30) + + def test_virtual_obj_on_always_virtual_more_bridges(self): + py.test.skip("Broken") + jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + _always_virtual_ = ['l'] + + def __init__(self, l): + self.l = l + + class Stuff(object): + def __init__(self, elem): + self.elem = elem + + def f(n): + frame = Frame([Stuff(3), Stuff(4)]) + s = 0 + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n, s=s) + jitdriver.jit_merge_point(frame=frame, n=n, s=s) + if n % 2: + s += frame.l[0].elem + frame.l[0] = Stuff(n) + elif n % 3: + s += 1 + else: + s += frame.l[1].elem + frame.l[1] = Stuff(n) + n -= 1 + return (frame.l[0].elem << 16) + frame.l[1].elem + + res = self.meta_interp(f, [60], listops=True) + self.check_loops(getfield_gc=0) + assert res == f(60) + def test_external_read(self): py.test.skip("Fails") jitdriver = JitDriver(greens = [], reds = ['frame'], From fijal at codespeak.net Fri Mar 20 13:32:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 13:32:08 +0100 (CET) Subject: [pypy-svn] r63131 - in pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp: . test Message-ID: <20090320123208.83D69168473@codespeak.net> Author: fijal Date: Fri Mar 20 13:32:05 2009 New Revision: 63131 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/graphpage.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/history.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py Log: * allow VirtualizableSpecNode to match NotSpecNode (unused virtualizable becomes NotSpecNode) * Fix the test, although everything explodes on top of llgraph backend, surprise * Store a loop instead of single op as jump_target Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py Fri Mar 20 13:32:05 2009 @@ -129,25 +129,24 @@ def compile_fresh_loop(metainterp, loop, old_loops, endliveboxes): history = metainterp.history loop.operations = history.operations - close_loop(loop, loop.operations[0], endliveboxes) + close_loop(loop, endliveboxes) old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, metainterp.cpu) if old_loop is not None: return old_loop - finish_loop_or_bridge(metainterp, loop, loop.operations[0]) + finish_loop_or_bridge(metainterp, loop, loop) old_loops.append(loop) return loop -def close_loop(loop, targetmp, endliveboxes): - assert targetmp.opnum == rop.MERGE_POINT +def close_loop(loop, endliveboxes): op = ResOperation(rop.JUMP, endliveboxes, None) - op.jump_target = targetmp + op.jump_target = loop loop.operations.append(op) -def finish_loop_or_bridge(metainterp, loop, targetmp, guard_op=None): - assert targetmp.opnum == rop.MERGE_POINT +def finish_loop_or_bridge(metainterp, loop, target, guard_op=None): + assert target.operations[0].opnum == rop.MERGE_POINT assert loop.operations[-1].opnum == rop.JUMP - loop.operations[-1].jump_target = targetmp + loop.operations[-1].jump_target = target metainterp.cpu.compile_operations(loop.operations, guard_op) metainterp.stats.loops.append(loop) @@ -175,6 +174,7 @@ bridge.jump_to = old_loop if newboxlist: # recompile loop - optimize.update_loop(metainterp, old_loop, bridge, newboxlist, storage) - finish_loop_or_bridge(metainterp, bridge, old_loop.operations[0], guard_op) + optimize.update_loop(metainterp, old_loop, bridge, newboxlist, storage, + old_loop) + finish_loop_or_bridge(metainterp, bridge, old_loop, guard_op) return bridge Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/graphpage.py Fri Mar 20 13:32:05 2009 @@ -48,10 +48,12 @@ for attrname, delta in [('jump_target', 0), ('_jump_target_prev', 1)]: tgt = getattr(op, attrname, None) - if tgt is not None and tgt in self.all_operations: - tgt_g, tgt_i = self.all_operations[tgt] - self.mark_starter(tgt_g, tgt_i+delta) - self.mark_starter(graphindex, i+1) + if tgt is not None: + tgt = tgt.operations[0] + if tgt in self.all_operations: + tgt_g, tgt_i = self.all_operations[tgt] + self.mark_starter(tgt_g, tgt_i+delta) + self.mark_starter(graphindex, i+1) if (op in self.highlightops) != (prevop in self.highlightops): self.mark_starter(graphindex, i) prevop = op @@ -134,17 +136,19 @@ for attrname, delta in [('jump_target', 0), ('_jump_target_prev', 1)]: tgt = getattr(op, attrname, None) - if tgt is not None and tgt in self.all_operations: - tgt_g, tgt_i = self.all_operations[tgt] - kwds = {} - #if op.opname == 'jump': - # #kwds['constraint'] = 'false' - # #kwds['headport'] = ':n' - # pass - self.genedge((graphindex, opstartindex), - (tgt_g, tgt_i+delta), - color='red', - **kwds) + if tgt is not None: + tgt = tgt.operations[0] + if tgt in self.all_operations: + tgt_g, tgt_i = self.all_operations[tgt] + kwds = {} + #if op.opname == 'jump': + # #kwds['constraint'] = 'false' + # #kwds['headport'] = ':n' + # pass + self.genedge((graphindex, opstartindex), + (tgt_g, tgt_i+delta), + color='red', + **kwds) opindex += 1 if opindex >= len(operations): break Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/history.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/history.py Fri Mar 20 13:32:05 2009 @@ -378,7 +378,7 @@ assert box not in seen seen[box] = True assert operations[-1].opnum == rop.JUMP - assert operations[-1].jump_target.opnum == rop.MERGE_POINT + assert operations[-1].jump_target.operations[0].opnum == rop.MERGE_POINT def __repr__(self): return '<%s>' % (self.name,) Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py Fri Mar 20 13:32:05 2009 @@ -901,18 +901,21 @@ res.append(op) return res -def update_loop(metainterp, loop, bridge, newboxlist, newrebuildops): +def update_loop(metainterp, loop, bridge, newboxlist, newrebuildops, orig_loop): mp = loop.operations[0] mp.args += newboxlist jump = loop.operations[-1] - jump.args += newboxlist + if jump.jump_target is orig_loop: + jump.args += newboxlist renaming = {} jump = bridge.operations[-1] for i in range(len(mp.args)): renaming[jump.args[i]] = mp.args[i] - # XXX also walk all already created bridges for op in loop.operations: if op.is_guard(): + if op.jump_target is not None: + update_loop(metainterp, op.jump_target, bridge, newboxlist, + newrebuildops, loop) op.liveboxes += newboxlist op.rebuild_ops += rename_ops(newrebuildops, renaming) metainterp.cpu.update_loop(loop, mp, newboxlist) Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/pyjitpl.py Fri Mar 20 13:32:05 2009 @@ -897,7 +897,7 @@ if not we_are_translated(): bridge._call_history = self._debug_history self.debug_history = [] - guard_failure.guard_op.jump_target = bridge.operations[0] + guard_failure.guard_op.jump_target = bridge return bridge def get_residual_args(self, loop, args): Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/specnode.py Fri Mar 20 13:32:05 2009 @@ -85,7 +85,7 @@ def equals(self, other): if type(other) is NotSpecNode: return True - return False + return other.equals(self) def matches(self, other): # NotSpecNode matches everything @@ -317,6 +317,8 @@ class VirtualizableSpecNode(VirtualizedSpecNode): def equals(self, other): + if type(other) is NotSpecNode: + return True if not isinstance(other, VirtualizableSpecNode): return False return VirtualizedSpecNode.equals(self, other) @@ -331,6 +333,8 @@ self.known_class.arraydescr) def equals(self, other): + if type(other) is NotSpecNode: + return True if not isinstance(other, VirtualizableListSpecNode): return False return VirtualizedSpecNode.equals(self, other) Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/test/test_virtualizable.py Fri Mar 20 13:32:05 2009 @@ -461,7 +461,6 @@ def test_virtual_obj_on_always_virtual_more_bridges(self): - py.test.skip("Broken") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) From fijal at codespeak.net Fri Mar 20 13:32:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 13:32:51 +0100 (CET) Subject: [pypy-svn] r63132 - pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph Message-ID: <20090320123251.193FA1684A9@codespeak.net> Author: fijal Date: Fri Mar 20 13:32:50 2009 New Revision: 63132 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py Log: store catches in jump2target as well Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/backend/llgraph/runner.py Fri Mar 20 13:32:50 2009 @@ -135,7 +135,7 @@ x)) if op.jump_target is not None: loop_target, loop_target_index = \ - self.jumptarget2loop[op.jump_target] + self.jumptarget2loop[op.jump_target.operations[0]] llimpl.compile_add_jump_target(c, loop_target, loop_target_index) if op.is_guard(): @@ -144,7 +144,7 @@ for box in op.liveboxes: assert isinstance(box, history.Box) llimpl.compile_add_livebox(c, var2index[box]) - if op.opnum == rop.MERGE_POINT: + if op.opnum == rop.MERGE_POINT or op.opnum == rop.CATCH: self.jumptarget2loop[op] = c, i if from_guard is not None: llimpl.compile_from_guard(c, from_guard._compiled, From fijal at codespeak.net Fri Mar 20 13:41:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 13:41:21 +0100 (CET) Subject: [pypy-svn] r63133 - pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp Message-ID: <20090320124121.E25191684AA@codespeak.net> Author: fijal Date: Fri Mar 20 13:41:21 2009 New Revision: 63133 Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py Log: clean up, call update_tree from a single place Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/compile.py Fri Mar 20 13:41:21 2009 @@ -174,7 +174,7 @@ bridge.jump_to = old_loop if newboxlist: # recompile loop - optimize.update_loop(metainterp, old_loop, bridge, newboxlist, storage, - old_loop) + optimize.update_loop(old_loop, bridge, newboxlist, storage, old_loop) + metainterp.cpu.update_tree(old_loop) finish_loop_or_bridge(metainterp, bridge, old_loop, guard_op) return bridge Modified: pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/virtualizable-specnodes-2/pypy/jit/metainterp/optimize.py Fri Mar 20 13:41:21 2009 @@ -901,7 +901,7 @@ res.append(op) return res -def update_loop(metainterp, loop, bridge, newboxlist, newrebuildops, orig_loop): +def update_loop(loop, bridge, newboxlist, newrebuildops, orig_loop): mp = loop.operations[0] mp.args += newboxlist jump = loop.operations[-1] @@ -914,11 +914,10 @@ for op in loop.operations: if op.is_guard(): if op.jump_target is not None: - update_loop(metainterp, op.jump_target, bridge, newboxlist, + update_loop(op.jump_target, bridge, newboxlist, newrebuildops, loop) op.liveboxes += newboxlist op.rebuild_ops += rename_ops(newrebuildops, renaming) - metainterp.cpu.update_loop(loop, mp, newboxlist) # ---------------------------------------------------------------------- From pedronis at codespeak.net Fri Mar 20 13:55:02 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 13:55:02 +0100 (CET) Subject: [pypy-svn] r63134 - in pypy/trunk/pypy/objspace/std: . test Message-ID: <20090320125502.6E8BF1684A8@codespeak.net> Author: pedronis Date: Fri Mar 20 13:55:00 2009 New Revision: 63134 Modified: pypy/trunk/pypy/objspace/std/builtinshortcut.py pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py Log: (iko, pedronis) don't consider conversions for the shortcuts, they may introduce divergences wrt cpython binary op behavior, fixes unicode string comparison issues with the shortcuts enabled Modified: pypy/trunk/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/trunk/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/trunk/pypy/objspace/std/builtinshortcut.py Fri Mar 20 13:55:00 2009 @@ -50,6 +50,14 @@ % (_name,)) +def filter_out_conversions(typeorder): + res = {} + for cls, order in typeorder.iteritems(): + res[cls] = [(target_type, converter) for (target_type, converter) in + order if converter is None] + return res + + def install(space, mm, fallback_mm=None): """Install a function () on the space instance which invokes a shortcut for built-in types. Returns the shortcutting multimethod @@ -81,7 +89,7 @@ expanded_order = space.model.get_typeorder_with_empty_usersubcls() if fallback_mm: mm = mm.merge_with(fallback_mm) - shortcut_method = mm.install_not_sliced(expanded_order) + shortcut_method = mm.install_not_sliced(filter_out_conversions(expanded_order)) def operate(*args_w): try: Modified: pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py Fri Mar 20 13:55:00 2009 @@ -62,7 +62,6 @@ assert 5 + 6.5 == 11.5 def test_unicode_string_compares(self): - skip("FAILING") assert u'a' == 'a' assert 'a' == u'a' assert not u'a' == 'b' From pedronis at codespeak.net Fri Mar 20 15:00:01 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 15:00:01 +0100 (CET) Subject: [pypy-svn] r63138 - in pypy/trunk/pypy: module/marshal/test rlib rlib/test Message-ID: <20090320140001.3C4941684A2@codespeak.net> Author: pedronis Date: Fri Mar 20 14:59:58 2009 New Revision: 63138 Modified: pypy/trunk/pypy/module/marshal/test/test_marshal.py pypy/trunk/pypy/rlib/runicode.py pypy/trunk/pypy/rlib/test/test_runicode.py Log: (iko, pedronis) - fix a utf-8 decoding issue that also was breaking unmarshaling of unicode - extend the runicode tests a bit Modified: pypy/trunk/pypy/module/marshal/test/test_marshal.py ============================================================================== --- pypy/trunk/pypy/module/marshal/test/test_marshal.py (original) +++ pypy/trunk/pypy/module/marshal/test/test_marshal.py Fri Mar 20 14:59:58 2009 @@ -577,6 +577,17 @@ assert obj2b == obj2 assert tail == 'END' + def test_unicode(self): + import marshal, sys + + u = u'\uFFFF' + u1 = marshal.loads(marshal.dumps(u)) + assert u == u1 + + u = unichr(sys.maxunicode) + u1 = marshal.loads(marshal.dumps(u)) + assert u == u1 + class AppTestMultiDict(object): def setup_class(cls): Modified: pypy/trunk/pypy/rlib/runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/runicode.py (original) +++ pypy/trunk/pypy/rlib/runicode.py Fri Mar 20 14:59:58 2009 @@ -178,7 +178,7 @@ result.append(r) else: # convert to UTF-16 if necessary - if c < MAXUNICODE: + if c <= MAXUNICODE: result.append(UNICHR(c)) else: # compute and append the two surrogates: Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Fri Mar 20 14:59:58 2009 @@ -89,12 +89,25 @@ for encoding in "utf-8 latin-1 utf-16 utf-16-be utf-16-le".split(): self.checkdecode(unichr(i), encoding) - def test_random(self): + def test_first_10000(self): for i in range(10000): - uni = unichr(random.randrange(sys.maxunicode)) for encoding in "utf-8 utf-16 utf-16-be utf-16-le".split(): self.checkdecode(unichr(i), encoding) + def test_random(self): + for i in range(10000): + v = random.randrange(sys.maxunicode) + if 0xd800 <= v <= 0xdfff: + continue + uni = unichr(v) + for encoding in "utf-8 utf-16 utf-16-be utf-16-le".split(): + self.checkdecode(uni, encoding) + + def test_maxunicode(self): + uni = unichr(sys.maxunicode) + for encoding in "utf-8 utf-16 utf-16-be utf-16-le".split(): + self.checkdecode(uni, encoding) + def test_single_chars_utf8(self): for s in ["\xd7\x90", "\xd6\x96", "\xeb\x96\x95", "\xf0\x90\x91\x93"]: self.checkdecode(s, "utf-8") @@ -156,12 +169,25 @@ for encoding in "utf-8 latin-1 utf-16 utf-16-be utf-16-le".split(): self.checkencode(unichr(i), encoding) - def test_random(self): + def test_first_10000(self): for i in range(10000): - uni = unichr(random.randrange(sys.maxunicode)) for encoding in "utf-8 utf-16 utf-16-be utf-16-le".split(): self.checkencode(unichr(i), encoding) + def test_random(self): + for i in range(10000): + v = random.randrange(sys.maxunicode) + if 0xd800 <= v <= 0xdfff: + continue + uni = unichr(v) + for encoding in "utf-8 utf-16 utf-16-be utf-16-le".split(): + self.checkencode(uni, encoding) + + def test_maxunicode(self): + uni = unichr(sys.maxunicode) + for encoding in "utf-8 utf-16 utf-16-be utf-16-le".split(): + self.checkencode(uni, encoding) + def test_single_chars_utf8(self): # check every number of bytes per char for s in ["\xd7\x90", "\xd6\x96", "\xeb\x96\x95", "\xf0\x90\x91\x93"]: From afa at codespeak.net Fri Mar 20 15:10:21 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Mar 2009 15:10:21 +0100 (CET) Subject: [pypy-svn] r63140 - pypy/trunk/pypy/module/rctime Message-ID: <20090320141021.2C16B1684B1@codespeak.net> Author: afa Date: Fri Mar 20 15:10:20 2009 New Revision: 63140 Modified: pypy/trunk/pypy/module/rctime/interp_time.py Log: Implement init_timezone() on Windows. This is still wrong though: this function is called from buildloaders(), i.e. early when translating! It should be moved into a startup() method. Modified: pypy/trunk/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/trunk/pypy/module/rctime/interp_time.py (original) +++ pypy/trunk/pypy/module/rctime/interp_time.py Fri Mar 20 15:10:20 2009 @@ -50,7 +50,7 @@ setattr(cConfig, k, v) cConfig.tm.__name__ = "_tm" -def external(name, args, result): +def external(name, args, result, eci=CConfig._compilation_info_): if _WIN and rffi.sizeof(rffi.TIME_T) == 8: # Recent Microsoft compilers use 64bit time_t and # the corresponding functions are named differently @@ -58,7 +58,7 @@ or result in (rffi.TIME_T, rffi.TIME_TP)): name = '_' + name + '64' return rffi.llexternal(name, args, result, - compilation_info=CConfig._compilation_info_, + compilation_info=eci, calling_conv=calling_conv, threadsafe=False) @@ -83,6 +83,23 @@ c_localtime = external('localtime', [rffi.TIME_TP], TM_P) if _POSIX: c_tzset = external('tzset', [], lltype.Void) +if _WIN: + win_eci = ExternalCompilationInfo( + includes = ["time.h"], + separate_module_sources = [ """ + long get_timezone() { return timezone; } + int get_daylight() { return daylight; } + char** get_tzname() { return tzname; } + """ + ], + export_symbols = ['_tzset', 'get_timezone', 'get_daylight', 'get_tzname'], + ) + # Ensure sure that we use _tzset() and timezone from the same C Runtime. + c_tzset = external('_tzset', [], lltype.Void, win_eci) + c_get_timezone = external('get_timezone', [], rffi.LONG, win_eci) + c_get_daylight = external('get_daylight', [], rffi.INT, win_eci) + c_get_tzname = external('get_tzname', [], rffi.CCHARPP, win_eci) + c_strftime = external('strftime', [rffi.CCHARP, rffi.SIZE_T, rffi.CCHARP, TM_P], rffi.SIZE_T) @@ -92,21 +109,15 @@ def _init_timezone(): timezone = daylight = altzone = 0 tzname = ["", ""] - - # pypy cant' use in_dll to access global exported variables - # so we can't compute these attributes - # if _WIN: - # cdll.msvcrt._tzset() - # - # timezone = c_long.in_dll(cdll.msvcrt, "_timezone").value - # if hasattr(cdll.msvcrt, "altzone"): - # altzone = c_long.in_dll(cdll.msvcrt, "altzone").value - # else: - # altzone = timezone - 3600 - # daylight = c_long.in_dll(cdll.msvcrt, "_daylight").value - # tzname = _tzname_t.in_dll(cdll.msvcrt, "_tzname") - # tzname = (tzname.tzname_0, tzname.tzname_1) + if _WIN: + c_tzset() + timezone = c_get_timezone() + altzone = timezone - 3600 + daylight = c_get_daylight() + tzname_ptr = c_get_tzname() + tzname = rffi.charp2str(tzname_ptr[0]), rffi.charp2str(tzname_ptr[1]) + if _POSIX: YEAR = (365 * 24 + 6) * 3600 From pedronis at codespeak.net Fri Mar 20 15:35:09 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 15:35:09 +0100 (CET) Subject: [pypy-svn] r63142 - pypy/trunk/pypy/module/sys/test Message-ID: <20090320143509.AA7CF1684A8@codespeak.net> Author: pedronis Date: Fri Mar 20 15:35:09 2009 New Revision: 63142 Modified: pypy/trunk/pypy/module/sys/test/test_sysmodule.py Log: (iko, pedronis) tweaks to make two tests reasonable or skipped in the -A case Modified: pypy/trunk/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/trunk/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/trunk/pypy/module/sys/test/test_sysmodule.py Fri Mar 20 15:35:09 2009 @@ -1,5 +1,6 @@ # -*- coding: iso-8859-1 -*- import autopath +from pypy.conftest import option from py.test import raises from pypy.interpreter.gateway import app2interp_temp @@ -20,6 +21,10 @@ space.sys.get('__stdout__') class AppTestAppSysTests: + + def setup_class(cls): + cls.w_appdirect = cls.space.wrap(option.runappdirect) + def test_sys_in_modules(self): import sys modules = sys.modules @@ -70,19 +75,24 @@ else: raise AssertionError, "ZeroDivisionError not caught" -def app_test_io(): - import sys - assert isinstance(sys.stdout, file) - assert isinstance(sys.__stdout__, file) - assert isinstance(sys.stderr, file) - assert isinstance(sys.__stderr__, file) - assert isinstance(sys.stdin, file) - assert isinstance(sys.__stdin__, file) + def test_io(self): + import sys + assert isinstance(sys.__stdout__, file) + assert isinstance(sys.__stderr__, file) + assert isinstance(sys.__stdin__, file) + + if self.appdirect and not isinstance(sys.stdout, file): + return + + assert isinstance(sys.stdout, file) + assert isinstance(sys.stderr, file) + assert isinstance(sys.stdin, file) class AppTestSysModulePortedFromCPython: def setup_class(cls): init_globals_via_builtins_hack(cls.space) + cls.w_appdirect = cls.space.wrap(option.runappdirect) def test_original_displayhook(self): import __builtin__ @@ -247,12 +257,20 @@ # can't check more than the type, as the user might have changed it assert isinstance(sys.getdefaultencoding(), str) - def test_getdefaultencoding(self): + def test_setdefaultencoding(self): + if self.appdirect: + skip("not worth running appdirect") + encoding = sys.getdefaultencoding() - sys.setdefaultencoding("ascii") try: + sys.setdefaultencoding("ascii") assert sys.getdefaultencoding() == 'ascii' raises(UnicodeDecodeError, unicode, '\x80') + + sys.setdefaultencoding("latin-1") + assert sys.getdefaultencoding() == 'latin-1' + assert unicode('\x80') == u'\u0080' + finally: sys.setdefaultencoding(encoding) From pedronis at codespeak.net Fri Mar 20 16:24:54 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 20 Mar 2009 16:24:54 +0100 (CET) Subject: [pypy-svn] r63143 - pypy/trunk/pypy/module/gc Message-ID: <20090320152454.0B3F01684B9@codespeak.net> Author: pedronis Date: Fri Mar 20 16:24:53 2009 New Revision: 63143 Modified: pypy/trunk/pypy/module/gc/interp_gc.py Log: (iko, pedronis) perturb the obscure feature maybe for the better Modified: pypy/trunk/pypy/module/gc/interp_gc.py ============================================================================== --- pypy/trunk/pypy/module/gc/interp_gc.py (original) +++ pypy/trunk/pypy/module/gc/interp_gc.py Fri Mar 20 16:24:53 2009 @@ -43,9 +43,11 @@ lines = content.split("\n") for line in lines: if line.startswith("VmSize:"): + start = line.find(" ") # try to ignore tabs + assert start > 0 stop = len(line) - 3 assert stop > 0 - result = int(line[len("VmSize:"):stop].strip(" ")) * 1024 + result = int(line[start:stop].strip(" ")) * 1024 return space.wrap(result) raise OperationError(space.w_RuntimeError, space.wrap("can't estimate the heap size")) From afa at codespeak.net Fri Mar 20 17:25:19 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Mar 2009 17:25:19 +0100 (CET) Subject: [pypy-svn] r63146 - pypy/trunk/pypy/module/rctime Message-ID: <20090320162519.2D62E1684B4@codespeak.net> Author: afa Date: Fri Mar 20 17:25:17 2009 New Revision: 63146 Modified: pypy/trunk/pypy/module/rctime/__init__.py pypy/trunk/pypy/module/rctime/interp_time.py Log: Initialize time.timezone &co when pypy-c loads the module, *not* at translation time. Modified: pypy/trunk/pypy/module/rctime/__init__.py ============================================================================== --- pypy/trunk/pypy/module/rctime/__init__.py (original) +++ pypy/trunk/pypy/module/rctime/__init__.py Fri Mar 20 17:25:17 2009 @@ -1,15 +1,11 @@ from pypy.interpreter.mixedmodule import MixedModule +import os class Module(MixedModule): applevel_name = 'time' interpleveldefs = { - 'accept2dyear': 'interp_time.accept2dyear', - 'timezone': 'interp_time.timezone', - 'daylight': 'interp_time.daylight', - 'tzname': 'interp_time.tzname', - 'altzone': 'interp_time.altzone', 'time': 'interp_time.time', 'clock': 'interp_time.clock', 'ctime': 'interp_time.ctime', @@ -21,30 +17,20 @@ 'sleep' : 'interp_time.sleep', } - def buildloaders(cls): - from pypy.module.rctime import interp_time - import os - - if os.name == "posix": - Module.interpleveldefs['tzset'] = 'interp_time.tzset' - - # this machinery is needed to expose constants - # that have to be initialized one time only - - Module.interpleveldefs["accept2dyear"] = 'space.wrap(%r)' %\ - interp_time._init_accept2dyear() - - timezone, daylight, tzname, altzone = interp_time._init_timezone() - Module.interpleveldefs['timezone'] = 'space.wrap(%r)' % timezone - Module.interpleveldefs['daylight'] = 'space.wrap(%r)' % daylight - Module.interpleveldefs['tzname'] = \ - 'space.newtuple([space.wrap(%r), space.wrap(%r)])' % tuple(tzname) - Module.interpleveldefs['altzone'] = 'space.wrap(%r)' % altzone - super(Module, cls).buildloaders() - buildloaders = classmethod(buildloaders) + if os.name == "posix": + interpleveldefs['tzset'] = 'interp_time.tzset' appleveldefs = { 'struct_time': 'app_time.struct_time', '__doc__': 'app_time.__doc__', 'strptime': 'app_time.strptime', } + + def startup(self, space): + # this machinery is needed to expose constants + # that have to be initialized one time only + from pypy.module.rctime import interp_time + + interp_time._init_timezone(space) + interp_time._init_accept2dyear(space) + Modified: pypy/trunk/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/trunk/pypy/module/rctime/interp_time.py (original) +++ pypy/trunk/pypy/module/rctime/interp_time.py Fri Mar 20 17:25:17 2009 @@ -86,27 +86,34 @@ if _WIN: win_eci = ExternalCompilationInfo( includes = ["time.h"], - separate_module_sources = [ """ - long get_timezone() { return timezone; } - int get_daylight() { return daylight; } - char** get_tzname() { return tzname; } - """ - ], - export_symbols = ['_tzset', 'get_timezone', 'get_daylight', 'get_tzname'], + post_include_bits = ["long pypy_get_timezone();", + "int pypy_get_daylight();", + "char** pypy_get_tzname();"], + separate_module_sources = [""" + long pypy_get_timezone() { return timezone; } + int pypy_get_daylight() { return daylight; } + char** pypy_get_tzname() { return tzname; } + """], + export_symbols = [ + '_tzset', 'pypy_get_timezone', 'pypy_get_daylight', 'pypy_get_tzname'], ) # Ensure sure that we use _tzset() and timezone from the same C Runtime. c_tzset = external('_tzset', [], lltype.Void, win_eci) - c_get_timezone = external('get_timezone', [], rffi.LONG, win_eci) - c_get_daylight = external('get_daylight', [], rffi.INT, win_eci) - c_get_tzname = external('get_tzname', [], rffi.CCHARPP, win_eci) + c_get_timezone = external('pypy_get_timezone', [], rffi.LONG, win_eci) + c_get_daylight = external('pypy_get_daylight', [], rffi.INT, win_eci) + c_get_tzname = external('pypy_get_tzname', [], rffi.CCHARPP, win_eci) c_strftime = external('strftime', [rffi.CCHARP, rffi.SIZE_T, rffi.CCHARP, TM_P], rffi.SIZE_T) -def _init_accept2dyear(): - return (1, 0)[bool(os.getenv("PYTHONY2K"))] +def _init_accept2dyear(space): + if os.environ.get("PYTHONY2K"): + accept2dyear = 0 + else: + accept2dyear = 1 + _set_module_object(space, "accept2dyear", space.wrap(accept2dyear)) -def _init_timezone(): +def _init_timezone(space): timezone = daylight = altzone = 0 tzname = ["", ""] @@ -149,7 +156,11 @@ daylight = int(janzone != julyzone) tzname = [janname, julyname] - return timezone, daylight, tzname, altzone + _set_module_object(space, "timezone", space.wrap(timezone)) + _set_module_object(space, 'daylight', space.wrap(daylight)) + tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])] + _set_module_object(space, 'tzname', space.newtuple(tzname_w)) + _set_module_object(space, 'altzone', space.wrap(altzone)) def _get_error_msg(): errno = rposix.get_errno() @@ -402,12 +413,7 @@ c_tzset() # reset timezone, altzone, daylight and tzname - timezone, daylight, tzname, altzone = _init_timezone() - _set_module_object(space, "timezone", space.wrap(timezone)) - _set_module_object(space, 'daylight', space.wrap(daylight)) - tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])] - _set_module_object(space, 'tzname', space.newtuple(tzname_w)) - _set_module_object(space, 'altzone', space.wrap(altzone)) + timezone, daylight, tzname, altzone = _init_timezone(space) tzset.unwrap_spec = [ObjSpace] def strftime(space, format, w_tup=None): From fijal at codespeak.net Fri Mar 20 19:56:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 19:56:51 +0100 (CET) Subject: [pypy-svn] r63152 - in pypy/extradoc/talk/pycon2009: status vm-summit Message-ID: <20090320185651.9B731168487@codespeak.net> Author: fijal Date: Fri Mar 20 19:56:48 2009 New Revision: 63152 Added: pypy/extradoc/talk/pycon2009/status/ pypy/extradoc/talk/pycon2009/vm-summit/ Log: I'm too lazy to do anything, create directories From fijal at codespeak.net Fri Mar 20 20:59:13 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Mar 2009 20:59:13 +0100 (CET) Subject: [pypy-svn] r63156 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090320195913.D5AE61684C0@codespeak.net> Author: fijal Date: Fri Mar 20 20:59:11 2009 New Revision: 63156 Added: pypy/extradoc/talk/pycon2009/status/author.latex pypy/extradoc/talk/pycon2009/status/makepdf (contents, props changed) pypy/extradoc/talk/pycon2009/status/merlinux-logo.jpg (contents, props changed) pypy/extradoc/talk/pycon2009/status/pypy-logo.png (contents, props changed) pypy/extradoc/talk/pycon2009/status/status.txt (contents, props changed) pypy/extradoc/talk/pycon2009/status/stylesheet.latex pypy/extradoc/talk/pycon2009/status/title.latex Log: blindly import pycon uk 2008 talk Added: pypy/extradoc/talk/pycon2009/status/author.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/status/author.latex Fri Mar 20 20:59:11 2009 @@ -0,0 +1,8 @@ +\definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} + +\title[PyPy status talk]{PyPy status talk} +\author[H. Krekel, M. Fijalkowski]{Holger Krekel \and Maciej Fijalkowski\\ +Merlinux GmbH} + +\institute[PyCon UK 2008]{PyCon UK 2008 - Birmingham} +\date{September 13 2008} Added: pypy/extradoc/talk/pycon2009/status/makepdf ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/status/makepdf Fri Mar 20 20:59:11 2009 @@ -0,0 +1,14 @@ +#!/bin/bash + +# you can find rst2beamer.py here: +# http://codespeak.net/svn/user/antocuni/bin/rst2beamer.py + +# WARNING: to work, it needs this patch for docutils +# https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414 + +BASE=status +rst2beamer.py --stylesheet=stylesheet.latex --documentoptions=14pt $BASE.txt $BASE.latex || exit +sed 's/\\date{}/\\input{author.latex}/' -i $BASE.latex || exit +sed 's/\\maketitle/\\input{title.latex}/' -i $BASE.latex || exit +pdflatex $BASE.latex || exit + Added: pypy/extradoc/talk/pycon2009/status/merlinux-logo.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pycon2009/status/pypy-logo.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/status/status.txt Fri Mar 20 20:59:11 2009 @@ -0,0 +1,299 @@ +================================ +PyPy Python Interpreter status +================================ + +What this talk is about +======================= + +* a bit of motivation + +* tell what Python Interpreter can run today + +* what we are heading for with the 1.1 release + +* Questions and Answers + +PyPy - motivation +================================= + +* CPython is nice, but not flexible enough + +* IronPython, Jython - bound to the specific VM + +* Separate language specification from low-level details, + such as GC or platform to run + +* Psyco and Stackless Python hard to maintain + +PyPy - user motivation +======================= + +* One should never be forced to write anything in C + for performance reasons (with some exceptions: embedded + devices etc.) + +* Just-in-time compiler should make number-crunching + and static-enough code fast enough + +* One should never care about low-level details + +Brief history of PyPy +========================== + +* first sprint 2003, about 30 more by now +* CPython/Psyco/Jython/Stackless developers participating +* MIT-License, more sprints +* EU Research project 2004-2007 +* 2007-2008 - open source project +* some google sponsoring + +Getting Production ready +========================== + +* we worked a lot on running + existing applications on top of PyPy + +* sometimes requiring to change applications slightly + +* especially refcounting details tend to be a problem + +:: + + open('xxx', 'w').write('stuff') + +CTypes +====== + +* official way to have bindings to + external (C) libraries for PyPy + +* can handle i.e. pysqlite-ctypes, pyglet, pymunk or Sole Scion, + almost whatever.... + +* contribution to original ctypes + (better errno handling, bugfixes, tests...) + +* part of google sponsoring + +* note: 32bit and a bit slow + +CTypes configure +================ + +* our own small addition to general + CTypes usefulness + +* invokes C compiler for small details + +* can handle #defines, types, structure layout + etc. + +Sqlite +====== + +* part of cpython stdlib since 2.5 + +* we use Gerhard Haering's CTypes version + +* works reasonably well after some fixes + +Django +====== + +* we run unmodified Django 1.0 + +* only sqlite DB backend for now + +http://www.djangoproject.com + +http://code.djangoproject.com/wiki/DjangoAndPyPy + +Pylons +====== + +* worked almost out of the box once eggs + were working (1 day) + +* no SQLAlchemy yet, obscure problems + ahead + +* unmodified passes all tests + +* http://pylonshq.com/ + +Twisted & Nevow +=============== + +* twisted works (60/4500 tests failing) + +* nevow works + +* we don't support PyCrypto nor PyOpenSSL and we + won't anytime soon (if nobody contributes CTypes or rpython + versions) + +* http://twistedmatrix.com/ + + +Other software +============== + +* pure python should just work + +* BitTorrent + +* PyPy translation toolchain + +* py lib + +* sympy + +* various smaller things, templating engines + +Obscure details that people rely on +=================================== + +* non-string keys in __dict__ of types + +* exact naming of a list comprehension variable + +* relying on untested and undocumented private stuff + (zipimport._zip_directory_cache) + +* exact message matching in exception catching + code + +* refcounting details + +Transition to 2.5 +========================== + +* SOC project Bruno Gola + +* almost complete + +* missing more testing, stdlib porting + +Conclusion on Compatibility +============================ + +* lessons learned: There is no feature obscure enough for people + not to rely on it. + +* pypy-c interpreter probably the most compatible to CPython + +* main blocker for running apps will be missing external modules + +Speed - comparison with CPython +=============================== + +* we're something between 0.8-4x slower than + CPython on various benchmarks. + +* steady but slow progress + +* we hope for our JIT to be a huge leap ahead + +* pypy-c has fastest Interpreter startup + +Speed - JIT generator +===================== + +* not ready yet! + +* will be super fast + +* some prototypes, research ongoing + +* psyco is a nice proof that this approach + would work + +Memory - comparison with CPython +=================================== + +* PyPy has pluggable Garbage Collection + +* gcbench - 0.8 (because of our faster GCs) + +* better handling of unusual patterns + +* care needed with communication with C + +* GCs are semi-decent + + +Threading / Stackless +=================================== + +* currently using GIL, quite robust + +* free threading? "it's work" + +* pypy-c has software threading / stackless + +* added during translation + +Other backends +============== + +* PyPy-jvm runs! + +* more integration between pypy-cli and .NET + +* general speed improvements + +* both backends are progressing - very slowly though + +* contributors wanted! + +Sandboxing +========== + +* fully sandboxed python interpreter + +* all external calls to C goes via another + python process + +* special library for making custom + policies + +.. image:: sandboxed.png + :scale: 30 + :align: center + +pypy-c on small devices +=============================== + +- cross-compilation +- startup time +- security +- RAM usage +- share interpreter state across processes +- pypy approach a very good fit! + +1.1 release goals +=================================== + +- compatible to Python 2.5.2 +- well tested on win/linux 32 bit +- running major packages unmodified +- easy_install/distutils working +- help e.g. by writing ctypes modules + +Contact / Q&A +========================== + +holger krekel, Maciej Fijalkowski +at http://merlinux.eu + +PyPy: http://codespeak.net/pypy + +Blog: http://morepypy.blogspot.com + +.. raw:: latex + + \begin{figure} + \includegraphics[width=64px,height=64px]{merlinux-logo.jpg} + \qquad + \includegraphics[width=80px]{../../img/py-web.png} + \end{figure} Added: pypy/extradoc/talk/pycon2009/status/stylesheet.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/status/stylesheet.latex Fri Mar 20 20:59:11 2009 @@ -0,0 +1,10 @@ +\usetheme{Boadilla} +\setbeamercovered{transparent} +\setbeamertemplate{navigation symbols}{} + +\definecolor{darkgreen}{rgb}{0, 0.5, 0.0} +\newcommand{\docutilsrolegreen}[1]{\color{darkgreen}#1\normalcolor} +\newcommand{\docutilsrolered}[1]{\color{red}#1\normalcolor} + +\newcommand{\green}[1]{\color{darkgreen}#1\normalcolor} +\newcommand{\red}[1]{\color{red}#1\normalcolor} Added: pypy/extradoc/talk/pycon2009/status/title.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/status/title.latex Fri Mar 20 20:59:11 2009 @@ -0,0 +1,7 @@ +\begin{titlepage} +\begin{figure}[h] +\includegraphics[width=64px,height=64px]{merlinux-logo.jpg} +\qquad +\includegraphics[width=80px]{../../img/py-web.png} +\end{figure} +\end{titlepage} From fijal at codespeak.net Sat Mar 21 11:51:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 21 Mar 2009 11:51:03 +0100 (CET) Subject: [pypy-svn] r63169 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090321105103.A5F7D1684BF@codespeak.net> Author: fijal Date: Sat Mar 21 11:51:00 2009 New Revision: 63169 Added: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (contents, props changed) Log: four slides that I want to present Added: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Sat Mar 21 11:51:00 2009 @@ -0,0 +1,12 @@ + +Multi target picture +==================== + +RPython - two words +=================== + +Garbage collector source code - it's all Python +=============================================== + +JIT - simple interpreter and run on PyPy +======================================== From hpk at codespeak.net Sat Mar 21 12:17:39 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Mar 2009 12:17:39 +0100 (CET) Subject: [pypy-svn] r63170 - pypy/trunk/pypy/translator/js/test Message-ID: <20090321111739.ED758168025@codespeak.net> Author: hpk Date: Sat Mar 21 12:17:36 2009 New Revision: 63170 Modified: pypy/trunk/pypy/translator/js/test/runtest.py Log: those two options don't exist currently i think Modified: pypy/trunk/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/trunk/pypy/translator/js/test/runtest.py (original) +++ pypy/trunk/pypy/translator/js/test/runtest.py Sat Mar 21 12:17:36 2009 @@ -12,8 +12,8 @@ from pypy.rpython.llinterp import LLException log = log.runtest -use_browsertest = py.test.config.option.browser -use_tg = py.test.config.option.tg +use_browsertest = False # XXX py.test currently has no py.test.config.option.browser +use_tg = False # XXX py.test.config.option.tg use_view = py.test.config.option.view port = 8080 From hpk at codespeak.net Sat Mar 21 13:05:16 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Mar 2009 13:05:16 +0100 (CET) Subject: [pypy-svn] r63172 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090321120516.A1FF61684C2@codespeak.net> Author: hpk Date: Sat Mar 21 13:05:14 2009 New Revision: 63172 Added: pypy/extradoc/talk/pycon2009/vm-summit/mario.png - copied unchanged from r63171, pypy/extradoc/talk/openbossa2009/pypy-mobile/mario.png pypy/extradoc/talk/pycon2009/vm-summit/pypy-multitarget.png - copied unchanged from r63171, pypy/extradoc/talk/openbossa2009/pypy-mobile/pypy-multitarget.png Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: a bit of meat, some mods Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Sat Mar 21 13:05:14 2009 @@ -1,12 +1,62 @@ -Multi target picture -==================== +PyPy - Motivation +================================= -RPython - two words -=================== +* **high level Python specification** (in RPyhton) -Garbage collector source code - it's all Python -=============================================== +* layer GCs, JIT, Stackless atop the spec -JIT - simple interpreter and run on PyPy +* **generate** efficient interpreters for targets + + +.. image:: pypy-multitarget.png + :scale: 50 + :align: center + +RPython - two words +========================== + +- RPython is a subset of Python, used in a statical way +- whole-program type-inference +- GCs, threading, stackless applied as graph transforms +- you can implement other languages or VMs in RPython + + +Virtual Machine translation! +========================================== + +.. image:: mario.png + :scale: 100 + :align: center + +Next-generation Garbage Collection +==================================== + +- currently: naive Mark&Compact (600 lines of code) +- port/implement newer techniques (e.g. deferred refcounting) +- even more compact GC headers +- malloc-directed inlining +- maximize shared interpreter state +- co-operate with kernel in swapping/collect situations + +PyPy's GC framework +=================================== + +- program your GC in Python +- test your GC in Python +- get Python tracebacks instead of segfaults +- once ready, translate with Python Interpreter + + +Generating JIT Compilers ======================================== + + +Current Challenges +====================== + +* generate a working JIT-compiling Python Interpreter +* PyPy 1.1 release +* more extension modules, C++ bindings? +* split into multiple projects + From antocuni at codespeak.net Sat Mar 21 13:27:37 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 21 Mar 2009 13:27:37 +0100 (CET) Subject: [pypy-svn] r63173 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090321122737.7E05F1683EE@codespeak.net> Author: antocuni Date: Sat Mar 21 13:27:35 2009 New Revision: 63173 Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: a comment and (I think) a typo Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Sat Mar 21 13:27:35 2009 @@ -8,6 +8,8 @@ * **generate** efficient interpreters for targets +.. (antocuni) I would say "generate efficient VMs", not "interpreters" + .. image:: pypy-multitarget.png :scale: 50 @@ -16,7 +18,7 @@ RPython - two words ========================== -- RPython is a subset of Python, used in a statical way +- RPython is a subset of Python, used in a static way - whole-program type-inference - GCs, threading, stackless applied as graph transforms - you can implement other languages or VMs in RPython From fijal at codespeak.net Sat Mar 21 14:09:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 21 Mar 2009 14:09:28 +0100 (CET) Subject: [pypy-svn] r63175 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090321130928.0B4AF16849E@codespeak.net> Author: fijal Date: Sat Mar 21 14:09:27 2009 New Revision: 63175 Added: pypy/extradoc/talk/pycon2009/vm-summit/picture.png (contents, props changed) pypy/extradoc/talk/pycon2009/vm-summit/picture.svg Log: add a picture Added: pypy/extradoc/talk/pycon2009/vm-summit/picture.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pycon2009/vm-summit/picture.svg ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/vm-summit/picture.svg Sat Mar 21 14:09:27 2009 @@ -0,0 +1,1181 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Python specification + + + + + + + + + + + + + + + + + + + Platform choic + e + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Garbage collection + + + + + strategy + + + + + + + + + C + + + + + + + + + LLVM + + + + + + + + + JVM + + + + + + + + + + + + + + + + + + + Just in time compiler generation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Python on JVM with JIT + + + + + + + + + + + + + + + + + + + + + + + JavaScript running on + + + + + Maemo with Mark + & + + + + + + Compact GC + + + + + + + + + + + + + + + + + + + + + + + Python with stackless and + + + + + JIT on top of C/POSIX + + + + + + + + + + + + + + + + + + + + + + + + + + + Dynamic language X just the + + + + + way you like it + + + + + + + + + + + + + + + + + + + JavaScript specification + + + + + + + + + + + + + + + + + + + + + + + + + KitchenSink implementation + + + + + + + + + + + From fijal at codespeak.net Sat Mar 21 14:48:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 21 Mar 2009 14:48:01 +0100 (CET) Subject: [pypy-svn] r63176 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090321134801.3516C1684C1@codespeak.net> Author: fijal Date: Sat Mar 21 14:47:59 2009 New Revision: 63176 Modified: pypy/extradoc/talk/pycon2009/vm-summit/picture.svg pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: the way how I see it Modified: pypy/extradoc/talk/pycon2009/vm-summit/picture.svg ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/picture.svg (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/picture.svg Sat Mar 21 14:47:59 2009 @@ -14,7 +14,10 @@ sodipodi:version="0.32" inkscape:version="0.46" sodipodi:docname="picture.svg" - inkscape:output_extension="org.inkscape.output.svg.inkscape"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/fijal/lang/python/pypy-dist/extradoc/talk/pycon2009/vm-summit/picture.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Sat Mar 21 14:47:59 2009 @@ -2,63 +2,49 @@ PyPy - Motivation ================================= -* **high level Python specification** (in RPyhton) +.. image:: picture.png + :scale: 50 + :align: center -* layer GCs, JIT, Stackless atop the spec +High level specification - how exactly +======================================= -* **generate** efficient interpreters for targets +* in our opinion specification that cannot be run + is not worth it -.. (antocuni) I would say "generate efficient VMs", not "interpreters" +* Python is high level enough +* We derived a static subset of Python that can be + efficiently compiled, called RPython -.. image:: pypy-multitarget.png - :scale: 50 - :align: center +XXX show mario -RPython - two words -========================== +Garbage Collection framework +==================================== -- RPython is a subset of Python, used in a static way -- whole-program type-inference -- GCs, threading, stackless applied as graph transforms -- you can implement other languages or VMs in RPython +* Written in Python +* We introduced a bunch of low-level primitives -Virtual Machine translation! -========================================== +* We can test a GC on top of Python (running specification) -.. image:: mario.png - :scale: 100 - :align: center +* ... and translate to a target -Next-generation Garbage Collection -==================================== +* Completely interpreter-agnostic -- currently: naive Mark&Compact (600 lines of code) -- port/implement newer techniques (e.g. deferred refcounting) -- even more compact GC headers -- malloc-directed inlining -- maximize shared interpreter state -- co-operate with kernel in swapping/collect situations - -PyPy's GC framework -=================================== - -- program your GC in Python -- test your GC in Python -- get Python tracebacks instead of segfaults -- once ready, translate with Python Interpreter +XXX show a piece of code in GC Generating JIT Compilers ======================================== +* We apply JIT generator to specification -Current Challenges -====================== +* A couple of manual hints is required -* generate a working JIT-compiling Python Interpreter -* PyPy 1.1 release -* more extension modules, C++ bindings? -* split into multiple projects +* We can try on top of Python as well + +Challenges +====================== +XXX out of time I suppose From hpk at codespeak.net Sat Mar 21 16:15:29 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 21 Mar 2009 16:15:29 +0100 (CET) Subject: [pypy-svn] r63189 - in pypy/trunk: dotviewer lib-python pypy Message-ID: <20090321151529.9B322168487@codespeak.net> Author: hpk Date: Sat Mar 21 16:15:24 2009 New Revision: 63189 Modified: pypy/trunk/dotviewer/conftest.py pypy/trunk/lib-python/conftest.py pypy/trunk/pypy/conftest.py Log: * specifying resultlog plugin as a dependency * fixing some dist-related settings Modified: pypy/trunk/dotviewer/conftest.py ============================================================================== --- pypy/trunk/dotviewer/conftest.py (original) +++ pypy/trunk/dotviewer/conftest.py Sat Mar 21 16:15:24 2009 @@ -1,7 +1,8 @@ import py -Option = py.test.config.Option -option = py.test.config.addoptions("dotviewer options", - Option('--pygame', action="store_true", dest="pygame", default=False, - help="allow interactive tests using Pygame"), - ) +class ConftestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("dotviever") + group.addoption('--pygame', action="store_true", + dest="pygame", default=False, + help="allow interactive tests using Pygame") Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Sat Mar 21 16:15:24 2009 @@ -21,7 +21,8 @@ from pypy.tool.pytest.confpath import pypydir, libpythondir, \ regrtestdir, modregrtestdir, testresultdir -dist_rsync_roots = ['.', '../pypy', '../py'] +pytest_plugins = "resultlog", +rsyncdirs = ['.', '../pypy'] # # Interfacing/Integrating with py.test's collection process Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Sat Mar 21 16:15:24 2009 @@ -10,11 +10,11 @@ rootdir = py.magic.autopath().dirpath() -# distributed testing settings -dist_rsync_roots = ['.', '../lib-python', '../py', '../demo'] -dist_rsync_ignore = ['_cache'] - -# +# pytest settings +pytest_plugins = "resultlog", +rsyncdirs = ['.', '../lib-python', '../demo'] +rsyncignore = ['_cache'] + # PyPy's command line extra options (these are added # to py.test's standard options) # From arigo at codespeak.net Sun Mar 22 10:45:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 22 Mar 2009 10:45:48 +0100 (CET) Subject: [pypy-svn] r63204 - pypy/branch/pyjitpl5-simplify Message-ID: <20090322094548.66DC7168433@codespeak.net> Author: arigo Date: Sun Mar 22 10:45:47 2009 New Revision: 63204 Added: pypy/branch/pyjitpl5-simplify/ - copied from r63203, pypy/branch/pyjitpl5/ Log: A branch in which to try to simplify, notably, the backend interface. From fijal at codespeak.net Sun Mar 22 12:04:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 22 Mar 2009 12:04:29 +0100 (CET) Subject: [pypy-svn] r63205 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090322110429.1C7DF168427@codespeak.net> Author: fijal Date: Sun Mar 22 12:04:27 2009 New Revision: 63205 Modified: pypy/extradoc/talk/pycon2009/vm-summit/picture.png pypy/extradoc/talk/pycon2009/vm-summit/picture.svg Log: shuffle stuff around Modified: pypy/extradoc/talk/pycon2009/vm-summit/picture.png ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon2009/vm-summit/picture.svg ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/picture.svg (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/picture.svg Sun Mar 22 12:04:27 2009 @@ -9,17 +9,14 @@ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="707" - height="743" + height="806" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" sodipodi:docname="picture.svg" - inkscape:output_extension="org.inkscape.output.svg.inkscape" - inkscape:export-filename="/home/fijal/lang/python/pypy-dist/extradoc/talk/pycon2009/vm-summit/picture.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + id="metadata448"> @@ -30,8 +27,8 @@ - - - - + inkscape:vp_z="707 : 403 : 1" + inkscape:persp3d-origin="353.5 : 268.66667 : 1" + id="perspective450" /> - + gradientUnits="userSpaceOnUse" /> + height="805" + id="rect6" /> @@ -143,7 +117,7 @@ @@ -223,19 +197,14 @@ font-size="12" font-family="Arial" fill="#000000" - id="tspan52">Platform choic - e + id="tspan52">Platform choice + id="g54"> + id="line56" /> + id="line58" /> + id="line60" /> + id="g62" /> + id="g64"> + id="line66" /> + id="line68" /> + transform="translate(0.0,36.0)" + id="g70" /> + transform="translate(279.0,241.0)" + id="g72"> + id="line74" /> + id="line76" /> + transform="translate(0.0,34.5)" + id="g78" /> + id="g80"> + id="line82" /> + id="line84" /> + transform="translate(0.0,33.5)" + id="g86" /> + transform="translate(196.5,395.0) rotate(0 62.5 20.0)" + id="g88"> + id="defs90"> + id="stop93" /> + id="stop95" /> + id="g97"> + id="path99" /> + id="path101" /> + id="g103"> + id="text105"> + id="tspan107"> Garbage collection + id="tspan109">Garbage collection + id="text111"> + id="tspan113"> strategy + id="tspan115"> strategy + id="g117"> + id="g119"> + id="text121"> + id="tspan123"> C + id="tspan125">C + transform="translate(226.5,262.0) rotate(0 77.5 12.0)" + id="g127"> + id="g129"> + id="text131"> + id="tspan133"> LLVM + id="tspan135">LLVM + id="g137"> + id="g139"> + id="text141"> + id="tspan143"> JVM + id="tspan145">JVM + transform="translate(176.0,295.5) rotate(0 125.0 22.5)" + id="g147"> + id="defs149"> + id="stop152" /> + id="stop154" /> + id="g156"> + id="path158" /> + id="path160" /> + id="g162"> + id="text164"> + id="tspan166"> Just in time compiler generation + id="tspan168">Just in time compiler generation + transform="translate(232.0,338.0)" + id="g170"> + id="line172" /> + id="g174" /> + transform="translate(258.0,339.0)" + id="g176"> + id="line178" /> + id="g180" /> + transform="translate(294.0,342.0)" + id="g182"> + id="line184" /> + id="g186" /> + transform="translate(361.0,342.0)" + id="g188"> + id="line190" /> + transform="translate(0.0,82.0)" + id="g192" /> + transform="translate(25.5,643.0) rotate(0 72.5 20.0)" + id="g194"> + id="defs196"> + id="stop199" /> + id="stop201" /> + id="g203"> + id="path205" /> + id="path207" /> + id="g209"> + id="text211"> + id="tspan213"> Python on JVM with JIT + id="tspan215">Python on JVM with JIT + transform="translate(98.05000000000001,643.05)" + id="g217"> + id="line219" /> + transform="translate(35.53577294715256,-70.96422705284745)" + id="g221" /> + transform="translate(171.0,585.0) rotate(0 80.0 25.0)" + id="g223"> + id="defs225"> + id="stop229" /> + id="stop231" /> + id="g233"> + id="path235" /> + style="fill:url(#linearGradient3607);fill-opacity:1" + id="path237" /> + id="g239"> + id="text241"> + id="tspan243"> JavaScript running on + id="tspan245">JavaScript running on + id="text247"> + id="tspan249"> Maemo with Mark + id="tspan251"> Maemo with Mark & + id="tspan253">& + id="tspan255" /> + id="text257"> + id="tspan259"> Compact GC + id="tspan261"> Compact GC + transform="translate(251.0,585.0)" + id="g263"> + id="line265" /> + transform="translate(-9.1476049163841,-35.0)" + id="g267" /> + transform="translate(306.0,665.0) rotate(0 80.0 20.0)" + id="g269"> + id="defs271"> + id="stop274" /> + id="stop276" /> + id="g278"> + id="path280" /> + id="path282" /> + id="g284"> + id="text286"> + id="tspan288"> Python with stackless and + id="tspan290">Python with stackless and + id="text292"> + id="tspan294"> JIT on top of C/POSIX + id="tspan296"> JIT on top of C/POSIX + transform="translate(386.0,665.0)" + id="g298"> + id="line300" /> + transform="translate(-32.89317200659442,-75.0)" + id="g302" /> + transform="translate(396.95,503.04999999999995)" + id="g304"> + id="line306" /> + transform="translate(44.6598071527549,53.725)" + id="g308" /> + transform="translate(401.5,600.5) rotate(0 87.5 22.5)" + id="g310"> + id="defs312"> + id="stop315" /> + id="stop317" /> + id="g319"> + id="path321" /> + id="path323" /> + id="g325"> + id="text327"> + id="tspan329"> Dynamic language X just the + id="tspan331">Dynamic language X just the + id="text333"> + id="tspan335"> way you like it + id="tspan337"> way you like it + id="g339"> + id="defs341"> + id="stop345" /> + id="stop347" /> + id="g349"> + id="path351" /> + style="fill:url(#linearGradient3599);fill-opacity:1" + id="path353" /> + id="g355"> + id="text357"> + id="tspan359"> JavaScript specification + id="tspan361">JavaScript specification + id="g363"> + id="line365" /> + id="line367" /> + id="line369" /> + id="g371" /> + id="g373"> + id="defs375"> + id="stop378" /> + offset="100%" + id="stop380" /> + id="g382"> + id="path384" /> + style="fill:url(#g25)" + id="path386" /> + id="g388"> + id="text390"> + id="tspan392"> KitchenSink implementation + id="tspan394">KitchenSink implementation + id="g396"> + id="line398" /> + id="line400" /> + id="line402" /> + id="g404" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fijal at codespeak.net Sun Mar 22 13:57:25 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 22 Mar 2009 13:57:25 +0100 (CET) Subject: [pypy-svn] r63206 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090322125725.E499D16844B@codespeak.net> Author: fijal Date: Sun Mar 22 13:57:23 2009 New Revision: 63206 Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: Update Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Sun Mar 22 13:57:23 2009 @@ -6,12 +6,9 @@ :scale: 50 :align: center -High level specification - how exactly +High level implementation - how exactly ======================================= -* in our opinion specification that cannot be run - is not worth it - * Python is high level enough * We derived a static subset of Python that can be From arigo at codespeak.net Sun Mar 22 15:40:54 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 22 Mar 2009 15:40:54 +0100 (CET) Subject: [pypy-svn] r63207 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090322144054.E6FDD1683FA@codespeak.net> Author: arigo Date: Sun Mar 22 15:40:52 2009 New Revision: 63207 Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: Add a sentence. Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Sun Mar 22 15:40:52 2009 @@ -9,6 +9,8 @@ High level implementation - how exactly ======================================= +* Raise the level at which you implement programming languages + * Python is high level enough * We derived a static subset of Python that can be From arigo at codespeak.net Mon Mar 23 13:29:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 13:29:13 +0100 (CET) Subject: [pypy-svn] r63225 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp Message-ID: <20090323122913.61E2B16846C@codespeak.net> Author: arigo Date: Mon Mar 23 13:29:10 2009 New Revision: 63225 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Log: Intermediate checkin: introduce the new model of operations and port graphpage.py to display it. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py Mon Mar 23 13:29:10 2009 @@ -125,14 +125,20 @@ # ____________________________________________________________ -class LoopOrBridge(object): +class CompiledLoop(object): def __init__(self): self.operations = [] def __repr__(self): - lines = ['\t' + repr(op) for op in self.operations] - lines.insert(0, 'LoopOrBridge:') - return '\n'.join(lines) + lines = [] + self.as_text(lines, 1) + return 'CompiledLoop:\n%s' % '\n'.join(lines) + + def as_text(self, lines, indent): + for op in self.operations: + lines.append('\t'*indent + repr(op)) + if op.is_guard(): + op.subloop.as_text(lines, indent+1) class Operation(object): def __init__(self, opnum): @@ -156,6 +162,9 @@ except KeyError: return '<%d>' % self.opnum + def is_guard(self): + return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST + def repr0(x): if isinstance(x, list): return '[' + ', '.join(repr0(y) for y in x) + ']' @@ -228,7 +237,7 @@ def compile_start(): del _variables[:] - return _to_opaque(LoopOrBridge()) + return _to_opaque(CompiledLoop()) def compile_start_int_var(loop): loop = _from_opaque(loop) @@ -299,6 +308,7 @@ return r def compile_add_jump_target(loop, loop_target, loop_target_index): + xxx loop = _from_opaque(loop) loop_target = _from_opaque(loop_target) op = loop.operations[-1] @@ -310,23 +320,12 @@ else: log.info("compiling new bridge") -def compile_add_failnum(loop, failnum): - loop = _from_opaque(loop) - op = loop.operations[-1] - op.failnum = failnum - -def compile_add_livebox(loop, intvar): +def compile_suboperations(loop): loop = _from_opaque(loop) op = loop.operations[-1] - op.livevars.append(_variables[intvar]) - -def compile_from_guard(loop, guard_loop, guard_opindex): - loop = _from_opaque(loop) - guard_loop = _from_opaque(guard_loop) - op = guard_loop.operations[guard_opindex] - assert rop._GUARD_FIRST <= op.opnum <= rop._GUARD_LAST - op.jump_target = loop - op.jump_target_index = 0 + assert op.is_guard() + op.subloop = CompiledLoop() + return _to_opaque(op.subloop) # ------------------------------ @@ -936,19 +935,19 @@ return hop.genop('direct_call', [cfunc] + args_v, hop.r_result) -LOOPORBRIDGE = lltype.Ptr(lltype.OpaqueType("LoopOrBridge")) +COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop")) FRAME = lltype.Ptr(lltype.OpaqueType("Frame")) MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast")) -_TO_OPAQUE[LoopOrBridge] = LOOPORBRIDGE.TO +_TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO _TO_OPAQUE[Frame] = FRAME.TO _TO_OPAQUE[MemoCast] = MEMOCAST.TO -s_LoopOrBridge = annmodel.SomePtr(LOOPORBRIDGE) +s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP) s_Frame = annmodel.SomePtr(FRAME) s_MemoCast = annmodel.SomePtr(MEMOCAST) -setannotation(compile_start, s_LoopOrBridge) +setannotation(compile_start, s_CompiledLoop) setannotation(compile_start_int_var, annmodel.SomeInteger()) setannotation(compile_start_ptr_var, annmodel.SomeInteger()) setannotation(compile_add, annmodel.s_None) @@ -959,9 +958,6 @@ setannotation(compile_add_int_result, annmodel.SomeInteger()) setannotation(compile_add_ptr_result, annmodel.SomeInteger()) setannotation(compile_add_jump_target, annmodel.s_None) -setannotation(compile_add_failnum, annmodel.s_None) -setannotation(compile_from_guard, annmodel.s_None) -setannotation(compile_add_livebox, annmodel.s_None) setannotation(new_frame, s_Frame) setannotation(frame_clear, annmodel.s_None) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Mon Mar 23 13:29:10 2009 @@ -57,31 +57,25 @@ annmixlevel=None): self.rtyper = rtyper self.translate_support_code = translate_support_code - self.jumptarget2loop = {} - self.guard_ops = [] - self.compiled_single_ops = {} self.stats = stats or MiniStats() self.stats.exec_counters = {} self.stats.exec_jumps = 0 self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats - llimpl._rtyper = self.rtyper llimpl._llinterp = LLInterpreter(self.rtyper) if translate_support_code: self.mixlevelann = annmixlevel self.fielddescrof_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr') - def set_meta_interp(self, metainterp): - self.metainterp = metainterp # to handle guard failures - - def compile_operations(self, operations, from_guard=None): + def compile_operations(self, loop): """In a real assembler backend, this should assemble the given list of operations. Here we just generate a similar LoopOrBridge instance. The code here is RPython, whereas the code in llimpl is not. """ - + operations = loop.operations c = llimpl.compile_start() + loop._compiled_version = c var2index = {} for i in range(len(operations[0].args)): box = operations[0].args[i] @@ -89,18 +83,12 @@ var2index[box] = llimpl.compile_start_int_var(c) elif isinstance(box, history.BoxPtr): var2index[box] = llimpl.compile_start_ptr_var(c) - elif isinstance(box, history.Const): - pass # accept anything and ignore it else: raise Exception("box is: %r" % (box,)) - j = 0 - for i in range(len(operations)): - op = operations[i] - #if op.opname[0] == '#': - # continue - op._compiled = c - op._opindex = j - j += 1 + self._compile_branch(c, operations[1:], var2index) + + def _compile_branch(self, c, operations, var2index): + for op in operations: llimpl.compile_add(c, op.opnum) if op.descr is not None: llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type) @@ -116,6 +104,9 @@ else: raise Exception("%s args contain: %r" % (op.getopname(), x)) + if op.is_guard(): + c2 = llimpl.compile_suboperations(c) + self._compile_branch(c2, op.suboperations, var2index.copy()) x = op.result if x is not None: if isinstance(x, history.BoxInt): @@ -125,31 +116,14 @@ else: raise Exception("%s.result contain: %r" % (op.getopname(), x)) - if op.jump_target is not None: - loop_target, loop_target_index = \ - self.jumptarget2loop[op.jump_target] - llimpl.compile_add_jump_target(c, loop_target, - loop_target_index) - if op.is_guard(): - llimpl.compile_add_failnum(c, len(self.guard_ops)) - self.guard_ops.append(op) - for box in op.liveboxes: - assert isinstance(box, history.Box) - llimpl.compile_add_livebox(c, var2index[box]) - if op.opnum == rop.MERGE_POINT: - self.jumptarget2loop[op] = c, i - if from_guard is not None: - llimpl.compile_from_guard(c, from_guard._compiled, - from_guard._opindex) - - def execute_operations_in_new_frame(self, name, operations, valueboxes): - """Perform a 'call' to the given merge point, i.e. create - a new CPU frame and use it to execute the operations that - follow the merge point. + llimpl.compile_add_jump_target(c, op.target_jump._compiled_version) + + def execute_operations(self, loop, valueboxes): + """Calls the assembler generated for the given loop. """ frame = llimpl.new_frame(self.memo_cast) - merge_point = operations[0] - llimpl.frame_clear(frame, merge_point._compiled, merge_point._opindex) + # setup the frame + llimpl.frame_clear(frame, loop._compiled_version) for box in valueboxes: if isinstance(box, history.BoxInt): llimpl.frame_add_int(frame, box.value) @@ -161,56 +135,15 @@ llimpl.frame_add_ptr(frame, box.value) else: raise Exception("bad box in valueboxes: %r" % (box,)) - return self.loop(frame) - - def loop(self, frame): - """Execute a loop. When the loop fails, ask the metainterp for more. - """ - while True: - guard_index = llimpl.frame_execute(frame) - guard_op = self.guard_ops[guard_index] - assert isinstance(lltype.typeOf(frame), lltype.Ptr) - gf = GuardFailed(frame, guard_op) - self.metainterp.handle_guard_failure(gf) - if gf.returns: - return gf.retbox - - def getvaluebox(self, frame, guard_op, argindex): - box = guard_op.liveboxes[argindex] - if isinstance(box, history.BoxInt): - value = llimpl.frame_int_getvalue(frame, argindex) - return history.BoxInt(value) - elif isinstance(box, history.BoxPtr): - value = llimpl.frame_ptr_getvalue(frame, argindex) - return history.BoxPtr(value) - else: - raise AssertionError('getvalue: box = %s' % (box,)) - - def setvaluebox(self, frame, guard_op, argindex, valuebox): - if isinstance(valuebox, history.BoxInt): - llimpl.frame_int_setvalue(frame, argindex, valuebox.value) - elif isinstance(valuebox, history.BoxPtr): - llimpl.frame_ptr_setvalue(frame, argindex, valuebox.value) - elif isinstance(valuebox, history.ConstInt): - llimpl.frame_int_setvalue(frame, argindex, valuebox.value) - elif isinstance(valuebox, history.ConstPtr): - llimpl.frame_ptr_setvalue(frame, argindex, valuebox.value) - elif isinstance(valuebox, history.ConstAddr): - llimpl.frame_int_setvalue(frame, argindex, valuebox.getint()) + # run the loop + result = llimpl.frame_execute(frame) + # get the exception to raise and really raise it, if any + exception_addr = llimpl.frame_get_exception(frame) + if exception_addr: + exc_value_gcref = llimpl.frame_get_exc_value(frame) + xxxx else: - raise AssertionError('setvalue: valuebox = %s' % (valuebox,)) - - def get_exception(self): - return self.cast_adr_to_int(llimpl.get_exception()) - - def get_exc_value(self): - return llimpl.get_exc_value() - - def clear_exception(self): - llimpl.clear_exception() - - def set_overflow_error(self): - llimpl.set_overflow_error() + return result @staticmethod def sizeof(S): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 13:29:10 2009 @@ -5,7 +5,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.history import Graph, log, Box +from pypy.jit.metainterp.history import Loop, log, Box from pypy.jit.metainterp import optimize @@ -52,11 +52,11 @@ loop = compile_fresh_loop(metainterp, loop, old_loops, endliveboxes) except Exception, exc: - show_loop(metainterp, loop, loop.operations[0], exc) + show_loop(metainterp, loop, error=exc) raise else: if loop == orgloop: - show_loop(metainterp, loop, loop.operations[0], None) + show_loop(metainterp, loop) else: log.info("reusing loop at %r" % (loop,)) except optimize.CancelInefficientLoop: @@ -71,11 +71,11 @@ bridge = compile_fresh_bridge(metainterp, bridge, old_loops, endliveboxes) except Exception, exc: - show_loop(metainterp, bridge, None, exc) + show_loop(metainterp, bridge, error=exc) raise else: if bridge == orgbridge: - show_loop(metainterp, bridge, None, None) + show_loop(metainterp, bridge) elif bridge is not None: log.info("reusing bridge at %r" % (bridge,)) else: @@ -86,7 +86,7 @@ bridge.check_consistency() return bridge -def show_loop(metainterp, loop, mp=None, error=None): +def show_loop(metainterp, loop, error=None): # debugging if option.view: if error: @@ -95,39 +95,22 @@ errmsg += ': ' + str(error) else: errmsg = None - loop.show(in_stats=metainterp.stats, errmsg=errmsg, - highlightops=find_highlight_ops(metainterp.history, mp)) - -def find_highlight_ops(history, mp=None): - result = {} - for op in history.operations[::-1]: - result[op] = True - if op is mp: - break - return result + loop.show(errmsg=errmsg) def create_empty_loop(metainterp): if we_are_translated(): name = 'Loop' else: name = 'Loop #%d' % len(metainterp.stats.loops) - graph = Graph(name, '#f084c2') - return graph - -def create_empty_bridge(metainterp): - if we_are_translated(): - name = 'Bridge' - else: - name = 'Bridge #%d' % len(metainterp.stats.loops) - graph = Graph(name, '#84f0c2') - return graph + return Loop(name) # ____________________________________________________________ def compile_fresh_loop(metainterp, loop, old_loops, endliveboxes): history = metainterp.history + loop.inputargs = history.inputargs loop.operations = history.operations - close_loop(loop, loop.operations[0], endliveboxes) + close_loop(loop, endliveboxes) old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, metainterp.cpu) if old_loop is not None: @@ -136,17 +119,16 @@ old_loops.append(loop) return loop -def close_loop(loop, targetmp, endliveboxes): - assert targetmp.opnum == rop.MERGE_POINT +def close_loop(loop, endliveboxes): op = ResOperation(rop.JUMP, endliveboxes, None) - op.jump_target = targetmp + op.jump_target = loop loop.operations.append(op) -def finish_loop_or_bridge(metainterp, loop, targetmp, guard_op=None): +def finish_loop_or_bridge(metainterp, loop, targetmp): assert targetmp.opnum == rop.MERGE_POINT assert loop.operations[-1].opnum == rop.JUMP loop.operations[-1].jump_target = targetmp - metainterp.cpu.compile_operations(loop.operations, guard_op) + metainterp.cpu.compile_operations(loop) metainterp.stats.loops.append(loop) # ____________________________________________________________ Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py Mon Mar 23 13:29:10 2009 @@ -192,7 +192,7 @@ execute = [None] * (rop._LAST+1) for key, value in rop.__dict__.items(): if not key.startswith('_'): - if (rop._SPECIAL_FIRST <= value <= rop._SPECIAL_LAST or + if (rop._FINAL_FIRST <= value <= rop._FINAL_LAST or rop._GUARD_FIRST <= value <= rop._GUARD_LAST): continue if execute[value] is not None: Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py Mon Mar 23 13:29:10 2009 @@ -4,10 +4,28 @@ from pypy.jit.metainterp.history import Box +class SubGraph: + def __init__(self, suboperations): + self.suboperations = suboperations + def get_operations(self): + return self.suboperations + def get_display_text(self): + return None + +def display_loops(loops, errmsg=None): + graphs = loops[:] + for graph in graphs: + for op in graph.get_operations(): + if op.is_guard(): + graphs.append(SubGraph(op.suboperations)) + graphpage = ResOpGraphPage(graphs, errmsg) + graphpage.display() + + class ResOpGraphPage(GraphPage): - def compute(self, graphs, errmsg=None, highlightops={}): - resopgen = ResOpGen(highlightops) + def compute(self, graphs, errmsg=None): + resopgen = ResOpGen() for graph in graphs: resopgen.add_graph(graph) if errmsg: @@ -20,11 +38,10 @@ CLUSTERING = True BOX_COLOR = (128, 0, 96) - def __init__(self, highlightops): + def __init__(self): self.graphs = [] self.block_starters = {} # {graphindex: {set-of-operation-indices}} self.all_operations = {} - self.highlightops = highlightops self.errmsg = None def op_name(self, graphindex, opindex): @@ -43,18 +60,9 @@ for graphindex in range(len(self.graphs)): self.block_starters[graphindex] = {0: True} for graphindex, graph in enumerate(self.graphs): - prevop = None for i, op in enumerate(graph.get_operations()): - for attrname, delta in [('jump_target', 0), - ('_jump_target_prev', 1)]: - tgt = getattr(op, attrname, None) - if tgt is not None and tgt in self.all_operations: - tgt_g, tgt_i = self.all_operations[tgt] - self.mark_starter(tgt_g, tgt_i+delta) - self.mark_starter(graphindex, i+1) - if (op in self.highlightops) != (prevop in self.highlightops): - self.mark_starter(graphindex, i) - prevop = op + if op.is_guard(): + self.mark_starter(graphindex, i+1) def set_errmsg(self, errmsg): self.errmsg = errmsg @@ -68,11 +76,7 @@ _prev = Box._extended_display try: Box._extended_display = False - if len(self.graphs) > 1: - graphs = self.graphs[1:] - else: - graphs = self.graphs - for i, graph in enumerate(graphs): + for i, graph in enumerate(self.graphs): self.gengraph(graph, i) finally: Box._extended_display = _prev @@ -99,17 +103,16 @@ graphname = self.getgraphname(graphindex) if self.CLUSTERING: self.dotgen.emit('subgraph cluster%d {' % graphindex) - self.dotgen.emit_node(graphname, shape="octagon", - label=graph.get_display_text(), - fillcolor=graph.color) - - operations = graph.get_operations() - if operations: + label = graph.get_display_text() + if label is not None: + self.dotgen.emit_node(graphname, shape="octagon", + label=label, fillcolor='#f084c2') self.pendingedges.append((graphname, self.op_name(graphindex, 0), {})) - for opindex in self.block_starters[graphindex]: - self.genblock(operations, graphindex, opindex) + operations = graph.get_operations() + for opindex in self.block_starters[graphindex]: + self.genblock(operations, graphindex, opindex) if self.CLUSTERING: self.dotgen.emit('}') # closes the subgraph @@ -125,56 +128,35 @@ block_starters = self.block_starters[graphindex] lines = [] opindex = opstartindex - op = None while True: op = operations[opindex] lines.append(repr(op)) - #if op.opname == 'jump': - # self.genjump(blockname, op) - for attrname, delta in [('jump_target', 0), - ('_jump_target_prev', 1)]: - tgt = getattr(op, attrname, None) - if tgt is not None and tgt in self.all_operations: - tgt_g, tgt_i = self.all_operations[tgt] - kwds = {} - #if op.opname == 'jump': - # #kwds['constraint'] = 'false' - # #kwds['headport'] = ':n' - # pass - self.genedge((graphindex, opstartindex), - (tgt_g, tgt_i+delta), - color='red', - **kwds) + if op.is_guard(): + tgt = op.suboperations[0] + tgt_g, tgt_i = self.all_operations[tgt] + self.genedge((graphindex, opstartindex), + (tgt_g, tgt_i), + color='red') opindex += 1 if opindex >= len(operations): break if opindex in block_starters: - kwds = {} - #if op.opname == 'jump': - # kwds['color'] = '#d0d0ff' self.genedge((graphindex, opstartindex), - (graphindex, opindex), **kwds) + (graphindex, opindex)) break + tgt = getattr(op, 'jump_target', None) + if tgt is not None and tgt in self.graphs: + tgt_g = self.graphs.index(tgt) + self.genedge((graphindex, opstartindex), + (tgt_g, 0)) lines.append("") label = "\\l".join(lines) kwds = {} - if op in self.highlightops: - kwds['color'] = 'red' - kwds['fillcolor'] = '#ffe8e8' + #if op in self.highlightops: + # kwds['color'] = 'red' + # kwds['fillcolor'] = '#ffe8e8' self.dotgen.emit_node(blockname, shape="box", label=label, **kwds) - def genjump(self, srcblockname, op): - graph1 = op.gettargetloop().graph - try: - graphindex = self.graphs.index(graph1) - except ValueError: - return - self.pendingedges.append((srcblockname, - self.op_name(graphindex, 0), - {'color': graph1.color, - #'headport': ':n', - })) - def getlinks(self): boxes = {} for op in self.all_operations: Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 13:29:10 2009 @@ -320,65 +320,74 @@ # ____________________________________________________________ -# The Graph class is to store a loop or a bridge. -# Unclear if it's really useful any more; just the list of operations -# is enough in most cases. +# The Loop class contains a loop or a generalized loop, i.e. a tree +# of operations. Each branch ends in a jump which can go either to +# the top of the same loop, or to another loop. + +class Loop(object): + inputargs = None + operations = None -class Graph(object): - - def __init__(self, name, color): + def __init__(self, name): self.name = name - self.color = color - self.operations = [] + # self.inputargs = list of distinct Boxes + # self.operations = ops of the kind 'guard_xxx' contain a further + # list of operations, which may itself contain + # 'guard_xxx' and so on, making a tree. - def get_operations(self): - return self.operations + def _all_operations(self): + "NOT_RPYTHON" + oplist = list(self.operations) + for op in oplist: + if op.is_guard(): + oplist += op.suboperations + return oplist def summary(self, adding_insns={}): # for debugging + "NOT_RPYTHON" insns = adding_insns.copy() - for op in self.operations: + for op in self._all_operations(): opname = op.getopname() insns[opname] = insns.get(opname, 0) + 1 return insns + def get_operations(self): + return self.operations + def get_display_text(self): # for graphpage.py - return self.name + return self.name + '\n' + repr(self.inputargs) - def show(self, in_stats=None, errmsg=None, highlightops={}): - if in_stats is None: - from pypy.jit.metainterp.graphpage import ResOpGraphPage - ResOpGraphPage([self], errmsg, highlightops).display() - else: - h = dict.fromkeys(self.operations) - h.update(highlightops) - in_stats.view(errmsg=errmsg, extragraphs=[self], - highlightops=h) - - def copy(self): # for testing only - g = Graph(self.name, self.color) - g.operations = self.operations[:] - return g + def show(self, errmsg=None): + "NOT_RPYTHON" + from pypy.jit.metainterp.graphpage import display_loops + display_loops([self], errmsg) def check_consistency(self): # for testing "NOT_RPYTHON" - operations = self.operations - op = operations[0] - assert op.opnum in (rop.MERGE_POINT, rop.CATCH) - seen = dict.fromkeys(op.args) + for box in self.inputargs: + assert isinstance(box, Box), "Loop.inputargs contains %r" % (box,) + seen = dict.fromkeys(self.inputargs) + assert len(seen) == len(self.inputargs), ( + "duplicate Box in the Loop.inputargs") + self.check_consistency_of_branch(self.operations, seen) + + def check_consistency_of_branch(self, operations, seen): + "NOT_RPYTHON" for op in operations: for box in op.args: if isinstance(box, Box): assert box in seen - elif isinstance(box, Const): - assert op.opnum != rop.MERGE_POINT, ( - "no Constant arguments allowed in: %s" % (op,)) + assert (op.suboperations is not None) == op.is_guard() + if op.is_guard(): + self.check_consistency_of_branch(op.suboperations, seen.copy()) box = op.result if box is not None: assert isinstance(box, Box) assert box not in seen seen[box] = True - assert operations[-1].opnum == rop.JUMP - assert operations[-1].jump_target.opnum == rop.MERGE_POINT + assert operations[-1].is_final() + if operations[-1].opnum == rop.JUMP: + assert isinstance(operations[-1].jump_target, Loop) def __repr__(self): return '<%s>' % (self.name,) @@ -386,12 +395,10 @@ # ____________________________________________________________ -class Matcher(object): - pass - -class RunningMatcher(Matcher): +class RunningMatcher(object): def __init__(self, cpu): self.cpu = cpu + self.inputargs = None self.operations = [] def record(self, opnum, argboxes, resbox, descr=None): raise NotImplementedError @@ -406,6 +413,7 @@ def record(self, opnum, argboxes, resbox, descr=None): return None + def mp_eq(greenkey1, greenkey2): assert len(greenkey1) == len(greenkey2) for i in range(len(greenkey1)): @@ -428,21 +436,10 @@ """For tests.""" def __init__(self): - self.history_graph = Graph('History', '#8080ff') self.loops = [] - def get_all_graphs(self): - graphs = [self.history_graph] + self.loops - return graphs - - def check_history(self, expected=None, **check): - insns = self.history_graph.summary() - if expected is not None: - expected.setdefault('catch', 1) # it always starts with a catch - assert insns == expected - for insn, expected_count in check.items(): - assert insns.get(insn, 0) == expected_count - return insns + def get_all_loops(self): + return self.loops def check_loops(self, expected=None, **check): insns = {} @@ -463,14 +460,14 @@ if option.view: self.view() - def view(self, errmsg=None, extragraphs=[], highlightops={}): - from pypy.jit.metainterp.graphpage import ResOpGraphPage - graphs = self.get_all_graphs() - for graph in extragraphs: - if graph in graphs: - graphs.remove(graph) - graphs.append(graph) - ResOpGraphPage(graphs, errmsg, highlightops).display() + def view(self, errmsg=None, extraloops=[]): + from pypy.jit.metainterp.graphpage import display_loops + loops = self.get_all_loops() + for loop in extraloops: + if loop in loops: + loops.remove(loop) + loops.append(loop) + display_loops(loops, errmsg) class CrashInJIT(Exception): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 13:29:10 2009 @@ -650,8 +650,9 @@ if box is not None: extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opnum, extraargs, None) - guard_op.liveboxes = liveboxes - guard_op.key = key + op = history.ResOperation(rop.FAIL, liveboxes, None) + op.key = key + guard_op.suboperations = [op] self.pc = saved_pc return guard_op @@ -724,12 +725,8 @@ self._codewriter = codewriter.CodeWriter(self, policy) self.portal_code = self._codewriter.make_portal_bytecode( self.portal_graph) - self.cpu.set_meta_interp(self) self.delete_history() - def enable_stats(self): - return not we_are_translated() - def newframe(self, jitcode): if not we_are_translated(): self._debug_history.append(['enter', jitcode, None]) @@ -764,8 +761,6 @@ def create_empty_history(self): self.history = history.History(self.cpu) - if self.enable_stats(): - self.stats.history_graph.operations = self.history.operations def delete_history(self): # XXX call me again later @@ -803,24 +798,20 @@ def interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, # a ContinueRunningNormally, or a GenerateMergePoint exception. - if isinstance(self.history, history.BlackHole): - text = ' (BlackHole)' - else: - text = '' if not we_are_translated(): - history.log.event('ENTER' + text) + history.log.event('ENTER') else: - debug_print('ENTER' + text) + debug_print('~~~ ENTER') try: while True: self.framestack[-1].run_one_step() finally: if not we_are_translated(): - history.log.event('LEAVE' + text) + history.log.event('LEAVE') else: - debug_print('LEAVE' + text) + debug_print('~~~ LEAVE') - def compile_and_run(self, *args): + def compile_and_run_once(self, *args): orig_boxes = self.initialize_state_from_start(*args) try: self.interpret() @@ -864,11 +855,9 @@ if not box1.equals(box2): # not a valid loop raise self.ContinueRunningNormally(live_arg_boxes) - mp = history.ResOperation(rop.MERGE_POINT, - original_boxes[num_green_args:], None) - mp.greenkey = original_boxes[:num_green_args] - self.history.operations.insert(0, mp) - old_loops = self.compiled_merge_points.setdefault(mp.greenkey, []) + self.history.inputargs = original_boxes[num_green_args:] + greenkey = original_boxes[:num_green_args] + old_loops = self.compiled_merge_points.setdefault(greenkey, []) loop = compile_new_loop(self, old_loops, live_arg_boxes[num_green_args:]) if not loop: @@ -879,6 +868,7 @@ return loop def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes): + XXX num_green_args = self.num_green_args mp = history.ResOperation(rop.CATCH, original_boxes, None) mp.coming_from = guard_failure.guard_op Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Mon Mar 23 13:29:10 2009 @@ -2,18 +2,14 @@ class ResOperation(object): """The central ResOperation class, representing one operation.""" - # for 'merge_point' - specnodes = None - key = None - - # for 'jump' and 'guard_*' + # for 'jump': points to the target loop jump_target = None + # for 'fail' + key = None + # for 'guard_*' - counter = 0 - liveboxes = None - rebuild_ops = None - unoptboxes = None + suboperations = None # for 'guard_nonvirtualizable' vdesc = None @@ -36,10 +32,7 @@ self.descr = descr def __repr__(self): - result = self.repr() - if self.liveboxes is not None: - result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) - return result + return self.repr() def repr(self): # RPython-friendly version @@ -80,17 +73,28 @@ def is_comparison(self): return rop._COMPARISON_FIRST <= self.opnum <= rop._COMPARISON_LAST + def is_final(self): + return rop._FINAL_FIRST <= self.opnum <= rop._FINAL_LAST + +# ____________________________________________________________ + + +class GuardFailed(Exception): + def __init__(self, key, currentboxes): + self.key = key + self.currentboxes = currentboxes + # ____________________________________________________________ class rop(object): """The possible names of the ResOperations.""" - _SPECIAL_FIRST = 1 - MERGE_POINT = 1 - CATCH = 2 - JUMP = 3 - _SPECIAL_LAST = 9 + _FINAL_FIRST = 1 + JUMP = 1 + FAIL = 2 + #RAISE = 3 + _FINAL_LAST = 9 _GUARD_FIRST = 10 # ----- start of guard operations ----- GUARD_TRUE = 10 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Mon Mar 23 13:29:10 2009 @@ -11,6 +11,7 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.jit import PARAMETERS from pypy.rlib.rarithmetic import r_uint +from pypy.rlib.debug import debug_print from pypy.rpython.lltypesystem.lloperation import llop from pypy.jit.metainterp import support, history, pyjitpl @@ -146,12 +147,14 @@ self.state = state def crash_in_jit(e): - print "Crash in JIT!" if not we_are_translated(): - print '%s: %s' % (e.__class__, e) - import sys, pdb; pdb.post_mortem(sys.exc_info()[2]) - else: - print e + print "~~~ Crash in JIT!" + print '~~~ %s: %s' % (e.__class__, e) + if sys.stdout == sys.__stdout__: + import pdb; pdb.post_mortem(sys.exc_info()[2]) + raise + debug_print('~~~ Crash in JIT!') + debug_print('~~~ %s' % (e,)) raise history.CrashInJIT("crash in JIT") crash_in_jit._dont_inline_ = True @@ -492,7 +495,7 @@ getkeyhash._always_inline_ = True def compile_and_run(self, argshash, *args): - loop, boxes = warmrunnerdesc.metainterp.compile_and_run(*args) + loop, boxes = warmrunnerdesc.metainterp.compile_and_run_once(*args) if loop: cpu = warmrunnerdesc.metainterp.cpu operations = loop.operations From afa at codespeak.net Mon Mar 23 13:52:39 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 23 Mar 2009 13:52:39 +0100 (CET) Subject: [pypy-svn] r63226 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090323125239.E41CC1684F6@codespeak.net> Author: afa Date: Mon Mar 23 13:52:36 2009 New Revision: 63226 Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py Log: Feature request: metaclass for types defined at interp-level. This will be needed if we want to translate (part of) the _ctypes module. Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_typeobject.py Mon Mar 23 13:52:36 2009 @@ -2,6 +2,10 @@ from pypy.objspace.std.stdtypedef import * from pypy.conftest import gettestobjspace +from pypy.objspace.std.typeobject import W_TypeObject +from pypy.interpreter.gateway import interp2app +import py + class TestTypeObject: def test_not_acceptable_as_base_class(self): @@ -57,6 +61,45 @@ space.warn = prev_warn assert len(warnings) == 2 + def test_metaclass_typedef(self): + py.test.skip("Not implemented yet") + + # Define a metaclass + class W_MyMetaclass(W_TypeObject): + def f(w_self, space): + return space.wrap(42) + + W_MyMetaclass.typedef = StdTypeDef( + "MyMeta", + W_TypeObject.typedef, + f=interp2app(W_MyMetaclass.f, unwrap_spec=["self", ObjSpace]), + ) + + # Define a type, instance of the above metaclass + class W_MyType(Wrappable): + pass + + def MyType_descr_new(space, w_cls): + return space.wrap(W_MyType()) + + W_MyType.typedef = StdTypeDef( + "MyType", + __new__ = interp2app(MyType_descr_new), + ) + W_MyType.typedef.meta = W_MyMetaclass + + # Test it + w_mytype = self.space.gettypeobject(W_MyType.typedef) + self.space.appexec([w_mytype], """(MyType): + x = MyType() + assert type(x).f() == 42 + + class MyDerived(MyType): + pass + y = MyDerived() + assert type(y).f() == 42 + """) + class AppTestTypeObject: From afa at codespeak.net Mon Mar 23 14:32:23 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 23 Mar 2009 14:32:23 +0100 (CET) Subject: [pypy-svn] r63227 - pypy/trunk/pypy/module/rctime Message-ID: <20090323133223.1B0F81684FC@codespeak.net> Author: afa Date: Mon Mar 23 14:32:22 2009 New Revision: 63227 Modified: pypy/trunk/pypy/module/rctime/interp_time.py Log: Oops, _init_timezone does not return anything nowadays. Modified: pypy/trunk/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/trunk/pypy/module/rctime/interp_time.py (original) +++ pypy/trunk/pypy/module/rctime/interp_time.py Mon Mar 23 14:32:22 2009 @@ -411,9 +411,9 @@ should not be relied on""" c_tzset() - + # reset timezone, altzone, daylight and tzname - timezone, daylight, tzname, altzone = _init_timezone(space) + _init_timezone(space) tzset.unwrap_spec = [ObjSpace] def strftime(space, format, w_tup=None): From arigo at codespeak.net Mon Mar 23 15:04:59 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 15:04:59 +0100 (CET) Subject: [pypy-svn] r63230 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp Message-ID: <20090323140459.CE5111684E8@codespeak.net> Author: arigo Date: Mon Mar 23 15:04:59 2009 New Revision: 63230 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Log: Two tests of test_loop pass again. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py Mon Mar 23 15:04:59 2009 @@ -127,6 +127,7 @@ class CompiledLoop(object): def __init__(self): + self.inputargs = [] self.operations = [] def __repr__(self): @@ -165,6 +166,9 @@ def is_guard(self): return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST + def is_final(self): + return rop._FINAL_FIRST <= self.opnum <= rop._FINAL_LAST + def repr0(x): if isinstance(x, list): return '[' + ', '.join(repr0(y) for y in x) + ']' @@ -244,6 +248,7 @@ assert not loop.operations v = Variable() v.concretetype = lltype.Signed + loop.inputargs.append(v) r = len(_variables) _variables.append(v) return r @@ -253,6 +258,7 @@ assert not loop.operations v = Variable() v.concretetype = llmemory.GCREF + loop.inputargs.append(v) r = len(_variables) _variables.append(v) return r @@ -307,18 +313,22 @@ _variables.append(v) return r -def compile_add_jump_target(loop, loop_target, loop_target_index): - xxx +def compile_add_jump_target(loop, loop_target): loop = _from_opaque(loop) loop_target = _from_opaque(loop_target) op = loop.operations[-1] op.jump_target = loop_target - op.jump_target_index = loop_target_index - if op.opnum == rop.JUMP: - if loop_target == loop and loop_target_index == 0: - log.info("compiling new loop") - else: - log.info("compiling new bridge") + assert op.opnum == rop.JUMP + if loop_target == loop: + log.info("compiling new loop") + else: + log.info("compiling new bridge") + +def compile_add_fail(loop, fail_index): + loop = _from_opaque(loop) + op = loop.operations[-1] + assert op.opnum == rop.FAIL + op.fail_index = fail_index def compile_suboperations(loop): loop = _from_opaque(loop) @@ -342,13 +352,6 @@ else: return self.env[v] - def go_to_merge_point(self, loop, opindex, args): - mp = loop.operations[opindex] - assert len(mp.args) == len(args) - self.loop = loop - self.opindex = opindex - self.env = dict(zip(mp.args, args)) - def execute(self): """Execute all operations in a loop, possibly following to other loops as well. @@ -356,22 +359,20 @@ global _last_exception assert _last_exception is None, "exception left behind" verbose = True + operations = self.loop.operations + opindex = 0 while True: - self.opindex += 1 - op = self.loop.operations[self.opindex] + op = operations[opindex] args = [self.getenv(v) for v in op.args] - if op.opnum == rop.MERGE_POINT: - self.go_to_merge_point(self.loop, self.opindex, args) - continue - if op.opnum == rop.JUMP: - self.go_to_merge_point(op.jump_target, - op.jump_target_index, - args) - _stats.exec_jumps += 1 - continue - try: - result = self.execute_operation(op.opnum, args, op.descr, - verbose) + if not op.is_final(): + try: + result = self.execute_operation(op.opnum, args, op.descr, + verbose) + except GuardFailed: + assert op.is_guard() + operations = op.subloop.operations + opindex = 0 + continue #verbose = self.verbose assert (result is None) == (op.result is None) if op.result is not None: @@ -384,29 +385,22 @@ raise Exception("op.result.concretetype is %r" % (RESTYPE,)) self.env[op.result] = x - except GuardFailed: - if hasattr(op, 'jump_target'): - # the guard already failed once, go to the - # already-generated code - catch_op = op.jump_target.operations[0] - assert catch_op.opnum == rop.CATCH - args = [] - it = iter(op.livevars) - for v in catch_op.args: - if isinstance(v, Variable): - args.append(self.getenv(it.next())) - else: - args.append(v) - assert list(it) == [] - self.go_to_merge_point(op.jump_target, - op.jump_target_index, - args) - else: - if self.verbose: - log.trace('failed: %s(%s)' % ( - opname, ', '.join(map(str, args)))) - self.failed_guard_op = op - return op.failnum + opindex += 1 + continue + if op.opnum == rop.JUMP: + assert len(op.jump_target.inputargs) == len(args) + self.env = dict(zip(op.jump_target.inputargs, args)) + operations = op.jump_target.operations + opindex = 0 + _stats.exec_jumps += 1 + elif op.opnum == rop.FAIL: + if self.verbose: + log.trace('failed: %s' % ( + ', '.join(map(str, args)),)) + self.fail_args = args + return op.fail_index + else: + assert 0, "unknown final operation %d" % (op.opnum,) def execute_operation(self, opnum, values, descr, verbose): """Execute a single operation. @@ -422,16 +416,22 @@ for i in range(len(values)): if isinstance(values[i], ComputedIntSymbolic): values[i] = values[i].compute_fn() - res = ophandler(self, descr, *values) - if verbose: - argtypes, restype = TYPES[opname] - if res is None: - resdata = '' - else: - resdata = '-> ' + repr1(res, restype, self.memocast) - # fish the types - log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.memocast), resdata)) + res = '*' + try: + res = ophandler(self, descr, *values) + finally: + if verbose: + argtypes, restype = TYPES[opname] + if res is None: + resdata = '' + elif res == '*': + resdata = '*fail*' + else: + resdata = '-> ' + repr1(res, restype, self.memocast) + # fish the types + log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, + self.memocast), + resdata)) return res def as_int(self, x): @@ -624,30 +624,26 @@ frame = Frame(memocast) return _to_opaque(frame) -def frame_clear(frame, loop, opindex): +def frame_clear(frame, loop): frame = _from_opaque(frame) loop = _from_opaque(loop) frame.loop = loop - frame.opindex = opindex frame.env = {} def frame_add_int(frame, value): frame = _from_opaque(frame) i = len(frame.env) - mp = frame.loop.operations[0] - frame.env[mp.args[i]] = value + frame.env[frame.loop.inputargs[i]] = value def frame_add_ptr(frame, value): frame = _from_opaque(frame) i = len(frame.env) - mp = frame.loop.operations[0] - frame.env[mp.args[i]] = value + frame.env[frame.loop.inputargs[i]] = value def frame_execute(frame): frame = _from_opaque(frame) if frame.verbose: - mp = frame.loop.operations[0] - values = [frame.env[v] for v in mp.args] + values = [frame.env[v] for v in frame.loop.inputargs] log.trace('Entering CPU frame <- %r' % (values,)) try: result = frame.execute() @@ -662,19 +658,11 @@ def frame_int_getvalue(frame, num): frame = _from_opaque(frame) - return frame.env[frame.failed_guard_op.livevars[num]] + return frame.fail_args[num] def frame_ptr_getvalue(frame, num): frame = _from_opaque(frame) - return frame.env[frame.failed_guard_op.livevars[num]] - -def frame_int_setvalue(frame, num, value): - frame = _from_opaque(frame) - frame.env[frame.loop.operations[0].args[num]] = value - -def frame_ptr_setvalue(frame, num, value): - frame = _from_opaque(frame) - frame.env[frame.loop.operations[0].args[num]] = value + return frame.fail_args[num] def frame_int_getresult(frame): frame = _from_opaque(frame) @@ -958,6 +946,7 @@ setannotation(compile_add_int_result, annmodel.SomeInteger()) setannotation(compile_add_ptr_result, annmodel.SomeInteger()) setannotation(compile_add_jump_target, annmodel.s_None) +setannotation(compile_add_fail, annmodel.s_None) setannotation(new_frame, s_Frame) setannotation(frame_clear, annmodel.s_None) @@ -966,8 +955,6 @@ setannotation(frame_execute, annmodel.SomeInteger()) setannotation(frame_int_getvalue, annmodel.SomeInteger()) setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF)) -setannotation(frame_int_setvalue, annmodel.s_None) -setannotation(frame_ptr_setvalue, annmodel.s_None) setannotation(frame_int_getresult, annmodel.SomeInteger()) setannotation(frame_ptr_getresult, annmodel.SomePtr(llmemory.GCREF)) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Mon Mar 23 15:04:59 2009 @@ -6,7 +6,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rpython.llinterp import LLInterpreter from pypy.jit.metainterp import history -from pypy.jit.metainterp.resoperation import ResOperation, rop +from pypy.jit.metainterp.resoperation import ResOperation, rop, GuardFailure from pypy.jit.backend.llgraph import llimpl, symbolic @@ -61,6 +61,7 @@ self.stats.exec_counters = {} self.stats.exec_jumps = 0 self.memo_cast = llimpl.new_memo_cast() + self.fail_ops = [] llimpl._stats = self.stats llimpl._llinterp = LLInterpreter(self.rtyper) if translate_support_code: @@ -69,23 +70,21 @@ def compile_operations(self, loop): """In a real assembler backend, this should assemble the given - list of operations. Here we just generate a similar LoopOrBridge + list of operations. Here we just generate a similar CompiledLoop instance. The code here is RPython, whereas the code in llimpl is not. """ - operations = loop.operations c = llimpl.compile_start() loop._compiled_version = c var2index = {} - for i in range(len(operations[0].args)): - box = operations[0].args[i] + for box in loop.inputargs: if isinstance(box, history.BoxInt): var2index[box] = llimpl.compile_start_int_var(c) elif isinstance(box, history.BoxPtr): var2index[box] = llimpl.compile_start_ptr_var(c) else: raise Exception("box is: %r" % (box,)) - self._compile_branch(c, operations[1:], var2index) + self._compile_branch(c, loop.operations, var2index) def _compile_branch(self, c, operations, var2index): for op in operations: @@ -116,10 +115,17 @@ else: raise Exception("%s.result contain: %r" % (op.getopname(), x)) - llimpl.compile_add_jump_target(c, op.target_jump._compiled_version) + assert op.is_final() + if op.opnum == rop.JUMP: + llimpl.compile_add_jump_target(c, op.jump_target._compiled_version) + elif op.opnum == rop.FAIL: + llimpl.compile_add_fail(c, len(self.fail_ops)) + self.fail_ops.append(op) def execute_operations(self, loop, valueboxes): """Calls the assembler generated for the given loop. + Typically returns an instance of 'resoperation.GuardFailure'; + may also raise an exception if the assembler code raises. """ frame = llimpl.new_frame(self.memo_cast) # setup the frame @@ -136,14 +142,30 @@ else: raise Exception("bad box in valueboxes: %r" % (box,)) # run the loop - result = llimpl.frame_execute(frame) + fail_index = llimpl.frame_execute(frame) # get the exception to raise and really raise it, if any - exception_addr = llimpl.frame_get_exception(frame) + exception_addr = llimpl.get_exception() if exception_addr: - exc_value_gcref = llimpl.frame_get_exc_value(frame) + exc_value_gcref = llimpl.get_exc_value() xxxx else: - return result + # common case: we hit a FAIL operation. Fish for the values + # (in a real backend, this should be done by the FAIL operation + # itself, not here) + op = self.fail_ops[fail_index] + currentboxes = [] + for i in range(len(op.args)): + box = op.args[i] + if isinstance(box, history.BoxInt): + value = llimpl.frame_int_getvalue(frame, i) + box = history.BoxInt(value) + elif isinstance(box, history.BoxPtr): + value = llimpl.frame_ptr_getvalue(frame, i) + box = history.BoxPtr(value) + else: + raise Exception("bad box in 'fail': %r" % (box,)) + currentboxes.append(box) + return GuardFailure(op.key, currentboxes) @staticmethod def sizeof(S): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 15:04:59 2009 @@ -115,7 +115,7 @@ metainterp.cpu) if old_loop is not None: return old_loop - finish_loop_or_bridge(metainterp, loop, loop.operations[0]) + send_loop_to_backend(metainterp, loop) old_loops.append(loop) return loop @@ -124,10 +124,7 @@ op.jump_target = loop loop.operations.append(op) -def finish_loop_or_bridge(metainterp, loop, targetmp): - assert targetmp.opnum == rop.MERGE_POINT - assert loop.operations[-1].opnum == rop.JUMP - loop.operations[-1].jump_target = targetmp +def send_loop_to_backend(metainterp, loop): metainterp.cpu.compile_operations(loop) metainterp.stats.loops.append(loop) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 15:04:59 2009 @@ -326,6 +326,7 @@ class Loop(object): inputargs = None + specnodes = None operations = None def __init__(self, name): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 15:04:59 2009 @@ -651,7 +651,8 @@ extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opnum, extraargs, None) op = history.ResOperation(rop.FAIL, liveboxes, None) - op.key = key + op.key = Key(key, opnum in (rop.GUARD_EXCEPTION, + rop.GUARD_NO_EXCEPTION)) guard_op.suboperations = [op] self.pc = saved_pc return guard_op @@ -823,17 +824,14 @@ def handle_guard_failure(self, guard_failure): orig_boxes = self.initialize_state_from_guard_failure(guard_failure) try: - if guard_failure.guard_op.opnum in (rop.GUARD_EXCEPTION, - rop.GUARD_NO_EXCEPTION): + if guard_failure.key.is_exception_catch: self.handle_exception() self.interpret() assert False, "should always raise" except GenerateMergePoint, gmp: compiled_bridge = self.compile_bridge(guard_failure, orig_boxes, gmp.argboxes) - loop, resargs = self.designate_target_loop(gmp, - compiled_bridge.jump_to) - self.jump_after_guard_failure(guard_failure, loop, resargs) + return self.designate_target_loop(gmp, compiled_bridge.jump_to) def designate_target_loop(self, gmp, loop): num_green_args = self.num_green_args @@ -841,12 +839,6 @@ gmp.argboxes[num_green_args:]) return (loop, residual_args) - def jump_after_guard_failure(self, guard_failure, loop, residual_args): - guard_failure.make_ready_for_continuing_at(loop.operations[0]) - for i in range(len(residual_args)): - self.cpu.setvaluebox(guard_failure.frame, loop.operations[0], - i, residual_args[i]) - def compile(self, original_boxes, live_arg_boxes): num_green_args = self.num_green_args for i in range(num_green_args): @@ -890,9 +882,9 @@ return bridge def get_residual_args(self, loop, args): - mp = loop.operations[0] - if mp.specnodes is None: # it is None only for tests + if loop.specnodes is None: # it is None only for tests return args + xxx assert len(mp.specnodes) == len(args) expanded_args = [] for i in range(len(mp.specnodes)): @@ -939,22 +931,14 @@ self.history = history.History(self.cpu) else: self.history = history.BlackHole(self.cpu) - guard_op = guard_failure.guard_op - boxes_from_frame = [] - index = 0 - for box in guard_op.liveboxes: - assert isinstance(box, Box) - newbox = self.cpu.getvaluebox(guard_failure.frame, - guard_op, index) - index += 1 - boxes_from_frame.append(newbox) - if guard_op.rebuild_ops is not None: + boxes_from_frame = guard_failure.currentboxes + if 0: # xxx guard_op.rebuild_ops is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( guard_op, self.cpu, self.history, boxes_from_frame) else: # xxx for tests only newboxes = boxes_from_frame - self.rebuild_state_after_failure(guard_op.key, newboxes) + self.rebuild_state_after_failure(guard_failure.key.key, newboxes) return boxes_from_frame def handle_exception(self): @@ -1007,3 +991,9 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args + +class Key(object): + def __init__(self, key, is_exception_catch): + self.key = key + self.counter = 0 + self.is_exception_catch = is_exception_catch Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Mon Mar 23 15:04:59 2009 @@ -79,7 +79,7 @@ # ____________________________________________________________ -class GuardFailed(Exception): +class GuardFailure(object): def __init__(self, key, currentboxes): self.key = key self.currentboxes = currentboxes Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Mon Mar 23 15:04:59 2009 @@ -495,17 +495,16 @@ getkeyhash._always_inline_ = True def compile_and_run(self, argshash, *args): - loop, boxes = warmrunnerdesc.metainterp.compile_and_run_once(*args) - if loop: + metainterp = warmrunnerdesc.metainterp + loop, boxes = metainterp.compile_and_run_once(*args) + while loop: cpu = warmrunnerdesc.metainterp.cpu - operations = loop.operations - box = cpu.execute_operations_in_new_frame('run_this_loop', - operations, boxes) - raise warmrunnerdesc.DoneWithThisFrame(box) + guard_failure = cpu.execute_operations(loop, boxes) + loop, boxes = metainterp.handle_guard_failure(guard_failure) def must_compile_from_failure(self, guard_failure): - guard_op = guard_failure.guard_op - guard_op.counter += 1 - return guard_op.counter >= self.trace_eagerness + key_holder = guard_failure.key + key_holder.counter += 1 + return key_holder.counter >= self.trace_eagerness return WarmEnterState From afa at codespeak.net Mon Mar 23 15:43:55 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 23 Mar 2009 15:43:55 +0100 (CET) Subject: [pypy-svn] r63231 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090323144355.3DB2C168418@codespeak.net> Author: afa Date: Mon Mar 23 15:43:53 2009 New Revision: 63231 Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: A few r_uint conversions to please the rtyper on 64bit platforms "arithmetic is not supported for rffi.INT" Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Mon Mar 23 15:43:53 2009 @@ -6,6 +6,7 @@ from pypy.objspace.descroperation import object_setattr from pypy.rpython.lltypesystem import rffi, lltype from pypy.rlib.unroll import unrolling_iterable +from pypy.rlib.rarithmetic import r_uint from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -168,7 +169,7 @@ result_error = "None" if name == 'CharacterDataHandler': - pre_code = 'if parser.buffer_string(space, w_arg0, arg1): return' + pre_code = 'if parser.buffer_string(space, w_arg0, r_uint(arg1)): return' else: pre_code = 'parser.flush_character_buffer(space)' @@ -339,7 +340,7 @@ def w_convert_charp_n(self, space, data, length): if data: - return self.w_convert(space, rffi.charp2strn(data, length)) + return self.w_convert(space, rffi.charp2strn(data, r_uint(length))) else: return space.w_None From arigo at codespeak.net Mon Mar 23 16:13:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 16:13:45 +0100 (CET) Subject: [pypy-svn] r63233 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090323151345.6F8701684CF@codespeak.net> Author: arigo Date: Mon Mar 23 16:13:44 2009 New Revision: 63233 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py Log: Still in-progress. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py Mon Mar 23 16:13:44 2009 @@ -370,6 +370,7 @@ verbose) except GuardFailed: assert op.is_guard() + _stats.exec_conditional_jumps += 1 operations = op.subloop.operations opindex = 0 continue @@ -416,7 +417,7 @@ for i in range(len(values)): if isinstance(values[i], ComputedIntSymbolic): values[i] = values[i].compute_fn() - res = '*' + res = NotImplemented try: res = ophandler(self, descr, *values) finally: @@ -424,7 +425,7 @@ argtypes, restype = TYPES[opname] if res is None: resdata = '' - elif res == '*': + elif res is NotImplemented: resdata = '*fail*' else: resdata = '-> ' + repr1(res, restype, self.memocast) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Mon Mar 23 16:13:44 2009 @@ -51,6 +51,7 @@ return '' % (self.ofs, self.type, self.name) return '' % (self.ofs, self.type) + class CPU(object): def __init__(self, rtyper, stats=None, translate_support_code=False, @@ -60,6 +61,7 @@ self.stats = stats or MiniStats() self.stats.exec_counters = {} self.stats.exec_jumps = 0 + self.stats.exec_conditional_jumps = 0 self.memo_cast = llimpl.new_memo_cast() self.fail_ops = [] llimpl._stats = self.stats @@ -167,6 +169,18 @@ currentboxes.append(box) return GuardFailure(op.key, currentboxes) + def get_exception(self): + return self.cast_adr_to_int(llimpl.get_exception()) + + def get_exc_value(self): + return llimpl.get_exc_value() + + def clear_exception(self): + llimpl.clear_exception() + + def set_overflow_error(self): + llimpl.set_overflow_error() + @staticmethod def sizeof(S): return Descr(symbolic.get_size(S)) @@ -317,22 +331,6 @@ else: # calldescr.type == 'v' # void llimpl.do_call_void(func, self.memo_cast) -class GuardFailed(object): - returns = False - - def __init__(self, frame, guard_op): - self.frame = frame - self.guard_op = guard_op - - def make_ready_for_return(self, retbox): - self.returns = True - self.retbox = retbox - - def make_ready_for_continuing_at(self, merge_point): - llimpl.frame_clear(self.frame, merge_point._compiled, - merge_point._opindex) - self.merge_point = merge_point - # ____________________________________________________________ import pypy.jit.metainterp.executor Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 16:13:44 2009 @@ -111,10 +111,10 @@ loop.inputargs = history.inputargs loop.operations = history.operations close_loop(loop, endliveboxes) - old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, - metainterp.cpu) - if old_loop is not None: - return old_loop + #old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, + # metainterp.cpu) + #if old_loop is not None: + # return old_loop send_loop_to_backend(metainterp, loop) old_loops.append(loop) return loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 16:13:44 2009 @@ -332,9 +332,9 @@ def __init__(self, name): self.name = name # self.inputargs = list of distinct Boxes - # self.operations = ops of the kind 'guard_xxx' contain a further - # list of operations, which may itself contain - # 'guard_xxx' and so on, making a tree. + # self.operations = list of ResOperations + # ops of the kind 'guard_xxx' contain a further list of operations, + # which may itself contain 'guard_xxx' and so on, making a tree. def _all_operations(self): "NOT_RPYTHON" @@ -442,11 +442,28 @@ def get_all_loops(self): return self.loops + def check_history(self, expected=None, **check): + insns = {} + for op in self.history.operations: + opname = op.getopname() + insns[opname] = insns.get(opname, 0) + 1 + if expected is not None: + # 'fail' operations may be omitted from 'expected' + if 'fail' in insns: + expected.setdefault('fail', insns['fail']) + assert insns == expected + for insn, expected_count in check.items(): + assert insns.get(insn, 0) == expected_count + return insns + def check_loops(self, expected=None, **check): insns = {} for loop in self.loops: insns = loop.summary(adding_insns=insns) if expected is not None: + # 'fail' operations may be omitted from 'expected' + if 'fail' in insns: + expected.setdefault('fail', insns['fail']) assert insns == expected for insn, expected_count in check.items(): assert insns.get(insn, 0) == expected_count Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 16:13:44 2009 @@ -762,6 +762,8 @@ def create_empty_history(self): self.history = history.History(self.cpu) + if self.stats is not None: + self.stats.history = self.history def delete_history(self): # XXX call me again later @@ -799,18 +801,22 @@ def interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, # a ContinueRunningNormally, or a GenerateMergePoint exception. + if isinstance(self.history, history.BlackHole): + text = ' (BlackHole)' + else: + text = '' if not we_are_translated(): - history.log.event('ENTER') + history.log.event('ENTER' + text) else: - debug_print('~~~ ENTER') + debug_print('~~~ ENTER', text) try: while True: self.framestack[-1].run_one_step() finally: if not we_are_translated(): - history.log.event('LEAVE') + history.log.event('LEAVE' + text) else: - debug_print('~~~ LEAVE') + debug_print('~~~ LEAVE', text) def compile_and_run_once(self, *args): orig_boxes = self.initialize_state_from_start(*args) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py Mon Mar 23 16:13:44 2009 @@ -62,13 +62,12 @@ graph = cw.unfinished_graphs.pop() cw.make_one_bytecode(graph, False) metainterp.portal_code = maingraph - metainterp.cpu.set_meta_interp(metainterp) metainterp.delete_history() metainterp.warmrunnerdesc = FakeWarmRunnderDesc metainterp.DoneWithThisFrame = DoneWithThisFrame self.metainterp = metainterp try: - metainterp.compile_and_run(*args) + metainterp.compile_and_run_once(*args) except DoneWithThisFrame, e: if conftest.option.view: metainterp.stats.view() @@ -143,15 +142,18 @@ res = self.meta_interp(f, [6, 7]) assert res == 42 self.check_loop_count(1) - self.check_loops({'merge_point': 1, 'guard_true': 1, + self.check_loops({'guard_true': 1, 'int_add': 1, 'int_sub': 1, 'int_gt': 1, 'jump': 1}) if self.basic: - for op in get_stats().loops[0].operations: - if op.getopname() == 'guard_true': - liveboxes = op.liveboxes + found = 0 + for op in get_stats().loops[0]._all_operations(): + if op.getopname() == 'fail': + liveboxes = op.args assert len(liveboxes) == 1 assert isinstance(liveboxes[0], history.BoxInt) + found += 1 + assert found == 1 def test_string(self): def f(n): From afa at codespeak.net Mon Mar 23 16:27:38 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 23 Mar 2009 16:27:38 +0100 (CET) Subject: [pypy-svn] r63236 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090323152738.E56FE1684D1@codespeak.net> Author: afa Date: Mon Mar 23 16:27:38 2009 New Revision: 63236 Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: Use the correct cast to lltype.Signed, instead of r_uint Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Mon Mar 23 16:27:38 2009 @@ -6,7 +6,6 @@ from pypy.objspace.descroperation import object_setattr from pypy.rpython.lltypesystem import rffi, lltype from pypy.rlib.unroll import unrolling_iterable -from pypy.rlib.rarithmetic import r_uint from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -169,7 +168,7 @@ result_error = "None" if name == 'CharacterDataHandler': - pre_code = 'if parser.buffer_string(space, w_arg0, r_uint(arg1)): return' + pre_code = 'if parser.buffer_string(space, w_arg0, arg1): return' else: pre_code = 'parser.flush_character_buffer(space)' @@ -339,8 +338,9 @@ return space.w_None def w_convert_charp_n(self, space, data, length): + ll_length = rffi.cast(lltype.Signed, length) if data: - return self.w_convert(space, rffi.charp2strn(data, r_uint(length))) + return self.w_convert(space, rffi.charp2strn(data, ll_length)) else: return space.w_None @@ -376,16 +376,17 @@ space.newtuple(children)]) def buffer_string(self, space, w_string, length): + ll_length = rffi.cast(lltype.Signed, length) if self.buffer_w is not None: - if self.buffer_used + length > self.buffer_size: + if self.buffer_used + ll_length > self.buffer_size: self.flush_character_buffer(space) # handler might have changed; drop the rest on the floor # if there isn't a handler anymore if self.w_character_data_handler is None: return True - if length <= self.buffer_size: + if ll_length <= self.buffer_size: self.buffer_w.append(w_string) - self.buffer_used += length + self.buffer_used += ll_length return True else: self.buffer_w = [] From arigo at codespeak.net Mon Mar 23 16:27:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 16:27:56 +0100 (CET) Subject: [pypy-svn] r63237 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090323152756.0C4AB1684D1@codespeak.net> Author: arigo Date: Mon Mar 23 16:27:56 2009 New Revision: 63237 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Log: Adapt the test. Still 3 failures. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Mon Mar 23 16:27:56 2009 @@ -165,12 +165,15 @@ # the 'char_eq' and following 'guard' should be constant-folded self.check_loops(char_eq=0, guard_true=1, guard_false=0) if self.basic: - for op in get_stats().loops[0].operations: - if op.getopname() == 'guard_true': - liveboxes = op.liveboxes + found = 0 + for op in get_stats().loops[0]._all_operations(): + if op.getopname() == 'fail': + liveboxes = op.args assert len(liveboxes) == 2 # x, y (in some order) assert isinstance(liveboxes[0], history.BoxInt) assert isinstance(liveboxes[1], history.BoxInt) + found += 1 + assert found == 1 def test_interp_many_paths(self): myjitdriver = JitDriver(greens = ['i'], reds = ['x', 'node']) @@ -363,7 +366,7 @@ res = self.meta_interp(main_interpreter_loop, [1]) assert res == 102 self.check_loop_count(1) - self.check_loops({'merge_point' : 1, 'int_add' : 3, 'int_gt' : 1, + self.check_loops({'int_add' : 3, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1}) def test_automatic_promotion(self): @@ -405,7 +408,7 @@ assert res == main_interpreter_loop(1) self.check_loop_count(1) # XXX maybe later optimize guard_value away - self.check_loops({'merge_point' : 1, 'int_add' : 6, 'int_gt' : 1, + self.check_loops({'int_add' : 6, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1, 'guard_value' : 3}) def test_can_enter_jit_outside_main_loop(self): From arigo at codespeak.net Mon Mar 23 16:40:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 16:40:31 +0100 (CET) Subject: [pypy-svn] r63239 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp/test Message-ID: <20090323154031.3B5211684FB@codespeak.net> Author: arigo Date: Mon Mar 23 16:40:30 2009 New Revision: 63239 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_exception.py Log: Fix exceptions -- we don't need to special-case them at all in execute_operations(). Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Mon Mar 23 16:40:30 2009 @@ -145,29 +145,23 @@ raise Exception("bad box in valueboxes: %r" % (box,)) # run the loop fail_index = llimpl.frame_execute(frame) - # get the exception to raise and really raise it, if any - exception_addr = llimpl.get_exception() - if exception_addr: - exc_value_gcref = llimpl.get_exc_value() - xxxx - else: - # common case: we hit a FAIL operation. Fish for the values - # (in a real backend, this should be done by the FAIL operation - # itself, not here) - op = self.fail_ops[fail_index] - currentboxes = [] - for i in range(len(op.args)): - box = op.args[i] - if isinstance(box, history.BoxInt): - value = llimpl.frame_int_getvalue(frame, i) - box = history.BoxInt(value) - elif isinstance(box, history.BoxPtr): - value = llimpl.frame_ptr_getvalue(frame, i) - box = history.BoxPtr(value) - else: - raise Exception("bad box in 'fail': %r" % (box,)) - currentboxes.append(box) - return GuardFailure(op.key, currentboxes) + # we hit a FAIL operation. Fish for the values + # (in a real backend, this should be done by the FAIL operation + # itself, not here) + op = self.fail_ops[fail_index] + currentboxes = [] + for i in range(len(op.args)): + box = op.args[i] + if isinstance(box, history.BoxInt): + value = llimpl.frame_int_getvalue(frame, i) + box = history.BoxInt(value) + elif isinstance(box, history.BoxPtr): + value = llimpl.frame_ptr_getvalue(frame, i) + box = history.BoxPtr(value) + else: + raise Exception("bad box in 'fail': %r" % (box,)) + currentboxes.append(box) + return GuardFailure(op.key, currentboxes) def get_exception(self): return self.cast_adr_to_int(llimpl.get_exception()) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_exception.py Mon Mar 23 16:40:30 2009 @@ -35,7 +35,7 @@ return n res = self.meta_interp(f, [10]) assert res == 0 - self.check_loops({'merge_point': 1, 'jump': 1, + self.check_loops({'jump': 1, 'int_gt': 1, 'guard_true': 1, 'int_sub': 1}) From arigo at codespeak.net Mon Mar 23 16:45:15 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 16:45:15 +0100 (CET) Subject: [pypy-svn] r63240 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090323154515.4D9C31684FE@codespeak.net> Author: arigo Date: Mon Mar 23 16:45:14 2009 New Revision: 63240 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py Log: Fix this test too. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py Mon Mar 23 16:45:14 2009 @@ -22,7 +22,7 @@ return c res = self.meta_interp(f, [1]) assert res == 2 - self.check_loops({'jump': 1, 'merge_point': 1, + self.check_loops({'jump': 1, 'int_sub': 1, 'int_gt' : 1, 'guard_true': 1}) # all folded away @@ -74,7 +74,7 @@ assert res == 43 self.check_loops({'call': 1, 'guard_no_exception': 1, 'getfield_gc': 1, - 'int_add': 1, 'merge_point' : 1, + 'int_add': 1, 'jump': 1, 'int_gt' : 1, 'guard_true' : 1, 'int_sub' : 1}) From cami at codespeak.net Mon Mar 23 18:24:55 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 23 Mar 2009 18:24:55 +0100 (CET) Subject: [pypy-svn] r63248 - pypy/branch/pyjitpl5-PyGirl Message-ID: <20090323172455.9D5FB1684E2@codespeak.net> Author: cami Date: Mon Mar 23 18:24:53 2009 New Revision: 63248 Added: pypy/branch/pyjitpl5-PyGirl/ - copied from r63247, pypy/branch/pyjitpl5/ Log: creating pyGirl jit branch From cami at codespeak.net Mon Mar 23 18:30:30 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 23 Mar 2009 18:30:30 +0100 (CET) Subject: [pypy-svn] r63249 - in pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy: . debug profiling test Message-ID: <20090323173030.42DD516846D@codespeak.net> Author: cami Date: Mon Mar 23 18:30:29 2009 New Revision: 63249 Added: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug.py - copied, changed from r58379, pypy/dist/pypy/lang/gameboy/debug/debug.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug_cpu.py - copied unchanged from r58379, pypy/dist/pypy/lang/gameboy/debug/debug_cpu.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug_rpc_xml_memory.py - copied, changed from r58379, pypy/dist/pypy/lang/gameboy/debug/debug_rpc_xml_memory.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboyImplementation.py - copied unchanged from r54952, pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_register.py (props changed) - copied unchanged from r54952, pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu_register.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy_implementation.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_register.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_video.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/video.py Log: mergin in the latest pyGirl Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Mon Mar 23 18:30:29 2009 @@ -1,7 +1,8 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import Interrupt -from pypy.lang.gameboy.cpu_register import Register, DoubleRegister, \ +from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ + ReservedDoubleRegister,\ FlagRegister, ImmediatePseudoRegister # --------------------------------------------------------------------------- @@ -50,8 +51,8 @@ self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_PC) - self.sp = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_SP) + self.pc = ReservedDoubleRegister(self, reset_value=constants.RESET_PC) + self.sp = ReservedDoubleRegister(self, reset_value=constants.RESET_SP) self.a = Register(self, constants.RESET_A) self.flag = FlagRegister(self, constants.RESET_F) @@ -251,6 +252,7 @@ def fetch_double_register(self, register): self.double_register_inverse_call(CPUFetchCaller(self), register) + self.cycles += 1 def push(self, data, use_cycles=True): # Stack, 2 cycles @@ -272,12 +274,11 @@ def pop_double_register(self, register): # 3 cycles self.double_register_inverse_call(CPUPopCaller(self), register) + self.cycles += 1 def double_register_inverse_call(self, getCaller, register): - b = getCaller.get() # 1 cycle - a = getCaller.get() # 1 cycle - register.set_hi_lo(a, b) # 2 cycles - self.cycles += 1 + register.set_lo(getCaller.get()) # 2 cycles + register.set_hi(getCaller.get()) # 2 cycles def call(self, address, use_cycles=True): # 4 cycles @@ -378,12 +379,14 @@ def xor_a(self, getCaller, setCaller=None): # 1 cycle self.a.set( self.a.get() ^ getCaller.get()) # 1 cycle - self.flag.zero_check(self.a.get(), reset=True) + self.flag.reset() + self.flag.zero_check(self.a.get()) def or_a(self, getCaller, setCaller=None): # 1 cycle self.a.set(self.a.get() | getCaller.get()) # 1 cycle - self.flag.zero_check(self.a.get(), reset=True) + self.flag.reset() + self.flag.zero_check(self.a.get()) def inc_double_register(self, register): # INC rr @@ -487,7 +490,8 @@ # 1 cycle data = getCaller.get() s = ((data << 4) + (data >> 4)) & 0xFF - self.flag.zero_check(s, reset=True) + self.flag.reset() + self.flag.zero_check(s) setCaller.set(s) def test_bit(self, getCaller, setCaller, n): @@ -685,9 +689,7 @@ def ret(self): # RET 4 cycles - lo = self.pop() # 1 cycle - hi = self.pop() # 1 cycle - self.pc.set_hi_lo(hi, lo) # 2 cycles + self.double_register_inverse_call(CPUPopCaller(self), self.pc) def conditional_return(self, cc): # RET cc 2,5 cycles Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu_register.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu_register.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu_register.py Mon Mar 23 18:30:29 2009 @@ -1,114 +1,225 @@ - # --------------------------------------------------------------------------- class AbstractRegister(object): + def __init__(self): + self.invalid = False + def get(self, use_cycles=True): - return 0xFF + self.check_sync() + return self._get(use_cycles) + + def set(self, value, use_cycles=True): + self.check_sync() + self.invalidate_other() + self._set(value, use_cycles) + + def sub(self, value, use_cycles=True): + self.check_sync() + self.invalidate_other() + return self._sub(value, use_cycles) + + def add(self, value, use_cycles=True): + self.check_sync() + self.invalidate_other() + return self._add(value, use_cycles) + + def _get(self, use_cycles): + raise Exception("not implemented") + + def _set(self, value, use_cycles): + raise Exception("not implemented") + + def _sub(self, value, use_cycles): + raise Exception("not implemented") + + def _add(self, value, use_cycles): + raise Exception("not implemented") + + def check_sync(self): + if self.invalid: + self.sync() + + def invalidate_other(self): + raise Exception("not implemented") + + def sync(self): + raise Exception("not implemented") + class Register(AbstractRegister): - def __init__(self, cpu, value=0): + def __init__(self, cpu, value=0x00): + AbstractRegister.__init__(self) # assert isinstance(cpu, CPU) self.reset_value = self.value = value + self.double_register = None self.cpu = cpu if value != 0: - self.set(value) + self._set(value) def reset(self): self.value = self.reset_value - def set(self, value, use_cycles=True): + def sync(self): + if self.double_register is not None: + self.double_register.sync_registers() + + def invalidate_other(self): + if self.double_register is not None: + self.double_register.invalid = True + + def _set(self, value, use_cycles=True): self.value = value & 0xFF if use_cycles: self.cpu.cycles -= 1 - def get(self, use_cycles=True): + def _get(self, use_cycles=True): return self.value - def add(self, value, use_cycles=True): - self.set(self.get(use_cycles)+value, use_cycles) + def _add(self, value, use_cycles=True): + self._set(self._get(use_cycles) + value, use_cycles) - def sub(self, value, use_cycles=True): - self.set(self.get(use_cycles)-value, use_cycles) + def _sub(self, value, use_cycles=True): + self._set(self._get(use_cycles) - value, use_cycles) #------------------------------------------------------------------------------ class DoubleRegister(AbstractRegister): - def __init__(self, cpu, hi, lo, reset_value=0): - #assert isinstance(cpu, CPU) - #assert isinstance(lo, Register) - #assert isinstance(hi, Register) + def __init__(self, cpu, hi, lo, reset_value=0x0000): + AbstractRegister.__init__(self) self.cpu = cpu + self.invalid = True + self.reset_value = reset_value self.hi = hi self.lo = lo - self.reset_value = reset_value - - def set(self, value, use_cycles=True): - # previous = self.get(False) - value = value & 0xFFFF - self.set_hi(value >> 8, use_cycles) - self.set_lo(value & 0xFF, use_cycles) - if use_cycles: - self.cpu.cycles += 1 + self.hi.double_register = self + self.lo.double_register = self + self.value = 0x0000 - def set_hi_lo(self, hi, lo, use_cycles=True): - self.set_hi(hi, use_cycles) - self.set_lo(lo, use_cycles) - def reset(self): self.set(self.reset_value, use_cycles=False) + def sync_registers(self): + self.hi._set(self.value >> 8, use_cycles=False) + self.hi.invalid = False + self.lo._set(self.value & 0xFF, use_cycles=False) + self.lo.invalid = False + + def sync(self): + self.value = (self.hi._get(use_cycles=False)<<8) + \ + self.lo._get(use_cycles=False) + self.invalid = False + + def invalidate_other(self): + self.hi.invalid = True + self.lo.invalid = True + + def _set(self, value, use_cycles=True): + self.value = value & 0xFFFF + if use_cycles: + self.cpu.cycles -= 1 + def set_hi(self, hi=0, use_cycles=True): self.hi.set(hi, use_cycles) def set_lo(self, lo=0, use_cycles=True): self.lo.set(lo, use_cycles) - def get(self, use_cycles=True): - return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles) + def _get(self, use_cycles=True): + return self.value def get_hi(self, use_cycles=True): return self.hi.get(use_cycles) def get_lo(self, use_cycles=True): return self.lo.get(use_cycles) - + def inc(self, use_cycles=True): - self.set(self.get(use_cycles) +1, use_cycles=use_cycles) + self.add(1, use_cycles=False) if use_cycles: - self.cpu.cycles -= 1 - + self.cpu.cycles -= 2 + def dec(self, use_cycles=True): - self.set(self.get(use_cycles) - 1, use_cycles=use_cycles) + self.add(-1, use_cycles=False) + if use_cycles: + self.cpu.cycles -= 2 + + def _add(self, value, use_cycles=True): + self.value += value + self.value &= 0xFFFF + if use_cycles: + self.cpu.cycles -= 3 + +#------------------------------------------------------------------------------ + +class ReservedDoubleRegister(AbstractRegister): + + def __init__(self, cpu, reset_value=0x0000): + AbstractRegister.__init__(self) + self.cpu = cpu + self.reset_value = reset_value + self.value = 0x0000 + + def reset(self): + self.set(self.reset_value, use_cycles=False) + + def set(self, value, use_cycles=True): + self.value = value & 0xFFFF if use_cycles: self.cpu.cycles -= 1 + + def set_hi(self, hi=0, use_cycles=True): + self.set((hi << 8) + (self.value & 0xFF)) + + def set_lo(self, lo=0, use_cycles=True): + self.set((self.value & 0xFF00) + (lo & 0xFF)) - def add(self, value, use_cycles=True): - self.set(self.get(use_cycles) + value, use_cycles=use_cycles) + def get(self, use_cycles=True): + return self.value + + def get_hi(self, use_cycles=True): + return (self.value >> 8) & 0xFF + + def get_lo(self, use_cycles=True): + return self.value & 0xFF + + def inc(self, use_cycles=True): + self.add(1, use_cycles=False) if use_cycles: self.cpu.cycles -= 2 - - + + def dec(self, use_cycles=True): + self.add(-1, use_cycles=False) + if use_cycles: + self.cpu.cycles -= 2 + + def add(self, value, use_cycles=True): + self.value += value + self.value &= 0xFFFF + if use_cycles: + self.cpu.cycles -= 3 + + # ------------------------------------------------------------------------------ class ImmediatePseudoRegister(Register): - def __init__(self, cpu, hl): - #assert isinstance(cpu, CPU) - self.cpu = cpu - self.hl = hl - - def set(self, value, use_cycles=True): - self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0 - if not use_cycles: - self.cpu.cycles += 2 - - def get(self, use_cycles=True): - if not use_cycles: - self.cpu.cycles += 1 - result = self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 - return result + def __init__(self, cpu, hl): + #assert isinstance(cpu, CPU) + self.cpu = cpu + self.hl = hl + + def set(self, value, use_cycles=True): + self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0 + if not use_cycles: + self.cpu.cycles += 2 + + def get(self, use_cycles=True): + if not use_cycles: + self.cpu.cycles += 1 + result = self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 + return result # ------------------------------------------------------------------------------ @@ -149,14 +260,20 @@ (which do not affect C-flag). """ def __init__(self, cpu, reset_value): + Register.__init__(self, cpu) #assert isinstance(cpu, CPU) - self.cpu = cpu self.reset_value = reset_value self.reset() def reset(self): - self.partial_reset() - + self.is_zero = False + self.is_subtraction = False + self.is_half_carry = False + self.is_carry = False + self.p_flag = False + self.s_flag = False + self.lower = 0x00 + def partial_reset(self, keep_is_zero=False, keep_is_subtraction=False, keep_is_half_carry=False, keep_is_carry=False,\ keep_p=False, keep_s=False): @@ -174,16 +291,16 @@ self.s_flag = False self.lower = 0x00 - def get(self, use_cycles=True): + def _get(self, use_cycles=True): value = 0 - value += (int(self.is_carry) << 4) - value += (int(self.is_half_carry) << 5) - value += (int(self.is_subtraction) << 6) - value += (int(self.is_zero) << 7) + value += (int(self.is_carry) << 4) + value += (int(self.is_half_carry) << 5) + value += (int(self.is_subtraction) << 6) + value += (int(self.is_zero) << 7) return value + self.lower - def set(self, value, use_cycles=True): - self.is_carry = bool(value & (1 << 4)) + def _set(self, value, use_cycles=True): + self.is_carry = bool(value & (1 << 4)) self.is_half_carry = bool(value & (1 << 5)) self.is_subtraction = bool(value & (1 << 6)) self.is_zero = bool(value & (1 << 7)) @@ -191,24 +308,13 @@ if use_cycles: self.cpu.cycles -= 1 - def zero_check(self, a, reset=False): - if reset: - self.reset() - if isinstance(a, (Register)): - a = a.get() - self.is_zero = ((a & 0xFF) == 0) + def zero_check(self, value): + self.is_zero = ((value & 0xFF) == 0) def is_carry_compare(self, value, compare_and=0x01, reset=False): if reset: self.reset() self.is_carry = ((value & compare_and) != 0) - def is_half_carry_compare(self, value, a, inverted=False): - if inverted: - self.is_half_carry = ((value & 0x0F) < (a & 0x0F)) - else: - self.is_half_carry = ((value & 0x0F) > (a & 0x0F)) - - #def is_carry_compare(self, a, b): - # self.is_carry = (a < b) - + def is_half_carry_compare(self, new, old): + self.is_half_carry = (old & 0x0F) < (new & 0x0F) Copied: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug.py (from r58379, pypy/dist/pypy/lang/gameboy/debug/debug.py) ============================================================================== --- pypy/dist/pypy/lang/gameboy/debug/debug.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug.py Mon Mar 23 18:30:29 2009 @@ -1,4 +1,6 @@ import operator +from pypy.lang.gameboy import cpu +import pdb DEBUG = True DEBUG_PRINT_LOGS = True @@ -86,16 +88,18 @@ CHECKED_OP_CODES = [0x00] CHECKED_FETCH_OP_CODES = [] +BAR_WIDTH = 79 +PRINT_OPCODE=True def log(opCode, is_fetch_execute=False): global COUNT, op_codes, fetch_execute_op_codes if DEBUG_PRINT_LOGS: - print "="*40 + print "=" * BAR_WIDTH if is_fetch_execute: - print COUNT[0], " FETCH EXEC: %i | %s" % (opCode, hex(opCode)) + print COUNT[0], " FETCH EXEC: %i | %s | %s" % (opCode, hex(opCode), resolve_fetch_opcode_name(opCode)) else: - print COUNT[0], " EXEC: %i | %s" % (opCode, hex(opCode)) - print "-"*40 + print COUNT[0], " EXEC: %i | %s | %s" % (opCode, hex(opCode), resolve_opcode_name(opCode)) + print "-" * BAR_WIDTH if is_fetch_execute: fetch_execute_op_codes[opCode ]+= 1 @@ -105,21 +109,43 @@ #if COUNT % 1000 == 0: # print "." - +def resolve_opcode_name(opcode): + method = cpu.OP_CODES[opcode].__name__ + if method == "": + try: + functions = "[ " + for func_closure in cpu.OP_CODES[opcode].func_closure: + functions += func_closure.cell_contents.im_func.__name__+ ", "; + return functions + "]"; + except: + return cpu.OP_CODES[opcode].func_code.co_names; + else: + return method; + +def resolve_fetch_opcode_name(opcode): + method = cpu.OP_CODES[opcode].__name__ + if method == "": + pdb.set_trace() + else: + return method; + + def print_results(): global COUNT, op_codes, fetch_execute_op_codes - codes = zip(map(lambda x: "%4s" % hex(x), range(len(op_codes))), op_codes) - - fetch_exec_keys = map(lambda x: "%4s %4s" % (hex(x[0]), hex(x[1])), - zip([0x83]*len(fetch_execute_op_codes), - range(len(fetch_execute_op_codes)))) + print_function = (lambda x: "%4s" % hex(x)) + codes = zip(map( print_function, range(len(op_codes))), op_codes) + print_function = (lambda x: "%4s %4s" % (hex(x[0]), hex(x[1]))) + opcode_range = range(len(fetch_execute_op_codes)) + arguments = zip([0x83] * len(fetch_execute_op_codes), opcode_range) + fetch_exec_keys = map( print_function, opcode_range, arguments ) + # Append the fetchexecuted opcodes to the list codes.extend(zip(fetch_exec_keys, fetch_execute_op_codes)) codes = sorted(codes, key=operator.itemgetter(1)) for code in codes: if code[1] != 0: - print "%8s : %s" % (code[0], code[1]) + print "%8s \t %s" % (code[0], code[1]) \ No newline at end of file Copied: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug_rpc_xml_memory.py (from r58379, pypy/dist/pypy/lang/gameboy/debug/debug_rpc_xml_memory.py) ============================================================================== --- pypy/dist/pypy/lang/gameboy/debug/debug_rpc_xml_memory.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/debug/debug_rpc_xml_memory.py Mon Mar 23 18:30:29 2009 @@ -74,6 +74,7 @@ # RPC =================================================================== def close(self): + pdb.set_trace() if not self.is_closed: print "python: called close" self.server_close() @@ -146,7 +147,7 @@ @printframe("comparing registers") def compare_registers(self, registers): - for reg in [("a", self.cpu.a.get()), ("f", self.cpu.f.get()), + for reg in [("a", self.cpu.a.get()), ("f", self.cpu.flag.get()), ("b", self.cpu.b.get()), ("c", self.cpu.c.get()), ("d", self.cpu.d.get()), ("e", self.cpu.e.get()), ("h", self.cpu.h.get()), ("l", self.cpu.l.get()), @@ -227,21 +228,21 @@ self.gameboy_debug.video.object_palette_1, \ video["obp1"]) self.print_check("video scx", \ - self.gameboy_debug.video.scroll_x, video["scx"]) + self.gameboy_debug.video.background.scroll_x, video["scx"]) self.print_check("video scy", \ - self.gameboy_debug.video.scroll_y, video["scy"]) + self.gameboy_debug.video.background.scroll_y, video["scy"]) self.print_check("video stat", \ self.gameboy_debug.video.status.read(), video["stat"]) self.print_check("video transfer", \ self.gameboy_debug.video.transfer, video["transfer"]) self.print_check("video vblank", \ - self.gameboy_debug.video.vblank, video["vblank"]) + self.gameboy_debug.video.v_blank, video["vblank"]) self.print_check("video wly", \ - self.gameboy_debug.video.window_line_y, video["wly"]) + self.gameboy_debug.video.window.line_y, video["wly"]) self.print_check("video wx", \ - self.gameboy_debug.video.window_x, video["wx"]) + self.gameboy_debug.video.window.x, video["wx"]) self.print_check("video wy", \ - self.gameboy_debug.video.window_y, video["wy"]) + self.gameboy_debug.video.window.y, video["wy"]) @printframe("comparing timer") def compare_timer(self, data): @@ -286,7 +287,8 @@ def compare_memory(self, name, expected, new): self.print_check(name+" length", len(expected), len(new)) if len(expected) != len(new): return - for address in range(len(expected)): + # only check every 3rd in order to speed things up + for address in range(0, len(expected), 3): self.print_check(name+" value at "+hex(address), \ expected[address], new[address]) @@ -325,9 +327,7 @@ if self.pending_steps > 0: self.pending_steps -= 1 return - #self.prompt_for_user_input() - - + self.prompt_for_user_input() def prompt_for_user_input(self): if self.showed_skip_message_count < 2: @@ -337,6 +337,8 @@ try: if int(read) > 0: self.pending_steps = int(read) + if read == "pdb": + pdb.set_trace() except Exception: if ("stop" in read) or ("exit" in read) or (read is "Q"): raise Exception("Debug mode Stopped by User") Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy.py Mon Mar 23 18:30:29 2009 @@ -38,8 +38,8 @@ self.timer = Timer(self.interrupt) self.joypad = Joypad(self.joypad_driver, self.interrupt) self.video = Video(self.video_driver, self.interrupt, self) - self.sound = Sound(self.sound_driver) - #self.sound = BogusSound() + #self.sound = Sound(self.sound_driver) + self.sound = BogusSound() def get_cartridge_manager(self): return self.cartridge_manager Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/gameboy_implementation.py Mon Mar 23 18:30:29 2009 @@ -12,16 +12,18 @@ from pypy.lang.gameboy import constants import time -show_metadata = False # Extends the window with windows visualizing meta-data +show_metadata = True # Extends the window with windows visualizing meta-data if constants.USE_RSDL: - from pypy.rlib.rsdl import RSDL, RSDL_helper, RMix + from pypy.rlib.rsdl import RSDL, RSDL_helper #, RMix from pypy.rpython.lltypesystem import lltype, rffi delay = RSDL.Delay get_ticks = RSDL.GetTicks else: delay = time.sleep +FPS = 1<<6 # About 1<<6 to make sure we have a clean distrubution of about + # 1<<6 frames per second from pypy.rlib.objectmodel import specialize @@ -65,13 +67,11 @@ return 0 def emulate_cycle(self): - X = 1<<6 # About 1<<6 to make sure we have a clean distrubution of about - # 1<<6 frames per second self.handle_events() - # Come back to this cycle every 1/X seconds - self.emulate(constants.GAMEBOY_CLOCK / X) + # Come back to this cycle every 1/FPS seconds + self.emulate(constants.GAMEBOY_CLOCK / FPS) spent = int(time.time()) - self.sync_time - left = int(1000.0/X) + self.penalty - spent + left = int(1000.0/FPS) + self.penalty - spent if left > 0: delay(left) self.penalty = 0 @@ -260,18 +260,20 @@ SoundDriver.__init__(self) self.enabled = False self.sampleRate = 44100 - self.chunksize = 1024 + self.buffersize = 512 self.channelCount = 2 self.bitsPerSample = 4 + self.sampleSize = self.bitsPerSample * self.channelCount self.create_sound_driver() def create_sound_driver(self): - if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, - self.channelCount, self.chunksize) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - else: - self.enabled = True + #if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, + # self.channelCount, self.chunksize) != 0: + # error = rffi.charp2str(RSDL.GetError()) + # raise Exception(error) + #else: + # self.enabled = True + pass def start(self): pass Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Mon Mar 23 18:30:29 2009 @@ -1,48 +1,37 @@ #!/usr/bin/env python -from __future__ import generators -from pypy.lang.gameboy.ram import iMemory -from pypy.lang.gameboy.gameboy_implementation import * -from pypy.lang.gameboy.profiling.profiling_cpu import ProfilingCPU -from pypy.lang.gameboy.debug import debug -from pypy.lang.gameboy.debug.debug_socket_memory import * +from pypy.lang.gameboy.gameboy import GameBoy +from pypy.lang.gameboy.joypad import JoypadDriver +from pypy.lang.gameboy.video import VideoDriver +from pypy.lang.gameboy.sound import SoundDriver +from pypy.lang.gameboy.timer import Clock +from pypy.lang.gameboy import constants + +from pypy.rlib.objectmodel import specialize # GAMEBOY ---------------------------------------------------------------------- -class GameBoyProfilingImplementation(GameBoyImplementation): - - def __init__(self, op_codes): - GameBoyImplementation.__init__(self) - self.op_codes = op_codes - self.cycleLimit = cycleLimit - self.cpu = ProfilingCPU(self.interrupt, self) - self.cpu.cycle_limit = cycleLimit - - def handle_execution_error(self): - self.is_running = False - debug.print_results() - +FPS = 1 << 6 -# CUSTOM DRIVER IMPLEMENTATIONS currently not used ============================= - +class GameBoyProfiler(GameBoy): -# VIDEO DRIVER ----------------------------------------------------------------- - -class VideoDriverDebugImplementation(VideoDriverImplementation): - pass - - -# JOYPAD DRIVER ---------------------------------------------------------------- + def __init__(self): + GameBoy.__init__(self) + self.is_running = False -class JoypadDriverDebugImplementation(JoypadDriverImplementation): - pass - - -# SOUND DRIVER ----------------------------------------------------------------- -class SoundDriverDebugImplementation(SoundDriverImplementation): - pass - + def create_drivers(self): + self.clock = Clock() + self.joypad_driver = JoypadDriver() + self.video_driver = VideoDriver() + self.sound_driver = SoundDriver() + + def mainLoop(self, execution_seconds): + self.reset() + self.is_running = True + for i in range(int(execution_seconds * FPS)): + self.emulate_cycle() -# ============================================================================== + def emulate_cycle(self): + self.emulate(constants.GAMEBOY_CLOCK / FPS) Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py Mon Mar 23 18:30:29 2009 @@ -431,7 +431,8 @@ # ld_BCi_A def test_0x02(): cpu = get_cpu(); - cpu.bc.set_hi_lo(0xC2, 0x23); + cpu.bc.set_hi(0xC2) + cpu.bc.set_lo(0x23); cpu.a.set(0x12); cycle_test(cpu, 0x02, 2); assert cpu.read(cpu.bc.get()) == cpu.a.get() @@ -451,7 +452,8 @@ # ld_DEi_A def test_0x12(): cpu = get_cpu(); - cpu.de.set_hi_lo(0xC2, 0x23); + cpu.de.set_hi(0xC2) + cpu.de.set_lo(0x23); cpu.a.set(0x12); cycle_test(cpu, 0x12, 2); assert cpu.read(cpu.de.get()) == cpu.a.get() @@ -470,7 +472,8 @@ # ldi_HLi_A def test_0x22(): cpu = get_cpu(); - cpu.hl.set_hi_lo(0xCD, 0xEF); + cpu.hl.set_hi(0xCD) + cpu.hl.set_lo(0xEF); cpu.a.set(0x12); cycle_test(cpu, 0x22, 2); assert cpu.read(0xCDEF) == cpu.a.get() @@ -479,7 +482,8 @@ # ldd_HLi_A def test_0x32(): cpu = get_cpu(); - cpu.hl.set_hi_lo(0xCD, 0xEF); + cpu.hl.set_hi(0xCD) + cpu.hl.set_lo(0xEF); cpu.a.set(0x12); cycle_test(cpu, 0x32, 2); assert cpu.read(0xCDEF) == cpu.a.get() @@ -881,8 +885,9 @@ cpu = get_cpu() opCode = 0x98 value = 0x12 - registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] + registers = ["b", "c", "d", "e", "h", "l", "hli", "a"] for register in registers: + register = cpu.__dict__[register] cpu.reset() cpu.a.set(value) register.set(value) @@ -896,11 +901,11 @@ cpu.flag.is_carry = True cpu.a.set(value+1) register.set(value) - numCycles= 1 + numCycles = 1 if register == cpu.hli: numCycles = 2 cycle_test(cpu, opCode, numCycles) - if register == cpu.a: + if register is cpu.a: assert cpu.a.get() == 0xFF else: assert cpu.a.get() == 0 Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_register.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_register.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_register.py Mon Mar 23 18:30:29 2009 @@ -26,9 +26,14 @@ TEST_CPU = get_cpu(True) TEST_CPU.reset() return TEST_CPU + +def get_double_register(): + cpu = get_cpu() + return DoubleRegister(cpu, Register(cpu), Register(cpu)) # ------------------------------------------------------------ # TEST REGISTER + def test_register_constructor(): register = Register(get_cpu()) assert register.get() == 0 @@ -103,7 +108,8 @@ valueHi = 0x12 valueLo = 0x34 oldCycles = register.cpu.cycles - register.set_hi_lo(valueHi, valueLo) + register.set_hi(valueHi) + register.set_lo(valueLo) assert oldCycles-register.cpu.cycles == 2 assert register.get_hi() == valueHi assert register.get_lo() == valueLo @@ -161,4 +167,82 @@ assert register.get() == value+1; register.reset() assert register.get() == value - \ No newline at end of file + + +# TEST REGISTER SYNCING ----------------------------------------------------- + +def test_register_sync(): + double_register = get_double_register() + assert double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + return double_register + +def test_register_sync_get(): + double_register = test_register_sync() + + double_register.get() + + assert not double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set(): + double_register = test_register_sync() + + double_register.set(0xFFFF) + + assert not double_register.invalid + assert double_register.hi.invalid + assert double_register.lo.invalid + + return double_register + + +def test_register_sync_set_get(): + double_register = test_register_sync_set() + + assert double_register.get() == 0xFFFF + + assert not double_register.invalid + assert double_register.hi.invalid + assert double_register.lo.invalid + + +def test_register_sync_set_get_hi(): + double_register = test_register_sync_set() + + assert double_register.hi.get() == 0xFF + + assert not double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set_get_lo(): + double_register = test_register_sync_set() + + assert double_register.lo.get() == 0xFF + + assert not double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set_hi(): + double_register = test_register_sync() + double_register.hi.set(0x12) + + assert double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid + + +def test_register_sync_set_lo(): + double_register = test_register_sync() + double_register.lo.set(0x12) + + assert double_register.invalid + assert not double_register.hi.invalid + assert not double_register.lo.invalid Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_video.py Mon Mar 23 18:30:29 2009 @@ -39,7 +39,6 @@ assert video.background.scroll_y == 0 assert video.window.x == 0 assert video.window.y == 0 - assert video.window.line_y == 0 assert video.background_palette == 0xFC assert video.object_palette_0 == 0xFF assert video.object_palette_1 == 0xFF @@ -181,7 +180,8 @@ video.write(0xFF40, 0x80+0x20) assert video.control.read() == 0x80+0x20 - assert video.window.line_y == 144 + # assert video.window.line_y == 144 # We don't jump, we just adjust and + # # start drawing where we are. def test_control_reset1(): video = get_video() Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/video.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/video.py Mon Mar 23 18:30:29 2009 @@ -468,6 +468,8 @@ window.draw_clean_line(self.line) def draw_line(self): + # XXX We should check if this is necessary for each line. + self.update_palette() self.draw_window(self.background, self.line_y, self.line) self.draw_window(self.window, self.line_y, self.line) self.draw_sprites(self.line_y, self.line) @@ -506,7 +508,6 @@ self.shown_sprites[highest], self.shown_sprites[index] def send_pixels_line_to_driver(self): - self.update_palette() for x in range(0, GAMEBOY_SCREEN_WIDTH): color = self.palette[self.line[SPRITE_SIZE + x]] self.driver.draw_gb_pixel(x, self.line_y, color) From arigo at codespeak.net Mon Mar 23 19:35:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 19:35:31 +0100 (CET) Subject: [pypy-svn] r63250 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp Message-ID: <20090323183531.95DCF168049@codespeak.net> Author: arigo Date: Mon Mar 23 19:35:29 2009 New Revision: 63250 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Log: Bridges start to work too. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Mon Mar 23 19:35:29 2009 @@ -6,7 +6,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rpython.llinterp import LLInterpreter from pypy.jit.metainterp import history -from pypy.jit.metainterp.resoperation import ResOperation, rop, GuardFailure +from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.backend.llgraph import llimpl, symbolic @@ -126,8 +126,7 @@ def execute_operations(self, loop, valueboxes): """Calls the assembler generated for the given loop. - Typically returns an instance of 'resoperation.GuardFailure'; - may also raise an exception if the assembler code raises. + Returns the ResOperation that failed, of type rop.FAIL. """ frame = llimpl.new_frame(self.memo_cast) # setup the frame @@ -149,19 +148,17 @@ # (in a real backend, this should be done by the FAIL operation # itself, not here) op = self.fail_ops[fail_index] - currentboxes = [] for i in range(len(op.args)): box = op.args[i] if isinstance(box, history.BoxInt): value = llimpl.frame_int_getvalue(frame, i) - box = history.BoxInt(value) + box.changevalue_int(value) elif isinstance(box, history.BoxPtr): value = llimpl.frame_ptr_getvalue(frame, i) - box = history.BoxPtr(value) + box.changevalue_ptr(value) else: raise Exception("bad box in 'fail': %r" % (box,)) - currentboxes.append(box) - return GuardFailure(op.key, currentboxes) + return op def get_exception(self): return self.cast_adr_to_int(llimpl.get_exception()) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 19:35:29 2009 @@ -24,21 +24,20 @@ else: return _compile_new_loop_1(metainterp, loop, old_loops, endliveboxes) -def compile_new_bridge(metainterp, old_loops, endliveboxes): +def compile_new_bridge(metainterp, old_loops, endliveboxes, resumekey): """Try to compile a new bridge leading from the beginning of the history to some existing place. """ - bridge = create_empty_bridge(metainterp) if we_are_translated(): try: - bridge = compile_fresh_bridge(metainterp, bridge, old_loops, - endliveboxes) - return bridge + target_loop = compile_fresh_bridge(metainterp, old_loops, + endliveboxes, resumekey) + return target_loop except optimize.CancelInefficientLoop: return None else: - return _compile_new_bridge_1(metainterp, bridge, old_loops, - endliveboxes) + return _compile_new_bridge_1(metainterp, old_loops, + endliveboxes, resumekey) class BridgeInProgress(Exception): pass @@ -64,29 +63,26 @@ loop.check_consistency() return loop -def _compile_new_bridge_1(metainterp, bridge, old_loops, endliveboxes): - orgbridge = bridge +def _compile_new_bridge_1(metainterp, old_loops, endliveboxes, resumekey): try: try: - bridge = compile_fresh_bridge(metainterp, bridge, old_loops, - endliveboxes) + target_loop = compile_fresh_bridge(metainterp, old_loops, + endliveboxes, resumekey) except Exception, exc: - show_loop(metainterp, bridge, error=exc) + show_loop(metainterp, error=exc) raise else: - if bridge == orgbridge: - show_loop(metainterp, bridge) - elif bridge is not None: - log.info("reusing bridge at %r" % (bridge,)) - else: + if target_loop is None: log.info("compile_fresh_bridge() returned None") + else: + show_loop(metainterp, target_loop) except optimize.CancelInefficientLoop: return None - if bridge is not None: - bridge.check_consistency() - return bridge + if target_loop is not None: + target_loop.check_consistency() + return target_loop -def show_loop(metainterp, loop, error=None): +def show_loop(metainterp, loop=None, error=None): # debugging if option.view: if error: @@ -95,7 +91,10 @@ errmsg += ': ' + str(error) else: errmsg = None - loop.show(errmsg=errmsg) + if loop is None: + metainterp.stats.view(errmsg=errmsg) + else: + loop.show(errmsg=errmsg) def create_empty_loop(metainterp): if we_are_translated(): @@ -107,6 +106,10 @@ # ____________________________________________________________ def compile_fresh_loop(metainterp, loop, old_loops, endliveboxes): + # ------ + if old_loops: + return old_loops[0] + # ------ history = metainterp.history loop.inputargs = history.inputargs loop.operations = history.operations @@ -115,7 +118,9 @@ # metainterp.cpu) #if old_loop is not None: # return old_loop + mark_keys_in_loop(loop, loop.operations) send_loop_to_backend(metainterp, loop) + metainterp.stats.loops.append(loop) old_loops.append(loop) return loop @@ -124,30 +129,39 @@ op.jump_target = loop loop.operations.append(op) +def mark_keys_in_loop(loop, operations): + op = None + for op in operations: + if op.is_guard(): + mark_keys_in_loop(loop, op.suboperations) + if op.opnum == rop.FAIL: + op.key.loop = loop + def send_loop_to_backend(metainterp, loop): metainterp.cpu.compile_operations(loop) - metainterp.stats.loops.append(loop) # ____________________________________________________________ def matching_merge_point(metainterp, targetmp, endliveboxes): return True -def compile_fresh_bridge(metainterp, bridge, old_loops, endliveboxes): +def compile_fresh_bridge(metainterp, old_loops, endliveboxes, resumekey): history = metainterp.history - catch_op = history.operations[0] - assert catch_op.opnum == rop.CATCH - guard_op = catch_op.coming_from - assert guard_op.is_guard() # - operations = bridge.operations = history.operations op = ResOperation(rop.JUMP, endliveboxes, None) - operations.append(op) + history.operations.append(op) # - old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge, - metainterp.cpu) - if old_loop is None: - return None - bridge.jump_to = old_loop - finish_loop_or_bridge(metainterp, bridge, old_loop.operations[0], guard_op) - return bridge + #old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge, + # metainterp.cpu) + #if old_loop is None: + # return None + # ------ + target_loop = old_loops[0] + op.jump_target = target_loop + # ------ + source_loop = resumekey.loop + guard_op = resumekey.guard_op + guard_op.suboperations = history.operations + mark_keys_in_loop(source_loop, guard_op.suboperations) + send_loop_to_backend(metainterp, source_loop) + return target_loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 19:35:29 2009 @@ -295,6 +295,8 @@ def _getrepr_(self): return self.value + changevalue_int = __init__ + class BoxPtr(Box): type = 'ptr' @@ -315,6 +317,7 @@ return lltype.cast_ptr_to_int(self.value) _getrepr_ = repr_pointer + changevalue_ptr = __init__ NULLBOX = BoxPtr() Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 19:35:29 2009 @@ -634,8 +634,9 @@ return saved_pc = self.pc self.pc = pc - # XXX 'key' should be shared, either partially or if possible totally - key = [] + # XXX 'resume_info' should be shared, either partially or + # if possible totally + resume_info = [] liveboxes = [] for frame in self.metainterp.framestack: const_part = [] @@ -645,14 +646,13 @@ liveboxes.append(framebox) framebox = None const_part.append(framebox) - key.append((frame.jitcode, frame.pc, const_part, - frame.exception_target)) + resume_info.append((frame.jitcode, frame.pc, const_part, + frame.exception_target)) if box is not None: extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opnum, extraargs, None) op = history.ResOperation(rop.FAIL, liveboxes, None) - op.key = Key(key, opnum in (rop.GUARD_EXCEPTION, - rop.GUARD_NO_EXCEPTION)) + op.key = ResumeKey(guard_op, resume_info) guard_op.suboperations = [op] self.pc = saved_pc return guard_op @@ -828,16 +828,17 @@ return self.designate_target_loop(gmp, compiled_loop) def handle_guard_failure(self, guard_failure): - orig_boxes = self.initialize_state_from_guard_failure(guard_failure) + self.initialize_state_from_guard_failure(guard_failure) + key = guard_failure.key try: - if guard_failure.key.is_exception_catch: + if key.guard_op.opnum in (rop.GUARD_NO_EXCEPTION, + rop.GUARD_EXCEPTION): self.handle_exception() self.interpret() assert False, "should always raise" except GenerateMergePoint, gmp: - compiled_bridge = self.compile_bridge(guard_failure, orig_boxes, - gmp.argboxes) - return self.designate_target_loop(gmp, compiled_bridge.jump_to) + target_loop = self.compile_bridge(key, gmp.argboxes) + return self.designate_target_loop(gmp, target_loop) def designate_target_loop(self, gmp, loop): num_green_args = self.num_green_args @@ -865,27 +866,23 @@ self.debug_history = [] return loop - def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes): - XXX + def compile_bridge(self, key, live_arg_boxes): num_green_args = self.num_green_args - mp = history.ResOperation(rop.CATCH, original_boxes, None) - mp.coming_from = guard_failure.guard_op - self.history.operations.insert(0, mp) + greenkey = live_arg_boxes[:num_green_args] try: - old_loops = self.compiled_merge_points[ - live_arg_boxes[:num_green_args]] + old_loops = self.compiled_merge_points[greenkey] except KeyError: - bridge = None + target_loop = None else: - bridge = compile_new_bridge(self, old_loops, - live_arg_boxes[num_green_args:]) - if bridge is None: + target_loop = compile_new_bridge(self, old_loops, + live_arg_boxes[num_green_args:], + key) + if target_loop is None: raise self.ContinueRunningNormally(live_arg_boxes) if not we_are_translated(): - bridge._call_history = self._debug_history + #bridge._call_history = self._debug_history self.debug_history = [] - guard_failure.guard_op.jump_target = bridge.operations[0] - return bridge + return target_loop def get_residual_args(self, loop, args): if loop.specnodes is None: # it is None only for tests @@ -933,19 +930,19 @@ def initialize_state_from_guard_failure(self, guard_failure): # guard failure: rebuild a complete MIFrame stack - if self.state.must_compile_from_failure(guard_failure): + if self.state.must_compile_from_failure(guard_failure.key): self.history = history.History(self.cpu) else: self.history = history.BlackHole(self.cpu) - boxes_from_frame = guard_failure.currentboxes + boxes_from_frame = guard_failure.args if 0: # xxx guard_op.rebuild_ops is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( guard_op, self.cpu, self.history, boxes_from_frame) else: # xxx for tests only newboxes = boxes_from_frame - self.rebuild_state_after_failure(guard_failure.key.key, newboxes) - return boxes_from_frame + self.rebuild_state_after_failure(guard_failure.key.resume_info, + newboxes) def handle_exception(self): etype = self.cpu.get_exception() @@ -964,12 +961,12 @@ frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, []) return False - def rebuild_state_after_failure(self, key, newboxes): + def rebuild_state_after_failure(self, resume_info, newboxes): if not we_are_translated(): self._debug_history.append(['guard_failure', None, None]) self.framestack = [] nbindex = 0 - for jitcode, pc, const_part, exception_target in key: + for jitcode, pc, const_part, exception_target in resume_info: f = self.newframe(jitcode) nbindex = f.setup_resume_at_op(pc, const_part, newboxes, nbindex, exception_target) @@ -998,8 +995,9 @@ def __init__(self, args): self.argboxes = args -class Key(object): - def __init__(self, key, is_exception_catch): - self.key = key +class ResumeKey(object): + def __init__(self, guard_op, resume_info): + self.resume_info = resume_info + self.guard_op = guard_op self.counter = 0 - self.is_exception_catch = is_exception_catch + # self.loop = ... set in compile.py Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Mon Mar 23 19:35:29 2009 @@ -43,12 +43,6 @@ return '%s%s(%s)' % (sres, self.getopname(), ', '.join([str(a) for a in self.args])) - def clone(self): - op = ResOperation(self.opnum, self.args, self.result, self.descr) - op.specnodes = self.specnodes - op.key = self.key - return op - def getopname(self): try: return opname[self.opnum].lower() @@ -79,14 +73,6 @@ # ____________________________________________________________ -class GuardFailure(object): - def __init__(self, key, currentboxes): - self.key = key - self.currentboxes = currentboxes - -# ____________________________________________________________ - - class rop(object): """The possible names of the ResOperations.""" Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Mon Mar 23 19:35:29 2009 @@ -502,9 +502,8 @@ guard_failure = cpu.execute_operations(loop, boxes) loop, boxes = metainterp.handle_guard_failure(guard_failure) - def must_compile_from_failure(self, guard_failure): - key_holder = guard_failure.key - key_holder.counter += 1 - return key_holder.counter >= self.trace_eagerness + def must_compile_from_failure(self, key): + key.counter += 1 + return key.counter >= self.trace_eagerness return WarmEnterState From cami at codespeak.net Mon Mar 23 20:10:04 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 23 Mar 2009 20:10:04 +0100 (CET) Subject: [pypy-svn] r63254 - in pypy/trunk/pypy/lang/gameboy/profiling: . evaluation Message-ID: <20090323191004.DF378168443@codespeak.net> Author: cami Date: Mon Mar 23 20:10:04 2009 New Revision: 63254 Modified: pypy/trunk/pypy/lang/gameboy/profiling/evaluation/evaluation_cpu.py pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_implementation.py pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_target.py pypy/trunk/pypy/lang/gameboy/profiling/gameboyTest.py Log: removing some strange imports Modified: pypy/trunk/pypy/lang/gameboy/profiling/evaluation/evaluation_cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/evaluation/evaluation_cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/evaluation/evaluation_cpu.py Mon Mar 23 20:10:04 2009 @@ -1,7 +1,6 @@ from __future__ import generators from pypy.lang.gameboy.cpu import CPU -from pypy.lang.gameboy.debug import debug class EvaluationCPU(CPU): Modified: pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_implementation.py Mon Mar 23 20:10:04 2009 @@ -1,6 +1,5 @@ #!/usr/bin/env python -from pypy.lang.gameboy.debug import debug from pypy.lang.gameboy.gameboy_implementation import * from pypy.lang.gameboy.debug.debug_socket_memory import * from pypy.lang.gameboy.profiling.evaluation.evaluation_cpu import EvaluationCPU Modified: pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_target.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_target.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/evaluation/gameboy_evaluation_target.py Mon Mar 23 20:10:04 2009 @@ -1,5 +1,4 @@ -from pypy.lang.gameboy.debug import debug from pypy.lang.gameboy.profiling.evaluation.gameboy_evaluation_implementation import * import py import sys Modified: pypy/trunk/pypy/lang/gameboy/profiling/gameboyTest.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/profiling/gameboyTest.py (original) +++ pypy/trunk/pypy/lang/gameboy/profiling/gameboyTest.py Mon Mar 23 20:10:04 2009 @@ -1,5 +1,4 @@ from pypy.lang.gameboy.profiling.gameboy_profiling_implementation import * -from pypy.lang.gameboy.debug import debug import py import sys From arigo at codespeak.net Mon Mar 23 20:26:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 20:26:26 +0100 (CET) Subject: [pypy-svn] r63255 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp Message-ID: <20090323192626.EA6591684F6@codespeak.net> Author: arigo Date: Mon Mar 23 20:26:24 2009 New Revision: 63255 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Log: RPython fixes. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py Mon Mar 23 20:26:24 2009 @@ -948,6 +948,7 @@ setannotation(compile_add_ptr_result, annmodel.SomeInteger()) setannotation(compile_add_jump_target, annmodel.s_None) setannotation(compile_add_fail, annmodel.s_None) +setannotation(compile_suboperations, s_CompiledLoop) setannotation(new_frame, s_Frame) setannotation(frame_clear, annmodel.s_None) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Mon Mar 23 20:26:24 2009 @@ -117,6 +117,7 @@ else: raise Exception("%s.result contain: %r" % (op.getopname(), x)) + op = operations[-1] assert op.is_final() if op.opnum == rop.JUMP: llimpl.compile_add_jump_target(c, op.jump_target._compiled_version) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 20:26:24 2009 @@ -130,10 +130,10 @@ loop.operations.append(op) def mark_keys_in_loop(loop, operations): - op = None for op in operations: if op.is_guard(): mark_keys_in_loop(loop, op.suboperations) + op = operations[-1] if op.opnum == rop.FAIL: op.key.loop = loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 20:26:24 2009 @@ -209,6 +209,7 @@ class ConstPtr(Const): type = 'ptr' + value = lltype.nullptr(llmemory.GCREF.TO) def __init__(self, value): assert lltype.typeOf(value) == llmemory.GCREF Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 20:26:24 2009 @@ -887,7 +887,8 @@ def get_residual_args(self, loop, args): if loop.specnodes is None: # it is None only for tests return args - xxx + assert 0, "XXX fix me" + # --- assert len(mp.specnodes) == len(args) expanded_args = [] for i in range(len(mp.specnodes)): From arigo at codespeak.net Mon Mar 23 20:45:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 20:45:00 +0100 (CET) Subject: [pypy-svn] r63256 - pypy/trunk/pypy/interpreter/pyparser/test Message-ID: <20090323194500.C7F001684E2@codespeak.net> Author: arigo Date: Mon Mar 23 20:45:00 2009 New Revision: 63256 Modified: pypy/trunk/pypy/interpreter/pyparser/test/test_parser.py Log: Remove dead import. Modified: pypy/trunk/pypy/interpreter/pyparser/test/test_parser.py ============================================================================== --- pypy/trunk/pypy/interpreter/pyparser/test/test_parser.py (original) +++ pypy/trunk/pypy/interpreter/pyparser/test/test_parser.py Mon Mar 23 20:45:00 2009 @@ -1,7 +1,6 @@ from pypy.interpreter.pyparser.asthelper import get_atoms from pypy.interpreter.pyparser.grammar import Parser from pypy.interpreter.pyparser import error -from fakes import FakeSpace def test_symbols(): From arigo at codespeak.net Mon Mar 23 21:22:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 21:22:58 +0100 (CET) Subject: [pypy-svn] r63257 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090323202258.3B77516845B@codespeak.net> Author: arigo Date: Mon Mar 23 21:22:55 2009 New Revision: 63257 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Log: Make optimize.py pass again (first step). Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 21:22:55 2009 @@ -5,7 +5,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.history import Loop, log, Box +from pypy.jit.metainterp.history import TreeLoop, log, Box from pypy.jit.metainterp import optimize @@ -101,7 +101,7 @@ name = 'Loop' else: name = 'Loop #%d' % len(metainterp.stats.loops) - return Loop(name) + return TreeLoop(name) # ____________________________________________________________ @@ -114,13 +114,14 @@ loop.inputargs = history.inputargs loop.operations = history.operations close_loop(loop, endliveboxes) - #old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, - # metainterp.cpu) - #if old_loop is not None: - # return old_loop + old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, + metainterp.cpu) + if old_loop is not None: + return old_loop mark_keys_in_loop(loop, loop.operations) send_loop_to_backend(metainterp, loop) metainterp.stats.loops.append(loop) + metainterp.stats.compiled_count += 1 old_loops.append(loop) return loop @@ -164,4 +165,5 @@ guard_op.suboperations = history.operations mark_keys_in_loop(source_loop, guard_op.suboperations) send_loop_to_backend(metainterp, source_loop) + metainterp.stats.compiled_count += 1 return target_loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 21:22:55 2009 @@ -324,11 +324,11 @@ # ____________________________________________________________ -# The Loop class contains a loop or a generalized loop, i.e. a tree +# The TreeLoop class contains a loop or a generalized loop, i.e. a tree # of operations. Each branch ends in a jump which can go either to -# the top of the same loop, or to another loop. +# the top of the same loop, or to another TreeLoop. -class Loop(object): +class TreeLoop(object): inputargs = None specnodes = None operations = None @@ -340,18 +340,16 @@ # ops of the kind 'guard_xxx' contain a further list of operations, # which may itself contain 'guard_xxx' and so on, making a tree. - def _all_operations(self): + def _all_operations(self, omit_fails=False): "NOT_RPYTHON" - oplist = list(self.operations) - for op in oplist: - if op.is_guard(): - oplist += op.suboperations - return oplist + result = [] + _list_all_operations(result, self.operations, omit_fails) + return result def summary(self, adding_insns={}): # for debugging "NOT_RPYTHON" insns = adding_insns.copy() - for op in self._all_operations(): + for op in self._all_operations(omit_fails=True): opname = op.getopname() insns[opname] = insns.get(opname, 0) + 1 return insns @@ -392,11 +390,19 @@ seen[box] = True assert operations[-1].is_final() if operations[-1].opnum == rop.JUMP: - assert isinstance(operations[-1].jump_target, Loop) + assert isinstance(operations[-1].jump_target, TreeLoop) def __repr__(self): return '<%s>' % (self.name,) +def _list_all_operations(result, operations, omit_fails=True): + if omit_fails and operations[-1].opnum == rop.FAIL: + return + result.extend(operations) + for op in operations: + if op.is_guard(): + _list_all_operations(result, op.suboperations, omit_fails) + # ____________________________________________________________ @@ -442,6 +448,7 @@ def __init__(self): self.loops = [] + self.compiled_count = 0 def get_all_loops(self): return self.loops @@ -452,9 +459,6 @@ opname = op.getopname() insns[opname] = insns.get(opname, 0) + 1 if expected is not None: - # 'fail' operations may be omitted from 'expected' - if 'fail' in insns: - expected.setdefault('fail', insns['fail']) assert insns == expected for insn, expected_count in check.items(): assert insns.get(insn, 0) == expected_count @@ -465,9 +469,6 @@ for loop in self.loops: insns = loop.summary(adding_insns=insns) if expected is not None: - # 'fail' operations may be omitted from 'expected' - if 'fail' in insns: - expected.setdefault('fail', insns['fail']) assert insns == expected for insn, expected_count in check.items(): assert insns.get(insn, 0) == expected_count Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Mon Mar 23 21:22:55 2009 @@ -279,17 +279,13 @@ def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True - # only catch can have consts - for box in self.loop.operations[0].args: - self.nodes[box] = InstanceNode(box, escaped=False, startbox=True, - const=isinstance(box, Const)) + for box in self.loop.inputargs: + self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) for op in self.loop.operations: #print '| ' + op.repr() opnum = op.opnum - if (opnum == rop.MERGE_POINT or - opnum == rop.CATCH or - opnum == rop.JUMP): - continue + if opnum == rop.JUMP: + break elif opnum == rop.NEW_WITH_VTABLE: box = op.result instnode = InstanceNode(box, escaped=False) @@ -392,15 +388,15 @@ self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): - assert self.loop.operations[0].opnum == rop.MERGE_POINT end_args = self.loop.operations[-1].args + assert len(self.loop.inputargs) == len(end_args) memo = {} for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): self.nodes[end_box].escape_if_startbox(memo) for i in range(len(end_args)): - box = self.loop.operations[0].args[i] + box = self.loop.inputargs[i] other_box = end_args[i] if isinstance(other_box, Box): self.nodes[box].add_to_dependency_graph(self.nodes[other_box], @@ -418,13 +414,11 @@ def intersect_input_and_output(self): # Step (3) self.recursively_find_escaping_values() - mp = self.loop.operations[0] jump = self.loop.operations[-1] - assert mp.opnum == rop.MERGE_POINT assert jump.opnum == rop.JUMP specnodes = [] - for i in range(len(mp.args)): - enternode = self.nodes[mp.args[i]] + for i in range(len(self.loop.inputargs)): + enternode = self.nodes[self.loop.inputargs[i]] leavenode = self.getnode(jump.args[i]) specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes @@ -439,7 +433,7 @@ specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) return newboxlist - def prepare_rebuild_ops(self, instnode, liveboxes, rebuild_ops, memo): + def prepare_rebuild_ops(self, instnode, rebuild_ops, memo): box = instnode.source if not isinstance(box, Box): return box @@ -465,8 +459,7 @@ rebuild_ops.append(op) memo[box] = newbox for ofs, node in instnode.curfields.items(): - fieldbox = self.prepare_rebuild_ops(node, liveboxes, - rebuild_ops, memo) + fieldbox = self.prepare_rebuild_ops(node, rebuild_ops, memo) if isinstance(ld, FixedList): op = ResOperation(rop.SETARRAYITEM_GC, [newbox, ofs, fieldbox], @@ -477,12 +470,10 @@ None, descr=ofs) rebuild_ops.append(op) return newbox - liveboxes.append(box) memo[box] = box if instnode.virtualized: for ofs, node in instnode.curfields.items(): - fieldbox = self.prepare_rebuild_ops(node, liveboxes, - rebuild_ops, memo) + fieldbox = self.prepare_rebuild_ops(node, rebuild_ops, memo) if instnode.cls and isinstance(instnode.cls.source, FixedList): ld = instnode.cls.source assert isinstance(ld, FixedList) @@ -498,36 +489,33 @@ def optimize_guard(self, op): # Make a list of operations to run to rebuild the unoptimized objects. - # The ops assume that the Boxes in 'liveboxes' have been reloaded. - liveboxes = [] rebuild_ops = [] memo = {} - old_boxes = op.liveboxes - op = op.clone() + assert len(op.suboperations) == 1 + op_fail = op.suboperations[0] + assert op_fail.opnum == rop.FAIL + old_boxes = op.suboperations[0].args unoptboxes = [] for box in old_boxes: if isinstance(box, Const): unoptboxes.append(box) continue unoptboxes.append(self.prepare_rebuild_ops(self.nodes[box], - liveboxes, rebuild_ops, - memo)) + rebuild_ops, memo)) # XXX sloooooow! for node in self.nodes.values(): if node.virtualized: - self.prepare_rebuild_ops(node, liveboxes, rebuild_ops, memo) + self.prepare_rebuild_ops(node, rebuild_ops, memo) # start of code for dirtyfields support for node in self.nodes.values(): for ofs, subnode in node.dirtyfields.items(): box = node.source if box not in memo and isinstance(box, Box): - liveboxes.append(box) memo[box] = box #index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME fieldbox = subnode.source if fieldbox not in memo and isinstance(fieldbox, Box): - liveboxes.append(fieldbox) memo[fieldbox] = fieldbox #fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | # FLAG_BOXES_FROM_FRAME) @@ -546,15 +534,9 @@ rebuild_ops.append(op1) # end of code for dirtyfields support - if not we_are_translated(): - for box in liveboxes: - assert isinstance(box, Box) - assert len(dict.fromkeys(liveboxes)) == len(liveboxes) - - op.args = self.new_arguments(op) - op.liveboxes = liveboxes - op.rebuild_ops = rebuild_ops - op.unoptboxes = unoptboxes + op_fail.args = unoptboxes + rebuild_ops.append(op_fail) + op.suboperations = rebuild_ops return op def new_arguments(self, op): @@ -567,11 +549,6 @@ newboxes.append(box) return newboxes - def replace_arguments(self, op): - op = op.clone() - op.args = self.new_arguments(op) - return op - def optimize_getfield(self, instnode, ofs, box): assert isinstance(ofs, AbstractValue) if instnode.virtual: @@ -604,32 +581,26 @@ def optimize_loop(self): newoperations = [] exception_might_have_happened = False - mp = self.loop.operations[0] - if mp.opnum == rop.MERGE_POINT: - assert len(mp.args) == len(self.specnodes) - for i in range(len(self.specnodes)): - box = mp.args[i] - self.specnodes[i].mutate_nodes(self.nodes[box]) - else: - assert mp.opnum == rop.CATCH - for box in mp.args: - self.nodes[box].cls = None - assert not self.nodes[box].virtual + assert len(self.loop.inputargs) == len(self.specnodes) + for i in range(len(self.specnodes)): + box = self.loop.inputargs[i] + self.specnodes[i].mutate_nodes(self.nodes[box]) + newinputargs = self.expanded_version_of(self.loop.inputargs, None) + +## assert mp.opnum == rop.CATCH +## for box in mp.args: +## self.nodes[box].cls = None +## assert not self.nodes[box].virtual for op in self.loop.operations: opnum = op.opnum - if opnum == rop.MERGE_POINT: - args = self.expanded_version_of(op.args, None) - op = ResOperation(rop.MERGE_POINT, args, None) - newoperations.append(op) - continue - elif opnum == rop.JUMP: + if opnum == rop.JUMP: args = self.expanded_version_of(op.args, newoperations) for arg in args: if arg in self.nodes: assert not self.nodes[arg].virtual self.cleanup_field_caches(newoperations) - op = ResOperation(rop.JUMP, args, None) + op.args = args newoperations.append(op) continue elif opnum == rop.GUARD_NO_EXCEPTION: @@ -753,7 +724,7 @@ self.nodes[box] = instnode continue # default handling of arguments and return value - op = self.replace_arguments(op) + op.args = self.new_arguments(op) if op.is_always_pure(): for box in op.args: if isinstance(box, Box): @@ -779,7 +750,8 @@ self.nodes[box] = instnode newoperations.append(op) - newoperations[0].specnodes = self.specnodes + self.loop.specnodes = self.specnodes + self.loop.inputargs = newinputargs self.loop.operations = newoperations def cleanup_field_caches(self, newoperations): @@ -817,6 +789,7 @@ def match(self, old_operations): old_mp = old_operations[0] jump_op = self.loop.operations[-1] + assert old_op.opnum == rop.MERGE_POINT assert jump_op.opnum == rop.JUMP assert len(old_mp.specnodes) == len(jump_op.args) for i in range(len(old_mp.specnodes)): @@ -829,6 +802,8 @@ def adapt_for_match(self, old_operations): old_mp = old_operations[0] jump_op = self.loop.operations[-1] + assert old_op.opnum == rop.MERGE_POINT + assert jump_op.opnum == rop.JUMP self.specnodes = old_mp.specnodes for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 21:22:55 2009 @@ -887,12 +887,10 @@ def get_residual_args(self, loop, args): if loop.specnodes is None: # it is None only for tests return args - assert 0, "XXX fix me" - # --- - assert len(mp.specnodes) == len(args) + assert len(loop.specnodes) == len(args) expanded_args = [] - for i in range(len(mp.specnodes)): - specnode = mp.specnodes[i] + for i in range(len(loop.specnodes)): + specnode = loop.specnodes[i] specnode.extract_runtime_data(self.cpu, args[i], expanded_args) return expanded_args Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py Mon Mar 23 21:22:55 2009 @@ -29,9 +29,11 @@ def check_loops(self, expected=None, **check): get_stats().check_loops(expected=expected, **check) def check_loop_count(self, count): + assert get_stats().compiled_count == count + def check_tree_loop_count(self, count): assert len(get_stats().loops) == count def check_loop_count_at_most(self, count): - assert len(get_stats().loops) <= count + assert get_stats().compiled_count <= count def check_jumps(self, maxcount): assert get_stats().exec_jumps <= maxcount Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Mon Mar 23 21:22:55 2009 @@ -321,10 +321,9 @@ expected = f(100, 5) res = self.meta_interp(f, [100, 5], policy=StopAtXPolicy(externfn)) assert res == expected - - loops = get_stats().loops - assert loops[0].operations[0].opnum == rop.MERGE_POINT - assert loops[1].operations[0].opnum == rop.CATCH + + self.check_loop_count(2) + self.check_tree_loop_count(1) def test_example(self): myjitdriver = JitDriver(greens = ['i'], From arigo at codespeak.net Mon Mar 23 21:43:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 21:43:49 +0100 (CET) Subject: [pypy-svn] r63258 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090323204349.5DC9F1684FB@codespeak.net> Author: arigo Date: Mon Mar 23 21:43:48 2009 New Revision: 63258 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Log: Cool, we don't actually need rebuild_boxes_from_guard_failure any more. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Mon Mar 23 21:43:48 2009 @@ -818,29 +818,22 @@ result.append(box) return result -def rebuild_boxes_from_guard_failure(guard_op, cpu, history, boxes_from_frame): -## print -## print guard_op.liveboxes +##def rebuild_boxes_from_guard_failure(guard_op, cpu, history, boxes_from_frame): +## currentvalues = {} +## assert len(boxes_from_frame) == len(guard_op.liveboxes) +## for i in range(len(boxes_from_frame)): +## currentvalues[guard_op.liveboxes[i]] = boxes_from_frame[i] + +## # interpret the operations stored in 'rebuild_ops' ## for op in guard_op.rebuild_ops: -## print op -## print guard_op.unoptboxes -## print '^'*79 -## import pdb; pdb.set_trace() - currentvalues = {} - assert len(boxes_from_frame) == len(guard_op.liveboxes) - for i in range(len(boxes_from_frame)): - currentvalues[guard_op.liveboxes[i]] = boxes_from_frame[i] - - # interpret the operations stored in 'rebuild_ops' - for op in guard_op.rebuild_ops: - argboxes = get_in_list(currentvalues, op.args) - # similar to execute_and_record, but not specialized on op.opnum - resbox = executor.execute_nonspec(cpu, op.opnum, argboxes, op.descr) - history.record(op.opnum, argboxes, resbox, op.descr) - if resbox is not None: - currentvalues[op.result] = resbox - # done - return [currentvalues[box] for box in guard_op.unoptboxes] +## argboxes = get_in_list(currentvalues, op.args) +## # similar to execute_and_record, but not specialized on op.opnum +## resbox = executor.execute_nonspec(cpu, op.opnum, argboxes, op.descr) +## history.record(op.opnum, argboxes, resbox, op.descr) +## if resbox is not None: +## currentvalues[op.result] = resbox +## # done +## return [currentvalues[box] for box in guard_op.unoptboxes] def partition(array, left, right): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 21:43:48 2009 @@ -933,15 +933,8 @@ self.history = history.History(self.cpu) else: self.history = history.BlackHole(self.cpu) - boxes_from_frame = guard_failure.args - if 0: # xxx guard_op.rebuild_ops is not None: - newboxes = optimize.rebuild_boxes_from_guard_failure( - guard_op, self.cpu, self.history, boxes_from_frame) - else: - # xxx for tests only - newboxes = boxes_from_frame self.rebuild_state_after_failure(guard_failure.key.resume_info, - newboxes) + guard_failure.args) def handle_exception(self): etype = self.cpu.get_exception() From arigo at codespeak.net Mon Mar 23 21:53:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 21:53:03 +0100 (CET) Subject: [pypy-svn] r63259 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090323205303.C42891684F8@codespeak.net> Author: arigo Date: Mon Mar 23 21:53:03 2009 New Revision: 63259 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Log: Fix test_optimize. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Mon Mar 23 21:53:03 2009 @@ -31,6 +31,16 @@ check_descr(descr) self.descr = descr + def clone(self): + "NOT_RPYTHON" # for tests only + res = ResOperation(self.opnum, self.args, self.result, self.descr) + res.jump_target = self.jump_target + res.key = self.key + res.vdesc = self.vdesc + if self.suboperations is not None: + res.suboperations = [op.clone() for op in self.suboperations] + return res + def __repr__(self): return self.repr() Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Mon Mar 23 21:53:03 2009 @@ -11,7 +11,7 @@ ConstAddr, History) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, - rebuild_boxes_from_guard_failure, NotSpecNode) + NotSpecNode) cpu = runner.CPU(None) @@ -35,8 +35,9 @@ # ____________________________________________________________ class Loop(object): - def __init__(self, operations): - self.operations = operations + def __init__(self, inputargs, operations): + self.inputargs = inputargs[:] + self.operations = [op.clone() for op in operations] class Any(object): def __eq__(self, other): @@ -78,6 +79,10 @@ opnum = getattr(rop, opname.upper()) return resoperation.ResOperation(opnum, args, result, descr) +def set_guard(op, args): + assert op.is_guard(), op + op.suboperations = [ResOperation('fail', args, None)] + # ____________________________________________________________ class A: @@ -96,8 +101,8 @@ v = BoxInt(startnode.value) v2 = BoxInt(startnode.value-1) sum2 = BoxInt(0 + startnode.value) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -109,7 +114,7 @@ ] def test_A_find_nodes(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() assert spec.nodes[A.sum] is not spec.nodes[A.sum2] assert spec.nodes[A.n1] is not spec.nodes[A.n2] @@ -119,7 +124,7 @@ assert not spec.nodes[A.n2].escaped def test_A_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() spec.intersect_input_and_output() assert len(spec.specnodes) == 2 @@ -131,12 +136,12 @@ assert isinstance(spec_n.fields[0][1], NotSpecNode) def test_A_optimize_loop(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [A.sum, A.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [A.sum, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), ResOperation('jump', [A.sum2, A.v2], None), @@ -146,8 +151,8 @@ class B: locals().update(A.__dict__) # :-) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('escape', [n1], None), ResOperation('getfield_gc', [n1], v, ofs_value), @@ -161,7 +166,7 @@ ] def test_B_find_nodes(): - spec = PerfectSpecializer(Loop(B.ops)) + spec = PerfectSpecializer(Loop(B.inputargs, B.ops)) spec.find_nodes() assert spec.nodes[B.n1].cls.source.value == node_vtable_adr assert spec.nodes[B.n1].escaped @@ -169,7 +174,7 @@ assert spec.nodes[B.n2].escaped def test_B_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(B.ops)) + spec = PerfectSpecializer(Loop(B.inputargs, B.ops)) spec.find_nodes() spec.intersect_input_and_output() assert len(spec.specnodes) == 2 @@ -179,12 +184,12 @@ assert spec_n.known_class.value == node_vtable_adr def test_B_optimize_loop(): - spec = PerfectSpecializer(Loop(B.ops)) + spec = PerfectSpecializer(Loop(B.inputargs, B.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [B.sum, B.n1] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [B.sum, B.n1], None), # guard_class is gone ResOperation('escape', [B.n1], None), ResOperation('getfield_gc', [B.n1], B.v, B.ofs_value), @@ -201,8 +206,8 @@ class C: locals().update(A.__dict__) # :-) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('escape', [n1], None), # <== escaping ResOperation('getfield_gc', [n1], v, ofs_value), @@ -216,14 +221,14 @@ ] def test_C_find_nodes(): - spec = PerfectSpecializer(Loop(C.ops)) + spec = PerfectSpecializer(Loop(C.inputargs, C.ops)) spec.find_nodes() assert spec.nodes[C.n1].cls.source.value == node_vtable_adr assert spec.nodes[C.n1].escaped assert spec.nodes[C.n2].cls.source.value == node_vtable_adr def test_C_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(C.ops)) + spec = PerfectSpecializer(Loop(C.inputargs, C.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[C.n2].escaped @@ -234,12 +239,12 @@ assert spec_n.known_class.value == node_vtable_adr def test_C_optimize_loop(): - spec = PerfectSpecializer(Loop(C.ops)) + spec = PerfectSpecializer(Loop(C.inputargs, C.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [C.sum, C.n1] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [C.sum, C.n1], None), # guard_class is gone ResOperation('escape', [C.n1], None), # <== escaping ResOperation('getfield_gc', [C.n1], C.v, C.ofs_value), @@ -256,8 +261,8 @@ class D: locals().update(A.__dict__) # :-) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu)], None), # the only difference is different vtable ^^^^^^^^^^^^ ResOperation('getfield_gc', [n1], v, ofs_value), @@ -270,7 +275,7 @@ ] def test_D_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(D.ops)) + spec = PerfectSpecializer(Loop(D.inputargs, D.ops)) spec.find_nodes() py.test.raises(CancelInefficientLoop, spec.intersect_input_and_output) @@ -278,8 +283,8 @@ class E: locals().update(A.__dict__) # :-) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -290,15 +295,15 @@ ResOperation('guard_true', [v2], None), ResOperation('jump', [sum2, n2], None), ] - ops[-2].liveboxes = [sum2, n2] - + set_guard(ops[-2], [sum2, n2]) + def test_E_optimize_loop(): - spec = PerfectSpecializer(Loop(E.ops), cpu=cpu) + spec = PerfectSpecializer(Loop(E.inputargs, E.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [E.sum, E.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [E.sum, E.v], None), # guard_class is gone ResOperation('int_sub', [E.v, ConstInt(1)], E.v2), ResOperation('int_add', [E.sum, E.v], E.sum2), @@ -307,35 +312,32 @@ ]) guard_op = spec.loop.operations[-2] assert guard_op.getopname() == 'guard_true' - assert guard_op.liveboxes == [E.sum2, E.v2] - vt = cpu.cast_adr_to_int(node_vtable_adr) - assert len(guard_op.unoptboxes) == 2 - assert guard_op.unoptboxes[0] == E.sum2 - assert len(guard_op.rebuild_ops) == 2 - assert guard_op.rebuild_ops[0].opnum == rop.NEW_WITH_VTABLE - assert guard_op.rebuild_ops[1].opnum == rop.SETFIELD_GC - assert guard_op.rebuild_ops[1].args[0] == guard_op.rebuild_ops[0].result - assert guard_op.rebuild_ops[1].descr == E.ofs_value - assert guard_op.unoptboxes[1] == guard_op.rebuild_ops[1].args[0] + _, n2 = guard_op.suboperations[-1].args + equaloplists(guard_op.suboperations, [ + ResOperation('new_with_vtable', [ConstAddr(node_vtable_adr, cpu)], n2, + E.size_of_node), + ResOperation('setfield_gc', [n2, E.v2], None, E.ofs_value), + ResOperation('fail', [E.sum2, n2], None), + ]) -def test_E_rebuild_after_failure(): - spec = PerfectSpecializer(Loop(E.ops), cpu=cpu) - spec.find_nodes() - spec.intersect_input_and_output() - spec.optimize_loop() - guard_op = spec.loop.operations[-2] - v_sum_b = BoxInt(13) - v_v_b = BoxInt(14) - history = History(cpu) - newboxes = rebuild_boxes_from_guard_failure(guard_op, cpu, history, - [v_sum_b, v_v_b]) - assert len(newboxes) == 2 - assert newboxes[0] == v_sum_b - p = newboxes[1].getptr(lltype.Ptr(NODE)) - assert p.value == 14 - assert len(history.operations) == 2 - assert ([op.getopname() for op in history.operations] == - ['new_with_vtable', 'setfield_gc']) +##def test_E_rebuild_after_failure(): +## spec = PerfectSpecializer(Loop(E.inputargs, E.ops), cpu=cpu) +## spec.find_nodes() +## spec.intersect_input_and_output() +## spec.optimize_loop() +## guard_op = spec.loop.operations[-2] +## v_sum_b = BoxInt(13) +## v_v_b = BoxInt(14) +## history = History(cpu) +## newboxes = rebuild_boxes_from_guard_failure(guard_op, cpu, history, +## [v_sum_b, v_v_b]) +## assert len(newboxes) == 2 +## assert newboxes[0] == v_sum_b +## p = newboxes[1].getptr(lltype.Ptr(NODE)) +## assert p.value == 14 +## assert len(history.operations) == 2 +## assert ([op.getopname() for op in history.operations] == +## ['new_with_vtable', 'setfield_gc']) # ____________________________________________________________ @@ -347,8 +349,8 @@ vbool1 = BoxInt(1) vbool2 = BoxInt(0) vbool3 = BoxInt(1) + inputargs = [sum, n1, n3] ops = [ - ResOperation('merge_point', [sum, n1, n3], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -364,25 +366,24 @@ ResOperation('guard_true', [vbool3], None), ResOperation('jump', [sum2, n2, n3], None), ] - liveboxes = [sum2, n2, n3] - ops[-2].liveboxes = liveboxes[:] - ops[-4].liveboxes = liveboxes[:] - ops[-6].liveboxes = liveboxes[:] + set_guard(ops[-2], [sum2, n2, n3]) + set_guard(ops[-4], [sum2, n2, n3]) + set_guard(ops[-6], [sum2, n2, n3]) def test_F_find_nodes(): - spec = PerfectSpecializer(Loop(F.ops)) + spec = PerfectSpecializer(Loop(F.inputargs, F.ops)) spec.find_nodes() assert not spec.nodes[F.n1].escaped assert not spec.nodes[F.n2].escaped def test_F_optimize_loop(): - spec = PerfectSpecializer(Loop(F.ops), cpu=cpu) + spec = PerfectSpecializer(Loop(F.inputargs, F.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped spec.optimize_loop() + assert spec.loop.inputargs == [F.sum, F.v, F.n3] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [F.sum, F.v, F.n3], None), ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), ResOperation('int_add', [F.sum, F.v], F.sum2), ResOperation('oononnull', [F.n3], F.vbool3), @@ -399,17 +400,17 @@ n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node3)) n4 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node4)) vbool1 = BoxInt(0) + inputargs = [n2, n3] ops = [ - ResOperation('merge_point', [n2, n3], None), ResOperation('oois', [n2, n3], vbool1), ResOperation('guard_true', [vbool1], None), ResOperation('escape', [], n4), ResOperation('jump', [n2, n4], None), ] - ops[2].liveboxes = [n2] + set_guard(ops[-3], [n2]) def test_F2_optimize_loop(): - spec = PerfectSpecializer(Loop(F2.ops), cpu=cpu) + spec = PerfectSpecializer(Loop(F2.inputargs, F2.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() @@ -421,8 +422,8 @@ locals().update(A.__dict__) # :-) v3 = BoxInt(123) v4 = BoxInt(124) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -436,15 +437,15 @@ ResOperation('guard_true', [v2], None), ResOperation('jump', [sum2, n2], None), ] - ops[-2].liveboxes = [sum2, n2] + set_guard(ops[-2], [sum2, n2]) def test_G_optimize_loop(): - spec = PerfectSpecializer(Loop(G.ops), cpu=cpu) + spec = PerfectSpecializer(Loop(G.inputargs, G.ops), cpu=cpu) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [G.sum, G.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [G.sum, G.v], None), # guard_class is gone ResOperation('int_sub', [G.v, ConstInt(1)], G.v2), ResOperation('int_add', [G.sum, G.v], G.sum2), @@ -453,11 +454,13 @@ ]) guard_op = spec.loop.operations[-2] assert guard_op.getopname() == 'guard_true' - assert guard_op.liveboxes == [G.sum2] - vt = cpu.cast_adr_to_int(node_vtable_adr) - assert ([op.getopname() for op in guard_op.rebuild_ops] == - ['new_with_vtable', 'setfield_gc']) - assert guard_op.rebuild_ops[1].args[1] == ConstInt(124) + _, n2 = guard_op.suboperations[-1].args + equaloplists(guard_op.suboperations, [ + ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, + G.size_of_node), + ResOperation('setfield_gc', [n2, ConstInt(124)], None, G.ofs_value), + ResOperation('fail', [G.sum2, n2], None), + ]) # ____________________________________________________________ @@ -474,8 +477,8 @@ n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) v = BoxInt(containernode.next.value) v2 = BoxInt(nextnode.value) + inputargs = [n0] ops = [ - ResOperation('merge_point', [n0], None), ResOperation('getfield_gc', [n0], n1, ofs_next), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -487,7 +490,7 @@ ] def test_H_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(H.ops)) + spec = PerfectSpecializer(Loop(H.inputargs, H.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[H.n0].escaped @@ -506,8 +509,8 @@ nextnode = lltype.malloc(NODE) nextnode.value = 19 n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + inputargs = [n0] ops = [ - ResOperation('merge_point', [n0], None), ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, size_of_node), ResOperation('setfield_gc', [n2, n0], None, ofs_next), @@ -515,7 +518,7 @@ ] def test_I_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(I.ops)) + spec = PerfectSpecializer(Loop(I.inputargs, I.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[I.n0].escaped @@ -534,8 +537,8 @@ nextnode.value = 19 n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + inputargs = [n0] ops = [ - ResOperation('merge_point', [n0], None), ResOperation('getfield_gc', [n0], n1, ofs_next), ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2, size_of_node), @@ -544,7 +547,7 @@ ] def test_J_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(J.ops)) + spec = PerfectSpecializer(Loop(J.inputargs, J.ops)) spec.find_nodes() spec.intersect_input_and_output() assert not spec.nodes[J.n0].escaped @@ -557,8 +560,8 @@ locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -570,13 +573,13 @@ ] def test_K0_optimize_loop(): - spec = PerfectSpecializer(Loop(K0.ops)) + spec = PerfectSpecializer(Loop(K0.inputargs, K0.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [K0.sum, K0.n1, K0.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [K0.sum, K0.n1, K0.v], None), ResOperation('int_sub', [K0.v, ConstInt(1)], K0.v2), ResOperation('int_add', [K0.sum, K0.v], K0.sum2), ResOperation('int_add', [K0.sum2, K0.v], K0.sum3), @@ -590,8 +593,8 @@ locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -604,13 +607,13 @@ ] def test_K1_optimize_loop(): - spec = PerfectSpecializer(Loop(K1.ops)) + spec = PerfectSpecializer(Loop(K1.inputargs, K1.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [K1.sum, K1.n1, K1.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [K1.sum, K1.n1, K1.v], None), ResOperation('int_sub', [K1.v, ConstInt(1)], K1.v2), ResOperation('int_add', [K1.sum, K1.v], K1.sum2), ResOperation('int_add', [K1.sum2, K1.sum], K1.sum3), @@ -625,8 +628,8 @@ locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -637,12 +640,12 @@ ] def test_K_optimize_loop(): - spec = PerfectSpecializer(Loop(K.ops)) + spec = PerfectSpecializer(Loop(K.inputargs, K.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [K.sum, K.n1, K.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [K.sum, K.n1, K.v], None), ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), ResOperation('int_add', [K.sum, K.v], K.sum2), ResOperation('int_add', [K.sum2, K.v], K.sum3), @@ -655,8 +658,8 @@ locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -668,12 +671,12 @@ ] def test_L_optimize_loop(): - spec = PerfectSpecializer(Loop(L.ops)) + spec = PerfectSpecializer(Loop(L.inputargs, L.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [L.sum, L.n1, L.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [L.sum, L.n1, L.v], None), ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), ResOperation('int_add', [L.sum, L.v], L.sum2), ResOperation('escape', [L.n1], None), @@ -688,8 +691,8 @@ locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -699,13 +702,13 @@ ] def test_M_optimize_loop(): - spec = PerfectSpecializer(Loop(M.ops)) + spec = PerfectSpecializer(Loop(M.inputargs, M.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [M.sum, M.n1, M.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [M.sum, M.n1, M.v], None), ResOperation('int_sub', [M.v, ConstInt(1)], M.v2), ResOperation('int_add', [M.sum, M.v], M.sum2), ResOperation('escape', [M.n1], None), @@ -719,8 +722,8 @@ locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) + inputargs = [sum, n1] ops = [ - ResOperation('merge_point', [sum, n1], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('int_sub', [v, ConstInt(1)], v2), @@ -730,13 +733,13 @@ ] def test_N_optimize_loop(): - spec = PerfectSpecializer(Loop(N.ops)) + spec = PerfectSpecializer(Loop(N.inputargs, N.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [N.sum, N.n1, N.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [N.sum, N.n1, N.v], None), ResOperation('int_sub', [N.v, ConstInt(1)], N.v2), ResOperation('int_add', [N.sum, N.v], N.sum2), ResOperation('escape', [N.n1], None), @@ -748,23 +751,23 @@ class O1: locals().update(A.__dict__) # :-) + inputargs = [] ops = [ - ResOperation('merge_point', [], None), ResOperation('escape', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('jump', [], None), ] - ops[-3].liveboxes = [] - ops[-2].liveboxes = [] + set_guard(ops[-3], []) + set_guard(ops[-2], []) def test_O1_optimize_loop(): - spec = PerfectSpecializer(Loop(O1.ops)) + spec = PerfectSpecializer(Loop(O1.inputargs, O1.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [], None), ResOperation('escape', [], O1.n1), # only the first guard_class is left ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu)], @@ -777,24 +780,24 @@ class O2: locals().update(A.__dict__) # :-) v1 = BoxInt(1) + inputargs = [] ops = [ - ResOperation('merge_point', [], None), ResOperation('escape', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('oononnull', [n1], v1), ResOperation('guard_true', [v1], None), ResOperation('jump', [], None), ] - ops[-4].liveboxes = [] - ops[-2].liveboxes = [] + set_guard(ops[-4], []) + set_guard(ops[-2], []) def test_O2_optimize_loop(): - spec = PerfectSpecializer(Loop(O2.ops)) + spec = PerfectSpecializer(Loop(O2.inputargs, O2.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [], None), ResOperation('escape', [], O2.n1), ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu)], None), @@ -808,8 +811,8 @@ class O3: locals().update(A.__dict__) # :-) v1 = BoxInt(1) + inputargs = [] ops = [ - ResOperation('merge_point', [], None), ResOperation('escape', [], n1), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None), ResOperation('oois', [n1, ConstPtr(lltype.nullptr(llmemory.GCREF.TO))], @@ -817,16 +820,16 @@ ResOperation('guard_false', [v1], None), ResOperation('jump', [], None), ] - ops[-4].liveboxes = [] - ops[-2].liveboxes = [] + set_guard(ops[-4], []) + set_guard(ops[-2], []) def test_O3_optimize_loop(): - spec = PerfectSpecializer(Loop(O3.ops)) + spec = PerfectSpecializer(Loop(O3.inputargs, O3.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [], None), ResOperation('escape', [], O3.n1), ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu)], None), @@ -842,8 +845,8 @@ thirdnode = lltype.malloc(NODE) n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, thirdnode)) f = BoxInt(0) # False + inputargs = [n1, n3] ops = [ - ResOperation('merge_point', [n1, n3], None), ResOperation('getfield_gc', [n3], v, ofs_value), ResOperation('setfield_gc', [n1, ConstInt(1)], None, ofs_value), ResOperation('getfield_gc', [n3], v2, ofs_value), @@ -852,11 +855,11 @@ ResOperation('getfield_gc', [n1], n2, ofs_next), ResOperation('jump', [n2, n3], None), ] - ops[-3].liveboxes = [] + set_guard(ops[-3], []) def test_P_optimize_loop(): py.test.skip("explodes") - spec = PerfectSpecializer(Loop(P.ops)) + spec = PerfectSpecializer(Loop(P.inputargs, P.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() From arigo at codespeak.net Mon Mar 23 21:56:15 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 21:56:15 +0100 (CET) Subject: [pypy-svn] r63260 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090323205615.4C6DF1684FA@codespeak.net> Author: arigo Date: Mon Mar 23 21:56:14 2009 New Revision: 63260 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py Log: Fix test_list_optimize. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py Mon Mar 23 21:56:14 2009 @@ -4,7 +4,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, - rebuild_boxes_from_guard_failure, NotSpecNode, FixedList) + NotSpecNode, FixedList) from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from pypy.jit.metainterp.test.test_optimize import Loop, equaloplists, cpu from pypy.jit.metainterp.specnode import DelayedFixedListSpecNode @@ -18,8 +18,8 @@ e0 = BoxInt(0) e1 = BoxInt(0) ad = cpu.arraydescrof(TP) + inputargs = [l] ops = [ - ResOperation(rop.MERGE_POINT, [l], None), ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e0, ad), ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e0], None, ad), ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e1, ad), @@ -28,25 +28,25 @@ ] def test_A_find_nodes(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() node = spec.nodes[A.l] assert isinstance(node.cls.source, FixedList) assert node.expanded_fields.keys() == [ConstInt(0)] def test_A_intersect(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() spec.intersect_input_and_output() assert isinstance(spec.specnodes[0], DelayedFixedListSpecNode) def test_A_optimize_loop(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [A.l, A.e0] equaloplists(spec.loop.operations, [ - ResOperation(rop.MERGE_POINT, [A.l, A.e0], None), ResOperation(rop.SETARRAYITEM_GC, [A.l, ConstInt(0), A.e0], None, A.ad), ResOperation(rop.JUMP, [A.l, A.e0], None) ]) @@ -57,8 +57,8 @@ locals().update(A.__dict__) e2 = BoxInt(0) e3 = BoxInt(0) + inputargs = [l] ops = [ - ResOperation(rop.MERGE_POINT, [l], None), ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e0, ad), ResOperation(rop.INT_ADD, [e0, ConstInt(1)], e1), ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e1], None, ad), @@ -70,12 +70,12 @@ ] def test_B_optimize_loop(): - spec = PerfectSpecializer(Loop(B.ops)) + spec = PerfectSpecializer(Loop(B.inputargs, B.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [B.l, B.e0] equaloplists(spec.loop.operations, [ - ResOperation(rop.MERGE_POINT, [B.l, B.e0], None), ResOperation(rop.INT_ADD, [B.e0, ConstInt(1)], B.e1), ResOperation(rop.SETARRAYITEM_GC, [B.l, ConstInt(0), B.e1], None, B.ad), ResOperation(-123, [B.e1], None), @@ -91,8 +91,8 @@ locals().update(A.__dict__) e3 = BoxInt(0) e2 = BoxInt(0) + inputargs = [l] ops = [ - ResOperation(rop.MERGE_POINT, [l], None), ResOperation(rop.GETARRAYITEM_GC, [l, ConstInt(0)], e0, ad), ResOperation(rop.INT_ADD, [e0, ConstInt(1)], e1), ResOperation(rop.SETARRAYITEM_GC, [l, ConstInt(0), e1], None, ad), From arigo at codespeak.net Mon Mar 23 21:56:59 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 21:56:59 +0100 (CET) Subject: [pypy-svn] r63261 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090323205659.78F311684F8@codespeak.net> Author: arigo Date: Mon Mar 23 21:56:57 2009 New Revision: 63261 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_tl.py Log: Fix test_tl. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_tl.py Mon Mar 23 21:56:57 2009 @@ -95,15 +95,14 @@ def test_tl_base(self): res = self.meta_interp(self.main.im_func, [0, 6], listops=True) assert res == 5040 - self.check_loops({'merge_point':1, - 'int_mul':1, 'jump':1, + self.check_loops({'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, 'guard_false':1, 'guard_value':1}) def test_tl_2(self): res = self.meta_interp(self.main.im_func, [1, 10], listops=True) assert res == self.main.im_func(1, 10) - self.check_loops({'merge_point':1, 'int_sub':1, 'int_le':1, + self.check_loops({'int_sub':1, 'int_le':1, 'int_is_true':1, 'guard_false':1, 'jump':1, 'guard_value':1}) From arigo at codespeak.net Mon Mar 23 21:59:01 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 21:59:01 +0100 (CET) Subject: [pypy-svn] r63262 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090323205901.963871684F8@codespeak.net> Author: arigo Date: Mon Mar 23 21:59:01 2009 New Revision: 63262 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Log: Fix test_vable_optimize. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Mon Mar 23 21:59:01 2009 @@ -83,8 +83,8 @@ v = BoxInt(frame.node.value) v2 = BoxInt(nextnode.value) sum2 = BoxInt(0 + frame.node.value) + inputargs = [sum, fr] ops = [ - ResOperation('merge_point', [sum, fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], None, ofs_node), ResOperation('getfield_gc', [fr], n1, ofs_node), @@ -100,12 +100,12 @@ ops[1].vdesc = xy_desc def test_A_find_nodes(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() assert spec.nodes[A.fr].virtualized def test_A_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[A.fr].escaped @@ -115,12 +115,12 @@ assert isinstance(spec.specnodes[1], VirtualizableSpecNode) def test_A_optimize_loop(): - spec = PerfectSpecializer(Loop(A.ops)) + spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + assert spec.loop.inputargs == [A.sum, A.fr, A.v] equaloplists(spec.loop.operations, [ - ResOperation('merge_point', [A.sum, A.fr, A.v], None), ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), ResOperation('jump', [A.sum2, A.fr, A.v2], None), @@ -140,8 +140,8 @@ fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v = BoxInt(13) + inputargs = [fr] ops = [ - ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], None, ofs_node), ResOperation('getfield_gc', [fr], n1, ofs_node), @@ -151,7 +151,7 @@ ops[1].vdesc = xy_desc def test_B_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(B.ops)) + spec = PerfectSpecializer(Loop(B.inputargs, B.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[B.fr].escaped @@ -168,8 +168,8 @@ locals().update(B.__dict__) n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v2 = BoxInt(13) + inputargs = [fr] ops = [ - ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], None, ofs_node), # @@ -186,7 +186,7 @@ ops[1].vdesc = xy_desc def test_C_intersect_input_and_output(): - spec = PerfectSpecializer(Loop(C.ops)) + spec = PerfectSpecializer(Loop(C.inputargs, C.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[C.fr].escaped @@ -211,8 +211,8 @@ n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v2 = BoxInt(13) l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + inputargs = [fr] ops = [ - ResOperation('merge_point', [fr], None), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), ConstInt(ofs_node)], None), # @@ -226,7 +226,7 @@ def test_D_intersect_input_and_output(): py.test.skip("XXX") - spec = PerfectSpecializer(Loop(D.ops)) + spec = PerfectSpecializer(Loop(D.inputargs, D.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[D.fr].escaped From arigo at codespeak.net Mon Mar 23 22:35:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 23 Mar 2009 22:35:37 +0100 (CET) Subject: [pypy-svn] r63263 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090323213537.26F561684FC@codespeak.net> Author: arigo Date: Mon Mar 23 22:35:36 2009 New Revision: 63263 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Log: Intermediate check-in. Busy trying to have optimize.py work on bridges. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py Mon Mar 23 22:35:36 2009 @@ -319,6 +319,7 @@ op = loop.operations[-1] op.jump_target = loop_target assert op.opnum == rop.JUMP + assert len(op.args) == len(loop_target.inputargs) if loop_target == loop: log.info("compiling new loop") else: Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Mar 23 22:35:36 2009 @@ -9,65 +9,60 @@ from pypy.jit.metainterp import optimize -def compile_new_loop(metainterp, old_loops, endliveboxes): +def compile_new_loop(metainterp, old_loops): """Try to compile a new loop by closing the current history back to the first operation. """ - loop = create_empty_loop(metainterp) if we_are_translated(): try: - loop = compile_fresh_loop(metainterp, loop, old_loops, - endliveboxes) + loop = compile_fresh_loop(metainterp, old_loops) return loop except optimize.CancelInefficientLoop: return None else: - return _compile_new_loop_1(metainterp, loop, old_loops, endliveboxes) + return _compile_new_loop_1(metainterp, old_loops) -def compile_new_bridge(metainterp, old_loops, endliveboxes, resumekey): +def compile_new_bridge(metainterp, old_loops, resumekey): """Try to compile a new bridge leading from the beginning of the history to some existing place. """ if we_are_translated(): try: target_loop = compile_fresh_bridge(metainterp, old_loops, - endliveboxes, resumekey) + resumekey) return target_loop except optimize.CancelInefficientLoop: return None else: - return _compile_new_bridge_1(metainterp, old_loops, - endliveboxes, resumekey) + return _compile_new_bridge_1(metainterp, old_loops, resumekey) class BridgeInProgress(Exception): pass # the following is not translatable -def _compile_new_loop_1(metainterp, loop, old_loops, endliveboxes): - orgloop = loop +def _compile_new_loop_1(metainterp, old_loops): try: try: - loop = compile_fresh_loop(metainterp, loop, old_loops, - endliveboxes) + loop = compile_fresh_loop(metainterp, old_loops) except Exception, exc: - show_loop(metainterp, loop, error=exc) + show_loop(metainterp, error=exc) raise else: - if loop == orgloop: - show_loop(metainterp, loop) - else: + if loop in old_loops: log.info("reusing loop at %r" % (loop,)) + else: + show_loop(metainterp, loop) except optimize.CancelInefficientLoop: return None loop.check_consistency() return loop -def _compile_new_bridge_1(metainterp, old_loops, endliveboxes, resumekey): +def _compile_new_bridge_1(metainterp, old_loops, resumekey): try: try: target_loop = compile_fresh_bridge(metainterp, old_loops, - endliveboxes, resumekey) + resumekey) except Exception, exc: show_loop(metainterp, error=exc) raise @@ -105,19 +100,17 @@ # ____________________________________________________________ -def compile_fresh_loop(metainterp, loop, old_loops, endliveboxes): - # ------ - if old_loops: - return old_loops[0] - # ------ +def compile_fresh_loop(metainterp, old_loops): history = metainterp.history - loop.inputargs = history.inputargs - loop.operations = history.operations - close_loop(loop, endliveboxes) - old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop, - metainterp.cpu) + old_loop = optimize.optimize_loop(metainterp.options, old_loops, + history, metainterp.cpu) if old_loop is not None: return old_loop + loop = create_empty_loop(metainterp) + loop.inputargs = history.inputargs + loop.specnodes = history.specnodes + loop.operations = history.operations + loop.operations[-1].jump_target = loop mark_keys_in_loop(loop, loop.operations) send_loop_to_backend(metainterp, loop) metainterp.stats.loops.append(loop) @@ -125,11 +118,6 @@ old_loops.append(loop) return loop -def close_loop(loop, endliveboxes): - op = ResOperation(rop.JUMP, endliveboxes, None) - op.jump_target = loop - loop.operations.append(op) - def mark_keys_in_loop(loop, operations): for op in operations: if op.is_guard(): @@ -143,26 +131,16 @@ # ____________________________________________________________ -def matching_merge_point(metainterp, targetmp, endliveboxes): - return True - -def compile_fresh_bridge(metainterp, old_loops, endliveboxes, resumekey): - history = metainterp.history - # - op = ResOperation(rop.JUMP, endliveboxes, None) - history.operations.append(op) - # - #old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge, - # metainterp.cpu) - #if old_loop is None: - # return None - # ------ +def compile_fresh_bridge(metainterp, old_loops, resumekey): + old_loop = optimize.optimize_bridge(metainterp.options, old_loops, + metainterp.history, metainterp.cpu) + if old_loop is None: + return None target_loop = old_loops[0] op.jump_target = target_loop - # ------ source_loop = resumekey.loop guard_op = resumekey.guard_op - guard_op.suboperations = history.operations + guard_op.suboperations = self.history.operations mark_keys_in_loop(source_loop, guard_op.suboperations) send_loop_to_backend(metainterp, source_loop) metainterp.stats.compiled_count += 1 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Mar 23 22:35:36 2009 @@ -407,6 +407,7 @@ class RunningMatcher(object): + specnodes = None def __init__(self, cpu): self.cpu = cpu self.inputargs = None Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Mon Mar 23 22:35:36 2009 @@ -189,7 +189,7 @@ if self.virtualized: flags += 'V' return "" % (self.source, flags) -def optimize_loop(options, old_loops, loop, cpu=None): +def optimize_loop(options, old_loops, history, cpu=None): if not options.specialize: # for tests only if old_loops: return old_loops[0] @@ -197,7 +197,7 @@ return None # This does "Perfect specialization" as per doc/jitpl5.txt. - perfect_specializer = PerfectSpecializer(loop, options, cpu) + perfect_specializer = PerfectSpecializer(history, options, cpu) perfect_specializer.find_nodes() perfect_specializer.intersect_input_and_output() for old_loop in old_loops: @@ -206,11 +206,11 @@ perfect_specializer.optimize_loop() return None -def optimize_bridge(options, old_loops, bridge, cpu=None): +def optimize_bridge(options, old_loops, history, cpu=None): if not options.specialize: # for tests only return old_loops[0] - perfect_specializer = PerfectSpecializer(bridge, options, cpu) + perfect_specializer = PerfectSpecializer(history, options, cpu) perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): @@ -221,8 +221,8 @@ class PerfectSpecializer(object): - def __init__(self, loop, options=Options(), cpu=None): - self.loop = loop + def __init__(self, history, options=Options(), cpu=None): + self.history = history self.options = options self.cpu = cpu self.nodes = {} @@ -279,9 +279,9 @@ def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True - for box in self.loop.inputargs: + for box in self.history.inputargs: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) - for op in self.loop.operations: + for op in self.history.operations: #print '| ' + op.repr() opnum = op.opnum if opnum == rop.JUMP: @@ -388,15 +388,15 @@ self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): - end_args = self.loop.operations[-1].args - assert len(self.loop.inputargs) == len(end_args) + end_args = self.history.operations[-1].args + assert len(self.history.inputargs) == len(end_args) memo = {} for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): self.nodes[end_box].escape_if_startbox(memo) for i in range(len(end_args)): - box = self.loop.inputargs[i] + box = self.history.inputargs[i] other_box = end_args[i] if isinstance(other_box, Box): self.nodes[box].add_to_dependency_graph(self.nodes[other_box], @@ -414,11 +414,11 @@ def intersect_input_and_output(self): # Step (3) self.recursively_find_escaping_values() - jump = self.loop.operations[-1] + jump = self.history.operations[-1] assert jump.opnum == rop.JUMP specnodes = [] - for i in range(len(self.loop.inputargs)): - enternode = self.nodes[self.loop.inputargs[i]] + for i in range(len(self.history.inputargs)): + enternode = self.nodes[self.history.inputargs[i]] leavenode = self.getnode(jump.args[i]) specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes @@ -581,18 +581,18 @@ def optimize_loop(self): newoperations = [] exception_might_have_happened = False - assert len(self.loop.inputargs) == len(self.specnodes) + assert len(self.history.inputargs) == len(self.specnodes) for i in range(len(self.specnodes)): - box = self.loop.inputargs[i] + box = self.history.inputargs[i] self.specnodes[i].mutate_nodes(self.nodes[box]) - newinputargs = self.expanded_version_of(self.loop.inputargs, None) + newinputargs = self.expanded_version_of(self.history.inputargs, None) ## assert mp.opnum == rop.CATCH ## for box in mp.args: ## self.nodes[box].cls = None ## assert not self.nodes[box].virtual - for op in self.loop.operations: + for op in self.history.operations: opnum = op.opnum if opnum == rop.JUMP: args = self.expanded_version_of(op.args, newoperations) @@ -602,7 +602,7 @@ self.cleanup_field_caches(newoperations) op.args = args newoperations.append(op) - continue + break elif opnum == rop.GUARD_NO_EXCEPTION: if not exception_might_have_happened: continue @@ -750,9 +750,9 @@ self.nodes[box] = instnode newoperations.append(op) - self.loop.specnodes = self.specnodes - self.loop.inputargs = newinputargs - self.loop.operations = newoperations + self.history.specnodes = self.specnodes + self.history.inputargs = newinputargs + self.history.operations = newoperations def cleanup_field_caches(self, newoperations): # we need to invalidate everything @@ -776,17 +776,16 @@ node.cleanfields = r_dict(av_eq, av_hash) def match_exactly(self, old_loop): - old_operations = old_loop.operations - old_mp = old_operations[0] - assert len(old_mp.specnodes) == len(self.specnodes) + assert len(old_loop.specnodes) == len(self.specnodes) for i in range(len(self.specnodes)): - old_specnode = old_mp.specnodes[i] + old_specnode = old_loop.specnodes[i] new_specnode = self.specnodes[i] if not old_specnode.equals(new_specnode): return False return True def match(self, old_operations): + xxx old_mp = old_operations[0] jump_op = self.loop.operations[-1] assert old_op.opnum == rop.MERGE_POINT Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 23 22:35:36 2009 @@ -857,8 +857,8 @@ self.history.inputargs = original_boxes[num_green_args:] greenkey = original_boxes[:num_green_args] old_loops = self.compiled_merge_points.setdefault(greenkey, []) - loop = compile_new_loop(self, old_loops, - live_arg_boxes[num_green_args:]) + self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) + loop = compile_new_loop(self, old_loops) if not loop: raise self.ContinueRunningNormally(live_arg_boxes) if not we_are_translated(): @@ -874,9 +874,9 @@ except KeyError: target_loop = None else: - target_loop = compile_new_bridge(self, old_loops, - live_arg_boxes[num_green_args:], - key) + self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], + None) + target_loop = compile_new_bridge(self, old_loops, key) if target_loop is None: raise self.ContinueRunningNormally(live_arg_boxes) if not we_are_translated(): @@ -931,8 +931,13 @@ # guard failure: rebuild a complete MIFrame stack if self.state.must_compile_from_failure(guard_failure.key): self.history = history.History(self.cpu) + suboperations = guard_failure.key.guard_op.suboperations + for i in range(len(suboperations)-1): + self.history.operations.append(suboperations[i]) else: self.history = history.BlackHole(self.cpu) + # the BlackHole is invalid because it doesn't start with + # guard_failure.key.guard_op.suboperations, but that's fine self.rebuild_state_after_failure(guard_failure.key.resume_info, guard_failure.args) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Mon Mar 23 22:35:36 2009 @@ -34,10 +34,11 @@ # ____________________________________________________________ -class Loop(object): - def __init__(self, inputargs, operations): - self.inputargs = inputargs[:] - self.operations = [op.clone() for op in operations] +def Loop(inputargs, operations): + history = History(cpu) + history.inputargs = inputargs[:] + history.operations = [op.clone() for op in operations] + return history class Any(object): def __eq__(self, other): From cami at codespeak.net Mon Mar 23 23:07:15 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 23 Mar 2009 23:07:15 +0100 (CET) Subject: [pypy-svn] r63264 - pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal Message-ID: <20090323220715.3F14E1684F9@codespeak.net> Author: cami Date: Mon Mar 23 23:07:13 2009 New Revision: 63264 Added: pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbfullprofiling.py Modified: pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbimplementation.py Log: fixing translation targets to use a jitpolicy Added: pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbfullprofiling.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbfullprofiling.py Mon Mar 23 23:07:13 2009 @@ -0,0 +1,45 @@ +#!/usr/bin/env python +import os, py, pdb, sys, time +from pypy.lang.gameboy.profiling.gameboy_profiling_implementation import GameBoyProfiler +from pypy.jit.metainterp.policy import JitPolicy + + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" + +def entry_point(argv=None): + if argv is not None and len(argv) > 1: + filename = argv[1] + execution_seconds = float(argv[2]) + else: + pos = str(9) + filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" + execution_seconds = 600 + gameBoy = GameBoyProfiler() + try: + gameBoy.load_cartridge_file(str(filename)) + except: + gameBoy.load_cartridge_file(str(filename), verify=False) + + start = time.time() + gameBoy.mainLoop(execution_seconds) + print time.time() - start + + return 0 + + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None + +def test_target(): + entry_point(sys.argv) + +def jitpolicy(self, driver): + from pypy.module.pypyjit.policy import PyPyJitPolicy + return PyPyJitPolicy(driver.translator) + +# STARTPOINT =================================================================== + +if __name__ == '__main__': + test_target() Modified: pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/translator/goal/targetgbimplementation.py Mon Mar 23 23:07:13 2009 @@ -35,6 +35,9 @@ def test_target(): entry_point(sys.argv) +def jitpolicy(self, driver): + from pypy.module.pypyjit.policy import PyPyJitPolicy + return PyPyJitPolicy(driver.translator) # STARTPOINT =================================================================== @@ -43,10 +46,5 @@ if use_rsdl and sys.platform == 'darwin': from AppKit import NSApplication NSApplication.sharedApplication() - try: - import psyco - psyco.full() - except: - pass - + test_target() From cami at codespeak.net Mon Mar 23 23:07:46 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 23 Mar 2009 23:07:46 +0100 (CET) Subject: [pypy-svn] r63265 - pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy Message-ID: <20090323220746.9053F1684F9@codespeak.net> Author: cami Date: Mon Mar 23 23:07:46 2009 New Revision: 63265 Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Log: tried to add jit hints (still chinese is not so familiar) Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Mon Mar 23 23:07:46 2009 @@ -4,6 +4,7 @@ from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ ReservedDoubleRegister,\ FlagRegister, ImmediatePseudoRegister +from pypy.rlib.jit import JitDriver # --------------------------------------------------------------------------- @@ -19,6 +20,7 @@ DEBUG_INSTRUCTION_COUNTER = 1 +jitdriver = JitDriver(greens = ['pc'], reds=['af', 'bc', 'de', 'hl', 'sp']) class CPU(object): """ @@ -174,7 +176,9 @@ self.cycles += ticks self.handle_pending_interrupts() while self.cycles > 0: - self.execute(self.fetch(use_cycles=False)) + opcode = self.fetch(use_cycles=False) + jitdriver.jit_merge_point(pc=self.pc.value) + self.execute(opcode) def emulate_step(self): self.handle_pending_interrupts() @@ -286,6 +290,7 @@ self.pc.set(address, use_cycles=use_cycles) # 1 cycle if use_cycles: self.cycles += 1 + jitdriver.can_enter_jit(pc=self.pc.value) def load(self, getCaller, setCaller): # 1 cycle @@ -656,6 +661,7 @@ # JP nnnn, 4 cycles self.pc.set(self.fetch_double_address()) # 1+2 cycles self.cycles -= 1 + jitdriver.can_enter_jit(pc=self.pc.value) def conditional_jump(self, cc): # JP cc,nnnn 3,4 cycles @@ -668,6 +674,7 @@ # JR +nn, 3 cycles self.pc.add(process_2s_complement(self.fetch())) # 3 + 1 cycles self.cycles += 1 + jitdriver.can_enter_jit(pc=self.pc.value) def relative_conditional_jump(self, cc): # JR cc,+nn, 2,3 cycles @@ -690,6 +697,7 @@ def ret(self): # RET 4 cycles self.double_register_inverse_call(CPUPopCaller(self), self.pc) + jitdriver.can_enter_jit(pc=self.pc.value) def conditional_return(self, cc): # RET cc 2,5 cycles From fijal at codespeak.net Tue Mar 24 10:14:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 24 Mar 2009 10:14:42 +0100 (CET) Subject: [pypy-svn] r63267 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090324091442.CE8F11684F8@codespeak.net> Author: fijal Date: Tue Mar 24 10:14:40 2009 New Revision: 63267 Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: update a bit slides Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Tue Mar 24 10:14:40 2009 @@ -1,15 +1,17 @@ ================================ -PyPy Python Interpreter status +PyPy's Python Interpreter status ================================ What this talk is about ======================= -* a bit of motivation +* A bit of motivation -* tell what Python Interpreter can run today +* What we can run on top of PyPy -* what we are heading for with the 1.1 release +* How fast is PyPy? + +* 1.1 release coming * Questions and Answers @@ -29,8 +31,7 @@ ======================= * One should never be forced to write anything in C - for performance reasons (with some exceptions: embedded - devices etc.) + for performance reasons (with some exceptions possibly) * Just-in-time compiler should make number-crunching and static-enough code fast enough @@ -41,10 +42,15 @@ ========================== * first sprint 2003, about 30 more by now + * CPython/Psyco/Jython/Stackless developers participating + * MIT-License, more sprints + * EU Research project 2004-2007 -* 2007-2008 - open source project + +* 2007-now - open source project + * some google sponsoring Getting Production ready @@ -134,7 +140,6 @@ * http://twistedmatrix.com/ - Other software ============== @@ -151,7 +156,7 @@ * various smaller things, templating engines Obscure details that people rely on -=================================== +======================================= * non-string keys in __dict__ of types @@ -165,22 +170,13 @@ * refcounting details -Transition to 2.5 -========================== - -* SOC project Bruno Gola - -* almost complete - -* missing more testing, stdlib porting - Conclusion on Compatibility ============================ * lessons learned: There is no feature obscure enough for people not to rely on it. -* pypy-c interpreter probably the most compatible to CPython +* pypy-c interpreter probably the most compatible to CPython 2.5 * main blocker for running apps will be missing external modules @@ -199,14 +195,14 @@ Speed - JIT generator ===================== -* not ready yet! +* 20-30x faster on small examples -* will be super fast +* nice proof of concept -* some prototypes, research ongoing +* a bit of time needed to speed up large python + programs -* psyco is a nice proof that this approach - would work +* probably won't make it to 1.1 Memory - comparison with CPython =================================== @@ -221,7 +217,6 @@ * GCs are semi-decent - Threading / Stackless =================================== @@ -246,21 +241,6 @@ * contributors wanted! -Sandboxing -========== - -* fully sandboxed python interpreter - -* all external calls to C goes via another - python process - -* special library for making custom - policies - -.. image:: sandboxed.png - :scale: 30 - :align: center - pypy-c on small devices =============================== @@ -271,15 +251,21 @@ - share interpreter state across processes - pypy approach a very good fit! -1.1 release goals +1.1 release =================================== - compatible to Python 2.5.2 + - well tested on win/linux 32 bit + - running major packages unmodified + - easy_install/distutils working + - help e.g. by writing ctypes modules +- hopefully next month + Contact / Q&A ========================== From fijal at codespeak.net Tue Mar 24 10:34:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 24 Mar 2009 10:34:19 +0100 (CET) Subject: [pypy-svn] r63268 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090324093419.334561683ED@codespeak.net> Author: fijal Date: Tue Mar 24 10:34:16 2009 New Revision: 63268 Modified: pypy/extradoc/talk/pycon2009/status/author.latex Log: update date & place Modified: pypy/extradoc/talk/pycon2009/status/author.latex ============================================================================== --- pypy/extradoc/talk/pycon2009/status/author.latex (original) +++ pypy/extradoc/talk/pycon2009/status/author.latex Tue Mar 24 10:34:16 2009 @@ -4,5 +4,5 @@ \author[H. Krekel, M. Fijalkowski]{Holger Krekel \and Maciej Fijalkowski\\ Merlinux GmbH} -\institute[PyCon UK 2008]{PyCon UK 2008 - Birmingham} -\date{September 13 2008} +\institute[PyCon 2009]{PyCon 2009 - Rosemont} +\date{March 28 2009} From antocuni at codespeak.net Tue Mar 24 10:38:30 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 24 Mar 2009 10:38:30 +0100 (CET) Subject: [pypy-svn] r63269 - in pypy/extradoc/talk/pycon2009: status vm-summit Message-ID: <20090324093830.F33651684DE@codespeak.net> Author: antocuni Date: Tue Mar 24 10:38:30 2009 New Revision: 63269 Modified: pypy/extradoc/talk/pycon2009/status/status.txt pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: a small rephrasing, and add a point about ctypes configure Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Tue Mar 24 10:38:30 2009 @@ -94,6 +94,8 @@ * can handle #defines, types, structure layout etc. +* works also for CPython! (antocuni) + Sqlite ====== Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Tue Mar 24 10:38:30 2009 @@ -37,7 +37,7 @@ Generating JIT Compilers ======================================== -* We apply JIT generator to specification +* We apply JIT generator to interpreters * A couple of manual hints is required From fijal at codespeak.net Tue Mar 24 10:40:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 24 Mar 2009 10:40:52 +0100 (CET) Subject: [pypy-svn] r63270 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090324094052.221C31684F8@codespeak.net> Author: fijal Date: Tue Mar 24 10:40:51 2009 New Revision: 63270 Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: delete a paragraph about ctypes_configure Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Tue Mar 24 10:40:51 2009 @@ -83,19 +83,6 @@ * note: 32bit and a bit slow -CTypes configure -================ - -* our own small addition to general - CTypes usefulness - -* invokes C compiler for small details - -* can handle #defines, types, structure layout - etc. - -* works also for CPython! (antocuni) - Sqlite ====== @@ -247,10 +234,15 @@ =============================== - cross-compilation + - startup time + - security + - RAM usage + - share interpreter state across processes + - pypy approach a very good fit! 1.1 release From fijal at codespeak.net Tue Mar 24 12:01:30 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 24 Mar 2009 12:01:30 +0100 (CET) Subject: [pypy-svn] r63273 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090324110130.08B091684F9@codespeak.net> Author: fijal Date: Tue Mar 24 12:01:27 2009 New Revision: 63273 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: run non-crashing example by default Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Tue Mar 24 12:01:27 2009 @@ -78,7 +78,7 @@ try: - f7() + f0() except Exception, e: print '/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\' print e.__class__, e From arigo at codespeak.net Tue Mar 24 12:15:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Mar 2009 12:15:13 +0100 (CET) Subject: [pypy-svn] r63274 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090324111513.AC3F4168499@codespeak.net> Author: arigo Date: Tue Mar 24 12:15:13 2009 New Revision: 63274 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Log: Fix these three tests. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py Tue Mar 24 12:15:13 2009 @@ -45,8 +45,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [A.l, A.e0] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [A.l, A.e0] + equaloplists(spec.history.operations, [ ResOperation(rop.SETARRAYITEM_GC, [A.l, ConstInt(0), A.e0], None, A.ad), ResOperation(rop.JUMP, [A.l, A.e0], None) ]) @@ -74,8 +74,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [B.l, B.e0] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [B.l, B.e0] + equaloplists(spec.history.operations, [ ResOperation(rop.INT_ADD, [B.e0, ConstInt(1)], B.e1), ResOperation(rop.SETARRAYITEM_GC, [B.l, ConstInt(0), B.e1], None, B.ad), ResOperation(-123, [B.e1], None), Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Tue Mar 24 12:15:13 2009 @@ -141,8 +141,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [A.sum, A.v] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [A.sum, A.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), ResOperation('jump', [A.sum2, A.v2], None), @@ -189,8 +189,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [B.sum, B.n1] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [B.sum, B.n1] + equaloplists(spec.history.operations, [ # guard_class is gone ResOperation('escape', [B.n1], None), ResOperation('getfield_gc', [B.n1], B.v, B.ofs_value), @@ -244,8 +244,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [C.sum, C.n1] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [C.sum, C.n1] + equaloplists(spec.history.operations, [ # guard_class is gone ResOperation('escape', [C.n1], None), # <== escaping ResOperation('getfield_gc', [C.n1], C.v, C.ofs_value), @@ -303,15 +303,15 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [E.sum, E.v] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [E.sum, E.v] + equaloplists(spec.history.operations, [ # guard_class is gone ResOperation('int_sub', [E.v, ConstInt(1)], E.v2), ResOperation('int_add', [E.sum, E.v], E.sum2), ResOperation('guard_true', [E.v2], None), ResOperation('jump', [E.sum2, E.v2], None), ]) - guard_op = spec.loop.operations[-2] + guard_op = spec.history.operations[-2] assert guard_op.getopname() == 'guard_true' _, n2 = guard_op.suboperations[-1].args equaloplists(guard_op.suboperations, [ @@ -326,7 +326,7 @@ ## spec.find_nodes() ## spec.intersect_input_and_output() ## spec.optimize_loop() -## guard_op = spec.loop.operations[-2] +## guard_op = spec.history.operations[-2] ## v_sum_b = BoxInt(13) ## v_v_b = BoxInt(14) ## history = History(cpu) @@ -383,8 +383,8 @@ spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped spec.optimize_loop() - assert spec.loop.inputargs == [F.sum, F.v, F.n3] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [F.sum, F.v, F.n3] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), ResOperation('int_add', [F.sum, F.v], F.sum2), ResOperation('oononnull', [F.n3], F.vbool3), @@ -415,7 +415,7 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - equaloplists(spec.loop.operations, F2.ops) + equaloplists(spec.history.operations, F2.ops) # ____________________________________________________________ @@ -445,15 +445,15 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [G.sum, G.v] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [G.sum, G.v] + equaloplists(spec.history.operations, [ # guard_class is gone ResOperation('int_sub', [G.v, ConstInt(1)], G.v2), ResOperation('int_add', [G.sum, G.v], G.sum2), ResOperation('guard_true', [G.v2], None), ResOperation('jump', [G.sum2, ConstInt(124)], None), ]) - guard_op = spec.loop.operations[-2] + guard_op = spec.history.operations[-2] assert guard_op.getopname() == 'guard_true' _, n2 = guard_op.suboperations[-1].args equaloplists(guard_op.suboperations, [ @@ -578,9 +578,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.loop.operations[-1].args[-1] - assert spec.loop.inputargs == [K0.sum, K0.n1, K0.v] - equaloplists(spec.loop.operations, [ + v4 = spec.history.operations[-1].args[-1] + assert spec.history.inputargs == [K0.sum, K0.n1, K0.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [K0.v, ConstInt(1)], K0.v2), ResOperation('int_add', [K0.sum, K0.v], K0.sum2), ResOperation('int_add', [K0.sum2, K0.v], K0.sum3), @@ -612,9 +612,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.loop.operations[-1].args[-1] - assert spec.loop.inputargs == [K1.sum, K1.n1, K1.v] - equaloplists(spec.loop.operations, [ + v4 = spec.history.operations[-1].args[-1] + assert spec.history.inputargs == [K1.sum, K1.n1, K1.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [K1.v, ConstInt(1)], K1.v2), ResOperation('int_add', [K1.sum, K1.v], K1.sum2), ResOperation('int_add', [K1.sum2, K1.sum], K1.sum3), @@ -645,8 +645,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [K.sum, K.n1, K.v] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [K.sum, K.n1, K.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), ResOperation('int_add', [K.sum, K.v], K.sum2), ResOperation('int_add', [K.sum2, K.v], K.sum3), @@ -676,8 +676,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [L.sum, L.n1, L.v] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [L.sum, L.n1, L.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), ResOperation('int_add', [L.sum, L.v], L.sum2), ResOperation('escape', [L.n1], None), @@ -707,9 +707,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.loop.operations[-1].args[-1] - assert spec.loop.inputargs == [M.sum, M.n1, M.v] - equaloplists(spec.loop.operations, [ + v4 = spec.history.operations[-1].args[-1] + assert spec.history.inputargs == [M.sum, M.n1, M.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [M.v, ConstInt(1)], M.v2), ResOperation('int_add', [M.sum, M.v], M.sum2), ResOperation('escape', [M.n1], None), @@ -738,9 +738,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.loop.operations[-1].args[-1] - assert spec.loop.inputargs == [N.sum, N.n1, N.v] - equaloplists(spec.loop.operations, [ + v4 = spec.history.operations[-1].args[-1] + assert spec.history.inputargs == [N.sum, N.n1, N.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [N.v, ConstInt(1)], N.v2), ResOperation('int_add', [N.sum, N.v], N.sum2), ResOperation('escape', [N.n1], None), @@ -767,8 +767,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [] + equaloplists(spec.history.operations, [ ResOperation('escape', [], O1.n1), # only the first guard_class is left ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu)], @@ -797,8 +797,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [] + equaloplists(spec.history.operations, [ ResOperation('escape', [], O2.n1), ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu)], None), @@ -829,8 +829,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [] + equaloplists(spec.history.operations, [ ResOperation('escape', [], O3.n1), ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu)], None), @@ -868,4 +868,4 @@ # If it does, then aliasing is not correctly detected. # It is ok to reorder just the 'getfield_gc[n1], n2' operation, # but the three remaining getfields/setfields *must* be in that order. - equaloplists(spec.loop.operations, P.ops) + equaloplists(spec.history.operations, P.ops) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 24 12:15:13 2009 @@ -119,8 +119,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.loop.inputargs == [A.sum, A.fr, A.v] - equaloplists(spec.loop.operations, [ + assert spec.history.inputargs == [A.sum, A.fr, A.v] + equaloplists(spec.history.operations, [ ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), ResOperation('jump', [A.sum2, A.fr, A.v2], None), From arigo at codespeak.net Tue Mar 24 13:17:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Mar 2009 13:17:30 +0100 (CET) Subject: [pypy-svn] r63276 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090324121730.867A21684F8@codespeak.net> Author: arigo Date: Tue Mar 24 13:17:29 2009 New Revision: 63276 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Log: Finish adding support for "bridges" in optimize.py. Now a bridge means a branch that is part of a loop. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 24 13:17:29 2009 @@ -136,12 +136,12 @@ metainterp.history, metainterp.cpu) if old_loop is None: return None - target_loop = old_loops[0] - op.jump_target = target_loop source_loop = resumekey.loop guard_op = resumekey.guard_op - guard_op.suboperations = self.history.operations + guard_op.suboperations = metainterp.history.operations + op = guard_op.suboperations[-1] + op.jump_target = old_loop mark_keys_in_loop(source_loop, guard_op.suboperations) send_loop_to_backend(metainterp, source_loop) metainterp.stats.compiled_count += 1 - return target_loop + return old_loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Tue Mar 24 13:17:29 2009 @@ -213,13 +213,14 @@ perfect_specializer = PerfectSpecializer(history, options, cpu) perfect_specializer.find_nodes() for old_loop in old_loops: - if perfect_specializer.match(old_loop.operations): - perfect_specializer.adapt_for_match(old_loop.operations) + if perfect_specializer.match(old_loop): + perfect_specializer.adapt_for_match(old_loop) perfect_specializer.optimize_loop() return old_loop return None # no loop matches class PerfectSpecializer(object): + _allow_automatic_node_creation = False def __init__(self, history, options=Options(), cpu=None): self.history = history @@ -232,9 +233,12 @@ try: return self.nodes[box] except KeyError: - assert isinstance(box, Const) - node = self.nodes[box] = InstanceNode(box, escaped=True, - const=True) + if isinstance(box, Const): + node = InstanceNode(box, escaped=True, const=True) + else: + assert self._allow_automatic_node_creation + node = InstanceNode(box, escaped=False, startbox=True) + self.nodes[box] = node return node def getsource(self, box): @@ -279,8 +283,13 @@ def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True - for box in self.history.inputargs: - self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) + if self.history.inputargs is not None: + for box in self.history.inputargs: + self.nodes[box] = InstanceNode(box, escaped=False, + startbox=True) + else: + self._allow_automatic_node_creation = True + # for op in self.history.operations: #print '| ' + op.repr() opnum = op.opnum @@ -382,7 +391,7 @@ self.first_escaping_op = False for box in op.args: if isinstance(box, Box): - self.nodes[box].escaped = True + self.getnode(box).escaped = True box = op.result if box is not None: self.nodes[box] = InstanceNode(box, escaped=True) @@ -579,19 +588,25 @@ # we never perform this operation here, note def optimize_loop(self): + self._allow_automatic_node_creation = False newoperations = [] exception_might_have_happened = False - assert len(self.history.inputargs) == len(self.specnodes) - for i in range(len(self.specnodes)): - box = self.history.inputargs[i] - self.specnodes[i].mutate_nodes(self.nodes[box]) - newinputargs = self.expanded_version_of(self.history.inputargs, None) - -## assert mp.opnum == rop.CATCH -## for box in mp.args: -## self.nodes[box].cls = None -## assert not self.nodes[box].virtual - + if self.history.inputargs is not None: + # closing a loop + assert len(self.history.inputargs) == len(self.specnodes) + for i in range(len(self.specnodes)): + box = self.history.inputargs[i] + self.specnodes[i].mutate_nodes(self.nodes[box]) + newinputargs = self.expanded_version_of(self.history.inputargs, + None) + else: + # making a bridge + for node in self.nodes.values(): # xxx slow, maybe + if node.startbox: + node.cls = None + assert not node.virtual + newinputargs = None + # for op in self.history.operations: opnum = op.opnum if opnum == rop.JUMP: @@ -666,7 +681,7 @@ if self.optimize_getfield(instnode, ofsbox, op.result): continue elif opnum == rop.NEW_WITH_VTABLE: - # self.nodes[op.results[0]] keep the value from Steps (1,2) + # self.nodes[op.result] keeps the value from Steps (1,2) instnode = self.nodes[op.result] if not instnode.escaped: instnode.virtual = True @@ -749,7 +764,7 @@ instnode = InstanceNode(box) self.nodes[box] = instnode newoperations.append(op) - + # self.history.specnodes = self.specnodes self.history.inputargs = newinputargs self.history.operations = newoperations @@ -784,29 +799,24 @@ return False return True - def match(self, old_operations): - xxx - old_mp = old_operations[0] - jump_op = self.loop.operations[-1] - assert old_op.opnum == rop.MERGE_POINT + def match(self, old_loop): + jump_op = self.history.operations[-1] assert jump_op.opnum == rop.JUMP - assert len(old_mp.specnodes) == len(jump_op.args) - for i in range(len(old_mp.specnodes)): - old_specnode = old_mp.specnodes[i] - new_instnode = self.nodes[jump_op.args[i]] + assert len(old_loop.specnodes) == len(jump_op.args) + for i in range(len(old_loop.specnodes)): + old_specnode = old_loop.specnodes[i] + new_instnode = self.getnode(jump_op.args[i]) if not old_specnode.matches(new_instnode): return False return True - def adapt_for_match(self, old_operations): - old_mp = old_operations[0] - jump_op = self.loop.operations[-1] - assert old_op.opnum == rop.MERGE_POINT + def adapt_for_match(self, old_loop): + jump_op = self.history.operations[-1] assert jump_op.opnum == rop.JUMP - self.specnodes = old_mp.specnodes - for i in range(len(old_mp.specnodes)): - old_specnode = old_mp.specnodes[i] - new_instnode = self.nodes[jump_op.args[i]] + self.specnodes = old_loop.specnodes + for i in range(len(old_loop.specnodes)): + old_specnode = old_loop.specnodes[i] + new_instnode = self.getnode(jump_op.args[i]) old_specnode.adapt_to(new_instnode) def get_in_list(dict, boxes_or_consts): From arigo at codespeak.net Tue Mar 24 13:57:18 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Mar 2009 13:57:18 +0100 (CET) Subject: [pypy-svn] r63277 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090324125718.31ACF168454@codespeak.net> Author: arigo Date: Tue Mar 24 13:57:16 2009 New Revision: 63277 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Log: Import test_virtualizable from virtualizable-specnode-2, and tweak it. Also fix *when* the pygame viewer actually shows compiled graphs. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 24 13:57:16 2009 @@ -43,13 +43,14 @@ # the following is not translatable def _compile_new_loop_1(metainterp, old_loops): try: + old_loops_1 = old_loops[:] try: loop = compile_fresh_loop(metainterp, old_loops) except Exception, exc: show_loop(metainterp, error=exc) raise else: - if loop in old_loops: + if loop in old_loops_1: log.info("reusing loop at %r" % (loop,)) else: show_loop(metainterp, loop) @@ -112,9 +113,8 @@ loop.operations = history.operations loop.operations[-1].jump_target = loop mark_keys_in_loop(loop, loop.operations) - send_loop_to_backend(metainterp, loop) + send_loop_to_backend(metainterp, loop, True) metainterp.stats.loops.append(loop) - metainterp.stats.compiled_count += 1 old_loops.append(loop) return loop @@ -126,22 +126,27 @@ if op.opnum == rop.FAIL: op.key.loop = loop -def send_loop_to_backend(metainterp, loop): +def send_loop_to_backend(metainterp, loop, is_loop): metainterp.cpu.compile_operations(loop) + metainterp.stats.compiled_count += 1 + if not we_are_translated(): + if is_loop: + log.info("compiling new loop") + else: + log.info("compiling new bridge") # ____________________________________________________________ def compile_fresh_bridge(metainterp, old_loops, resumekey): - old_loop = optimize.optimize_bridge(metainterp.options, old_loops, - metainterp.history, metainterp.cpu) - if old_loop is None: + target_loop = optimize.optimize_bridge(metainterp.options, old_loops, + metainterp.history, metainterp.cpu) + if target_loop is None: return None source_loop = resumekey.loop guard_op = resumekey.guard_op guard_op.suboperations = metainterp.history.operations op = guard_op.suboperations[-1] - op.jump_target = old_loop + op.jump_target = target_loop mark_keys_in_loop(source_loop, guard_op.suboperations) - send_loop_to_backend(metainterp, source_loop) - metainterp.stats.compiled_count += 1 - return old_loop + send_loop_to_backend(metainterp, source_loop, False) + return target_loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Tue Mar 24 13:57:16 2009 @@ -6,6 +6,8 @@ from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR from pypy.jit.metainterp.test.test_vable_optimize import XY, xy_vtable +from pypy.jit.metainterp.warmspot import get_stats +from pypy.jit.metainterp import history promote_virtualizable = lloperation.llop.promote_virtualizable debug_print = lloperation.llop.debug_print @@ -25,62 +27,65 @@ return xy def test_preexisting_access(self): + py.test.skip("bugs") myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) def f(n): xy = self.setup() - xy.x = 10 + xy.inst_x = 10 while n > 0: myjitdriver.can_enter_jit(xy=xy, n=n) myjitdriver.jit_merge_point(xy=xy, n=n) - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 1 + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x + xy.inst_x = x + 1 n -= 1 - return xy.x + return xy.inst_x res = self.meta_interp(f, [20]) assert res == 30 self.check_loops(getfield_gc=0, setfield_gc=0) def test_preexisting_access_2(self): + py.test.skip("bugs") myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) def f(n): xy = self.setup() - xy.x = 100 + xy.inst_x = 100 while n > -8: myjitdriver.can_enter_jit(xy=xy, n=n) myjitdriver.jit_merge_point(xy=xy, n=n) if n > 0: - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 1 + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x + xy.inst_x = x + 1 else: - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 10 + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x + xy.inst_x = x + 10 n -= 1 - return xy.x + return xy.inst_x res = self.meta_interp(f, [5]) assert res == 185 self.check_loops(getfield_gc=0, setfield_gc=0) def test_two_paths_access(self): + py.test.skip("bugs") myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) def f(n): xy = self.setup() - xy.x = 100 + xy.inst_x = 100 while n > 0: myjitdriver.can_enter_jit(xy=xy, n=n) myjitdriver.jit_merge_point(xy=xy, n=n) - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x + promote_virtualizable(lltype.Void, xy, 'inst_x') + x = xy.inst_x if n <= 10: x += 1000 - xy.x = x + 1 + xy.inst_x = x + 1 n -= 1 - return xy.x + return xy.inst_x res = self.meta_interp(f, [18]) assert res == 10118 self.check_loops(getfield_gc=0, setfield_gc=0) @@ -394,7 +399,6 @@ assert res == 2 def test_pass_always_virtual_to_bridge(self): - py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], virtualizables = ['frame']) @@ -419,11 +423,22 @@ res = self.meta_interp(f, [30], listops=True) self.check_loops(setarrayitem_gc=0) - self.check_loop_count(2) + #self.check_loop_count(2) -- this is hard to predict right now: + # what occurs is that one path through the loop is compiled, + # then exits; then later when we compile again we see the other + # path of the loop by chance, then exits; then finally we see + # again one loop or the other, and this time we make a bridge. + # So dependening on details we may or may not compile the other + # path as an independent loop. assert res == 3 + if self.basic: + for loop in get_stats().loops: + for op in loop._all_operations(): + if op.getopname() == "int_sub": + assert isinstance(op.args[0], history.BoxInt) + assert isinstance(op.args[1], history.BoxInt) def test_virtual_obj_on_always_virtual(self): - py.test.skip("in-progress") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) @@ -452,12 +467,50 @@ s += frame.l[1].elem frame.l[1] = Stuff(n) n -= 1 - return s + return (frame.l[0].elem << 16) + frame.l[1].elem res = self.meta_interp(f, [30], listops=True) self.check_loops(getfield_gc=0) assert res == f(30) + + def test_virtual_obj_on_always_virtual_more_bridges(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + + _always_virtual_ = ['l'] + + def __init__(self, l): + self.l = l + + class Stuff(object): + def __init__(self, elem): + self.elem = elem + + def f(n): + frame = Frame([Stuff(3), Stuff(4)]) + s = 0 + while n > 0: + jitdriver.can_enter_jit(frame=frame, n=n, s=s) + jitdriver.jit_merge_point(frame=frame, n=n, s=s) + if n % 2: + s += frame.l[0].elem + frame.l[0] = Stuff(n) + elif n % 3: + s += 1 + else: + s += frame.l[1].elem + frame.l[1] = Stuff(n) + n -= 1 + return (frame.l[0].elem << 16) + frame.l[1].elem + + res = self.meta_interp(f, [60], listops=True) + self.check_loops(getfield_gc=0) + assert res == f(60) + def test_external_read(self): py.test.skip("Fails") jitdriver = JitDriver(greens = [], reds = ['frame'], From arigo at codespeak.net Tue Mar 24 14:19:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Mar 2009 14:19:56 +0100 (CET) Subject: [pypy-svn] r63278 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090324131956.3A73516850C@codespeak.net> Author: arigo Date: Tue Mar 24 14:19:53 2009 New Revision: 63278 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Log: Fix? Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 24 14:19:53 2009 @@ -138,6 +138,9 @@ # ____________________________________________________________ def compile_fresh_bridge(metainterp, old_loops, resumekey): + #temp = TreeLoop('temp') + #temp.operations = metainterp.history.operations + #temp.show() target_loop = optimize.optimize_bridge(metainterp.options, old_loops, metainterp.history, metainterp.cpu) if target_loop is None: Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Tue Mar 24 14:19:53 2009 @@ -568,9 +568,11 @@ return True # this means field comes from a virtualizable but is never # written. Cool, simply make the result constant - self.nodes[box] = InstanceNode(box.constbox(), const=True) - return True - elif ofs in instnode.cleanfields: + # XXX uh??? making it constant in the resulting assembler + # is just plain wrong + #self.nodes[box] = InstanceNode(box.constbox(), const=True) + #return True + if ofs in instnode.cleanfields: self.nodes[box] = instnode.cleanfields[ofs] return True else: From arigo at codespeak.net Tue Mar 24 14:31:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Mar 2009 14:31:11 +0100 (CET) Subject: [pypy-svn] r63279 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090324133111.36CB8168479@codespeak.net> Author: arigo Date: Tue Mar 24 14:31:09 2009 New Revision: 63279 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Log: Tweak. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 24 14:31:09 2009 @@ -140,7 +140,7 @@ def compile_fresh_bridge(metainterp, old_loops, resumekey): #temp = TreeLoop('temp') #temp.operations = metainterp.history.operations - #temp.show() + #metainterp.stats.view(extraloops=[temp]) target_loop = optimize.optimize_bridge(metainterp.options, old_loops, metainterp.history, metainterp.cpu) if target_loop is None: From afa at codespeak.net Tue Mar 24 15:41:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 24 Mar 2009 15:41:10 +0100 (CET) Subject: [pypy-svn] r63280 - pypy/trunk/pypy/translator/platform Message-ID: <20090324144110.0227616845A@codespeak.net> Author: afa Date: Tue Mar 24 15:41:08 2009 New Revision: 63280 Modified: pypy/trunk/pypy/translator/platform/windows.py Log: Don't crash if the version of the msvc compiler cannot be determined Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Tue Mar 24 15:41:08 2009 @@ -88,7 +88,11 @@ returncode, stdout, stderr = _run_subprocess(self.cc, '', env=self.c_environ) r = re.search('Version ([0-9]+)\.([0-9]+)', stderr) - self.version = int(''.join(r.groups())) / 10 - 60 + if r is not None: + self.version = int(''.join(r.groups())) / 10 - 60 + else: + # Probably not a msvc compiler... + self.version = 0 # Install debug options only when interpreter is in debug mode if sys.executable.lower().endswith('_d.exe'): From afa at codespeak.net Tue Mar 24 15:55:54 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 24 Mar 2009 15:55:54 +0100 (CET) Subject: [pypy-svn] r63281 - pypy/trunk/pypy/translator/platform Message-ID: <20090324145554.E56EF168480@codespeak.net> Author: afa Date: Tue Mar 24 15:55:51 2009 New Revision: 63281 Modified: pypy/trunk/pypy/translator/platform/windows.py Log: Translation with mingw: for now, return empty dirs for the libffi library. Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Tue Mar 24 15:55:51 2009 @@ -272,3 +272,10 @@ def _args_for_shared(self, args): return ['-shared'] + args + def include_dirs_for_libffi(self): + return [] + + def library_dirs_for_libffi(self): + return [] + + From cfbolz at codespeak.net Tue Mar 24 17:34:01 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 24 Mar 2009 17:34:01 +0100 (CET) Subject: [pypy-svn] r63282 - in pypy/branch/pyjitpl5-PyGirl/pypy: jit/tl lang/gameboy lang/gameboy/profiling Message-ID: <20090324163401.AF90716851B@codespeak.net> Author: cfbolz Date: Tue Mar 24 17:33:59 2009 New Revision: 63282 Added: pypy/branch/pyjitpl5-PyGirl/pypy/jit/tl/gbjit.py (contents, props changed) pypy/branch/pyjitpl5-PyGirl/pypy/jit/tl/gbjit_child.py (contents, props changed) Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cartridge.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Log: try to rewrite gameboy implementation to be more jit-friendly. also write a file that lets one see better what is going on with the jit. Added: pypy/branch/pyjitpl5-PyGirl/pypy/jit/tl/gbjit.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-PyGirl/pypy/jit/tl/gbjit.py Tue Mar 24 17:33:59 2009 @@ -0,0 +1,64 @@ +""" +A file that invokes translation of PyGirl with the JIT enabled. +""" + +import py, os + +from pypy.config.translationoption import set_opt_level, get_combined_translation_config +from pypy.lang.gameboy.profiling.gameboy_profiling_implementation import GameBoyProfiler +from pypy.rpython.annlowlevel import llhelper, llstr, hlstr +from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.lltypesystem import lltype +from pypy.translator.goal import unixcheckpoint + +config = get_combined_translation_config(translating=True) +config.translation.backendopt.inline_threshold = 0 +set_opt_level(config, level='1') +print config + +import sys, pdb, time + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" + +gameBoy = GameBoyProfiler() +# an infinite loop +filename = ROM_PATH+"/rom3/rom3.gb" +gameBoy.load_cartridge_file(str(filename), verify=False) +gameBoy.reset() + +def entry_point(): + execution_seconds = 600 + + start = time.time() + gameBoy.mainLoop(execution_seconds) + print time.time() - start + return 0 + +def test_run_translation(): + from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy + from pypy.rpython.test.test_llinterp import get_interpreter + + # first annotate, rtype, and backendoptimize PyPy + try: + interp, graph = get_interpreter(entry_point, [], backendopt=True, + config=config) + except Exception, e: + print '%s: %s' % (e.__class__, e) + pdb.post_mortem(sys.exc_info()[2]) + raise + + # parent process loop: spawn a child, wait for the child to finish, + # print a message, and restart + unixcheckpoint.restartable_point(auto='run') + + from pypy.jit.tl.gbjit_child import run_child + run_child(globals(), locals()) + + +if __name__ == '__main__': + import sys + if len(sys.argv) > 1: + # debugging: run the code directly + entry_point() + else: + test_run_translation() Added: pypy/branch/pyjitpl5-PyGirl/pypy/jit/tl/gbjit_child.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-PyGirl/pypy/jit/tl/gbjit_child.py Tue Mar 24 17:33:59 2009 @@ -0,0 +1,30 @@ +from pypy.conftest import option +from pypy.rpython.lltypesystem import lltype +from pypy.jit.metainterp import warmspot +from pypy.jit.metainterp.policy import ManualJitPolicy + +from pypy.translator.backendopt.support import find_calls_from + +class GbJitPolicy(ManualJitPolicy): + def look_inside_function(self, func): + if "update_clock" in func.func_name: + return False + if "ll_int2hex" in func.func_name: + return False + return True # XXX for now + +def run_child(glob, loc): + import sys, pdb + interp = loc['interp'] + graph = loc['graph'] + interp.malloc_check = False + + #def returns_null(T, *args, **kwds): + # return lltype.nullptr(T) + #interp.heap.malloc_nonmovable = returns_null # XXX + + print 'warmspot.jittify_and_run() started...' + policy = GbJitPolicy(interp.typer.annotator.translator) + option.view = True + warmspot.jittify_and_run(interp, graph, [], policy=policy, + listops=True) Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cartridge.py Tue Mar 24 17:33:59 2009 @@ -31,6 +31,7 @@ return constants.CATRIDGE_TYPE_MAPPING[cartridge_type](rom, ram, clock) else: raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridge_type)+")") +create_bank_controller._look_inside_me_ = False def map_to_byte( string): mapped = [0]*len(string) @@ -307,6 +308,7 @@ hex(self.max_rom_bank_size))) self.rom = buffer self.rom_size = self.rom_bank_size * banks - 1 + set_rom._look_inside_me_ = False def set_ram(self, buffer): @@ -317,6 +319,7 @@ hex(self.max_ram_bank_size))) self.ram = buffer self.ram_size = constants.RAM_BANK_SIZE * banks - 1 + set_rom._look_inside_me_ = False def read(self, address): @@ -334,8 +337,8 @@ #return 0xFF raise Exception("RAM is not Enabled") #return 0xFF - raise InvalidMemoryAccessException("MBC: Invalid address, out of range: %s" - % hex(address)) + raise InvalidMemoryAccessException#("MBC: Invalid address, out of range: %s" + # % hex(address)) def write(self, address, data): raise InvalidMemoryAccessException("MBC: Invalid write access") Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Tue Mar 24 17:33:59 2009 @@ -20,7 +20,7 @@ DEBUG_INSTRUCTION_COUNTER = 1 -jitdriver = JitDriver(greens = ['pc'], reds=['af', 'bc', 'de', 'hl', 'sp']) +jitdriver = JitDriver(greens = ['pc'], reds=['self'], virtualizables=['self']) class CPU(object): """ @@ -28,6 +28,9 @@ Central Unit Processor_a (Sharp LR35902 CPU) """ + _virtualizable2_ = True + _always_virtual_ = 'b c bc d e de h l hl hli pc sp a flag af interrupt rom'.split() + def __init__(self, interrupt, memory): assert isinstance(interrupt, Interrupt) self.interrupt = interrupt @@ -176,8 +179,8 @@ self.cycles += ticks self.handle_pending_interrupts() while self.cycles > 0: + jitdriver.jit_merge_point(pc=self.pc.value, self=self) opcode = self.fetch(use_cycles=False) - jitdriver.jit_merge_point(pc=self.pc.value) self.execute(opcode) def emulate_step(self): @@ -290,7 +293,6 @@ self.pc.set(address, use_cycles=use_cycles) # 1 cycle if use_cycles: self.cycles += 1 - jitdriver.can_enter_jit(pc=self.pc.value) def load(self, getCaller, setCaller): # 1 cycle @@ -659,9 +661,12 @@ def jump(self): # JP nnnn, 4 cycles - self.pc.set(self.fetch_double_address()) # 1+2 cycles + oldpc = self.pc.value + newpc = self.fetch_double_address() + self.pc.set(newpc) # 1+2 cycles self.cycles -= 1 - jitdriver.can_enter_jit(pc=self.pc.value) + if oldpc >= newpc: + jitdriver.can_enter_jit(pc=self.pc.value, self=self) def conditional_jump(self, cc): # JP cc,nnnn 3,4 cycles @@ -672,9 +677,11 @@ def relative_jump(self): # JR +nn, 3 cycles - self.pc.add(process_2s_complement(self.fetch())) # 3 + 1 cycles + increment = process_2s_complement(self.fetch()) + self.pc.add(increment) # 3 + 1 cycles self.cycles += 1 - jitdriver.can_enter_jit(pc=self.pc.value) + if increment <= 0: + jitdriver.can_enter_jit(pc=self.pc.value, self=self) def relative_conditional_jump(self, cc): # JR cc,+nn, 2,3 cycles @@ -697,7 +704,6 @@ def ret(self): # RET 4 cycles self.double_register_inverse_call(CPUPopCaller(self), self.pc) - jitdriver.can_enter_jit(pc=self.pc.value) def conditional_return(self, cc): # RET cc 2,5 cycles Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/profiling/gameboy_profiling_implementation.py Tue Mar 24 17:33:59 2009 @@ -28,7 +28,7 @@ self.sound_driver = SoundDriver() def mainLoop(self, execution_seconds): - self.reset() + #self.reset() self.is_running = True for i in range(int(execution_seconds * FPS)): self.emulate_cycle() From cfbolz at codespeak.net Tue Mar 24 17:57:09 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 24 Mar 2009 17:57:09 +0100 (CET) Subject: [pypy-svn] r63283 - pypy/branch/pyjitpl5-PyGirl/pypy/rlib Message-ID: <20090324165709.E6785168432@codespeak.net> Author: cfbolz Date: Tue Mar 24 17:57:07 2009 New Revision: 63283 Modified: pypy/branch/pyjitpl5-PyGirl/pypy/rlib/jit.py Log: rename self, for the case where there is a jit variable called self Modified: pypy/branch/pyjitpl5-PyGirl/pypy/rlib/jit.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/rlib/jit.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/rlib/jit.py Tue Mar 24 17:57:07 2009 @@ -113,13 +113,13 @@ def _freeze_(self): return True - def jit_merge_point(self, **livevars): + def jit_merge_point(_self_with_unlikely_name, **livevars): # special-cased by ExtRegistryEntry - assert dict.fromkeys(livevars) == self._alllivevars + assert dict.fromkeys(livevars) == _self_with_unlikely_name._alllivevars - def can_enter_jit(self, **livevars): + def can_enter_jit(_self_with_unlikely_name, **livevars): # special-cased by ExtRegistryEntry - assert dict.fromkeys(livevars) == self._alllivevars + assert dict.fromkeys(livevars) == _self_with_unlikely_name._alllivevars def _set_param(self, name, value): # special-cased by ExtRegistryEntry From cfbolz at codespeak.net Tue Mar 24 18:11:47 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 24 Mar 2009 18:11:47 +0100 (CET) Subject: [pypy-svn] r63284 - in pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy: . test Message-ID: <20090324171147.79D01168481@codespeak.net> Author: cfbolz Date: Tue Mar 24 18:11:46 2009 New Revision: 63284 Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_2.py Log: make cpu.rom a string to help the jit Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Tue Mar 24 18:11:46 2009 @@ -4,7 +4,7 @@ from pypy.lang.gameboy.cpu_register import Register, DoubleRegister,\ ReservedDoubleRegister,\ FlagRegister, ImmediatePseudoRegister -from pypy.rlib.jit import JitDriver +from pypy.rlib.jit import JitDriver, hint # --------------------------------------------------------------------------- @@ -39,7 +39,7 @@ self.halted = False self.cycles = 0 self.ini_registers() - self.rom = [0] + self.rom = "\x00" self.reset() def ini_registers(self): @@ -171,8 +171,16 @@ return not self.is_n() def set_rom(self, banks): - self.rom = banks - + rom = [] + for i in banks: + rom.append(chr(i)) + self.rom = "".join(rom) + + def _change_rom(self, address, value): + """NOT_RPYTHON: only for tests""" + rom = self.rom + self.rom = rom[:address] + chr(value) + rom[address + 1:] + # --------------------------------------------------------------- def emulate(self, ticks): @@ -220,7 +228,6 @@ self.last_op_code = op_code OP_CODES[op_code](self) - # ------------------------------------------------------------------- def debug(self): @@ -246,7 +253,7 @@ self.cycles += 1 pc = self.pc.get(use_cycles) if pc <= 0x3FFF: - data = self.rom[self.pc.get(use_cycles)] + data = ord(self.rom[self.pc.get(use_cycles)]) else: data = self.memory.read(self.pc.get(use_cycles)) self.pc.inc(use_cycles) # 2 cycles @@ -681,7 +688,8 @@ self.pc.add(increment) # 3 + 1 cycles self.cycles += 1 if increment <= 0: - jitdriver.can_enter_jit(pc=self.pc.value, self=self) + pc = self.pc.value + jitdriver.can_enter_jit(pc=pc, self=self) def relative_conditional_jump(self, cc): # JR cc,+nn, 2,3 cycles Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu.py Tue Mar 24 18:11:46 2009 @@ -71,7 +71,7 @@ value = 0x12 # in rom cpu.pc.set(address) - cpu.rom[address] = value + cpu._change_rom(address, value) startCycles = cpu.cycles assert cpu.fetch() == value assert startCycles-cpu.cycles == 1 @@ -104,7 +104,7 @@ cpu = get_cpu() pc = cpu.pc.get() value = 0x12 - cpu.rom[constants.RESET_PC] = value + cpu._change_rom(constants.RESET_PC, value) # test jr_nn startCycles = cpu.cycles cpu.relative_conditional_jump(True) @@ -141,7 +141,7 @@ prepare_for_fetch(cpu, 0x12, 0x12) cpu.memory.write(0x1234, 0x12) assert cpu.is_z() == True - cpu.rom[0x1234] = 0x12 + cpu._change_rom(0x1234, 0x12) assert cpu.is_z() == True @@ -249,10 +249,10 @@ def prepare_for_fetch(cpu, value, valueLo=None): pc = cpu.pc.get() if valueLo is not None: - cpu.rom[pc] = valueLo & 0xFF + cpu._change_rom(pc, valueLo & 0xFF) cpu.memory.write(pc, valueLo & 0xFF) pc += 1 - cpu.rom[pc] = value & 0xFF + cpu._change_rom(pc, value & 0xFF) cpu.memory.write(pc, value & 0xFF) def test_prepare_for_fetch(): Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_2.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_2.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/test/test_cpu_2.py Tue Mar 24 18:11:46 2009 @@ -91,10 +91,10 @@ def prepare_for_fetch(cpu, value, valueLo=None): pc = cpu.pc.get() if valueLo is not None: - cpu.rom[pc] = valueLo & 0xFF + cpu._change_rom(pc, valueLo & 0xFF) cpu.memory.write(pc, valueLo & 0xFF) pc += 1 - cpu.rom[pc] = value & 0xFF + cpu._change_rom(pc, value & 0xFF) cpu.memory.write(pc, value & 0xFF) def test_prepare_for_fetch(): @@ -976,4 +976,4 @@ assert cpu.a.get() == 0x43 assert_flags(cpu, z=False, n=False, h=False, c=False) - \ No newline at end of file + From afa at codespeak.net Tue Mar 24 18:45:43 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 24 Mar 2009 18:45:43 +0100 (CET) Subject: [pypy-svn] r63285 - pypy/trunk/pypy/translator/cli Message-ID: <20090324174543.B824916846B@codespeak.net> Author: afa Date: Tue Mar 24 18:45:36 2009 New Revision: 63285 Modified: pypy/trunk/pypy/translator/cli/rte.py Log: On Windows, the cli compiler output messages to stdout. Add it to the exception. Modified: pypy/trunk/pypy/translator/cli/rte.py ============================================================================== --- pypy/trunk/pypy/translator/cli/rte.py (original) +++ pypy/trunk/pypy/translator/cli/rte.py Tue Mar 24 18:45:36 2009 @@ -60,7 +60,8 @@ stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = compiler.communicate() retval = compiler.wait() - assert retval == 0, 'Failed to compile %s: the compiler said:\n %s' % (cls.OUTPUT, stderr) + assert retval == 0, 'Failed to compile %s: the compiler said:\n %s' % ( + cls.OUTPUT, stdout + stderr) if cls.ALIAS is not None: alias = cls._filename(cls.ALIAS) shutil.copy(out, alias) From afa at codespeak.net Tue Mar 24 18:59:03 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 24 Mar 2009 18:59:03 +0100 (CET) Subject: [pypy-svn] r63286 - pypy/trunk/pypy/translator Message-ID: <20090324175903.A9C631684FD@codespeak.net> Author: afa Date: Tue Mar 24 18:59:01 2009 New Revision: 63286 Modified: pypy/trunk/pypy/translator/geninterplevel.py Log: This has been sleeping in my workspace: - check a variable before using it + harmless backslash to help Emacs indenting the code correctly. Modified: pypy/trunk/pypy/translator/geninterplevel.py ============================================================================== --- pypy/trunk/pypy/translator/geninterplevel.py (original) +++ pypy/trunk/pypy/translator/geninterplevel.py Tue Mar 24 18:59:01 2009 @@ -420,7 +420,7 @@ # see if we have space.builtin in this context space.builtin except AttributeError: - print "didn't get", %(bltin)r + print "didn\'t get", %(bltin)r def %(name)s(space, __args__): w_func = space.builtin.get(%(bltin)r) return space.call_args(w_func, __args__) @@ -974,10 +974,10 @@ def nameof_property(self, prop): origin = prop.__doc__ # XXX quite a hack - name = self.uniquename('gprop_' + origin) if not origin: raise ValueError("sorry, cannot build properties" " without a helper in __doc__") + name = self.uniquename('gprop_' + origin) # property is lazy loaded app-level as well, trigger it*s creation self.initcode.append1('space.builtin.get("property") # pull it in') globname = self.nameof(self.moddict) From afa at codespeak.net Tue Mar 24 19:01:57 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 24 Mar 2009 19:01:57 +0100 (CET) Subject: [pypy-svn] r63287 - pypy/trunk/pypy/translator/platform Message-ID: <20090324180157.6F6271684F9@codespeak.net> Author: afa Date: Tue Mar 24 19:01:56 2009 New Revision: 63287 Modified: pypy/trunk/pypy/translator/platform/__init__.py Log: Be a little more verbose when printing error messages 5 lines are often not enough. Also account for the Microsoft compilers printing compilation errors to stdout. Modified: pypy/trunk/pypy/translator/platform/__init__.py ============================================================================== --- pypy/trunk/pypy/translator/platform/__init__.py (original) +++ pypy/trunk/pypy/translator/platform/__init__.py Tue Mar 24 19:01:56 2009 @@ -32,7 +32,10 @@ self.err = err.replace('\r\n', '\n') def __repr__(self): - return "" % safe_repr._repr(self.err) + if self.err: + return "" % safe_repr._repr(self.err) + else: + return "" % safe_repr._repr(self.out) __str__ = __repr__ @@ -100,9 +103,9 @@ errorfile = outname.new(ext='errors') errorfile.write(stderr) stderrlines = stderr.splitlines() - for line in stderrlines[:5]: + for line in stderrlines[:20]: log.ERROR(line) - if len(stderrlines) > 5: + if len(stderrlines) > 20: log.ERROR('...') raise CompilationError(stdout, stderr) From afa at codespeak.net Tue Mar 24 19:11:34 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 24 Mar 2009 19:11:34 +0100 (CET) Subject: [pypy-svn] r63288 - in pypy/trunk/pypy: module/bz2 rlib Message-ID: <20090324181134.7747B1683DB@codespeak.net> Author: afa Date: Tue Mar 24 19:11:33 2009 New Revision: 63288 Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py pypy/trunk/pypy/rlib/rzlib.py Log: Update zlib and bz2 for the mingw compiler which prefers libz.a and libbz2.a mingw can use the zlib.lib compiled by a MSVC compiler, except that this does not link due to a mess with different C runtimes and missing manifests, giving error messages that I shall not utter here. Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/trunk/pypy/module/bz2/interp_bz2.py (original) +++ pypy/trunk/pypy/module/bz2/interp_bz2.py Tue Mar 24 19:11:33 2009 @@ -8,10 +8,12 @@ from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app, Arguments from pypy.rlib.streamio import Stream from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.platform import platform as compiler from pypy.rlib.rarithmetic import intmask, r_longlong import sys -if sys.platform == "win32": + +if compiler.name == "win32": libname = 'libbz2' else: libname = 'bz2' Modified: pypy/trunk/pypy/rlib/rzlib.py ============================================================================== --- pypy/trunk/pypy/rlib/rzlib.py (original) +++ pypy/trunk/pypy/rlib/rzlib.py Tue Mar 24 19:11:33 2009 @@ -2,8 +2,9 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.platform import platform as compiler -if sys.platform == "win32": +if compiler.name == "win32": libname = 'zlib' else: libname = 'z' From afa at codespeak.net Wed Mar 25 10:14:20 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 25 Mar 2009 10:14:20 +0100 (CET) Subject: [pypy-svn] r63309 - in pypy/trunk/pypy: module/bz2 rlib Message-ID: <20090325091420.8761F1684F2@codespeak.net> Author: afa Date: Wed Mar 25 10:14:18 2009 New Revision: 63309 Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py pypy/trunk/pypy/rlib/rzlib.py Log: fix a typo that disabled bz2 and zlib modules on windows Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/trunk/pypy/module/bz2/interp_bz2.py (original) +++ pypy/trunk/pypy/module/bz2/interp_bz2.py Wed Mar 25 10:14:18 2009 @@ -13,7 +13,7 @@ import sys -if compiler.name == "win32": +if compiler.name == "msvc": libname = 'libbz2' else: libname = 'bz2' Modified: pypy/trunk/pypy/rlib/rzlib.py ============================================================================== --- pypy/trunk/pypy/rlib/rzlib.py (original) +++ pypy/trunk/pypy/rlib/rzlib.py Wed Mar 25 10:14:18 2009 @@ -4,7 +4,7 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.platform import platform as compiler -if compiler.name == "win32": +if compiler.name == "msvc": libname = 'zlib' else: libname = 'z' From afa at codespeak.net Wed Mar 25 10:20:29 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 25 Mar 2009 10:20:29 +0100 (CET) Subject: [pypy-svn] r63310 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090325092029.766E21684F3@codespeak.net> Author: afa Date: Wed Mar 25 10:20:27 2009 New Revision: 63310 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_bz2.py Log: Explicitely closes the file at the end of the test. test_bz2 now passes on Windows Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_bz2.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_bz2.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_bz2.py Wed Mar 25 10:20:27 2009 @@ -180,6 +180,7 @@ bz2f = BZ2File(self.filename, "r") self.assertRaises(IOError, bz2f.write, "a") self.assertRaises(IOError, bz2f.writelines, ["a"]) + bz2f.close() def testSeekForward(self): # "Test BZ2File.seek(150, 0)" From antocuni at codespeak.net Wed Mar 25 10:22:23 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 25 Mar 2009 10:22:23 +0100 (CET) Subject: [pypy-svn] r63311 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090325092223.0C20F1684FF@codespeak.net> Author: antocuni Date: Wed Mar 25 10:22:23 2009 New Revision: 63311 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: update my dates Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Wed Mar 25 10:22:23 2009 @@ -12,7 +12,7 @@ ==================== ============== ======================= Armin Rigo -- private Carl Friedrich Bolz 14th-21st Ermina -Antonio Cuni 14th-21st Ermina +Antonio Cuni 15th-21st Ermina Samuele Pedroni 14th-22nd Ermina Anders Hammarquist 14th-22nd Ermina ==================== ============== ======================= From cfbolz at codespeak.net Wed Mar 25 11:01:05 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Mar 2009 11:01:05 +0100 (CET) Subject: [pypy-svn] r63314 - pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy Message-ID: <20090325100105.98B4C168075@codespeak.net> Author: cfbolz Date: Wed Mar 25 11:01:04 2009 New Revision: 63314 Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Log: use some jit hints to improve the code Modified: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/cpu.py Wed Mar 25 11:01:04 2009 @@ -250,13 +250,16 @@ def fetch(self, use_cycles=True): # Fetching 1 cycle if use_cycles: - self.cycles += 1 + self.cycles -= 1 # upate cycles manually pc = self.pc.get(use_cycles) + pc = hint(pc, promote=True) if pc <= 0x3FFF: - data = ord(self.rom[self.pc.get(use_cycles)]) + rom = hint(self.rom, promote=True) + data = ord(rom[pc]) + data = hint(data, promote=True) else: - data = self.memory.read(self.pc.get(use_cycles)) - self.pc.inc(use_cycles) # 2 cycles + data = self.memory.read(pc) + self.pc.value = pc + 1 # do the update manually to help the jit return data def fetch_double_address(self): From cami at codespeak.net Wed Mar 25 12:12:19 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 25 Mar 2009 12:12:19 +0100 (CET) Subject: [pypy-svn] r63317 - pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/rom/rom3 Message-ID: <20090325111219.60C9516843C@codespeak.net> Author: cami Date: Wed Mar 25 12:12:17 2009 New Revision: 63317 Added: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/rom/rom3/rom3loopCall.gb (contents, props changed) Log: adding rom with call from within a loop Added: pypy/branch/pyjitpl5-PyGirl/pypy/lang/gameboy/rom/rom3/rom3loopCall.gb ============================================================================== Binary file. No diff available. From hpk at codespeak.net Wed Mar 25 13:20:55 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 25 Mar 2009 13:20:55 +0100 (CET) Subject: [pypy-svn] r63321 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090325122055.63296168494@codespeak.net> Author: hpk Date: Wed Mar 25 13:20:53 2009 New Revision: 63321 Added: pypy/extradoc/talk/pycon2009/vm-summit/author.latex pypy/extradoc/talk/pycon2009/vm-summit/makepdf (contents, props changed) pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf (contents, props changed) pypy/extradoc/talk/pycon2009/vm-summit/stylesheet.latex pypy/extradoc/talk/pycon2009/vm-summit/title.latex Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: (hpk, fijal) current status of slisdes Added: pypy/extradoc/talk/pycon2009/vm-summit/author.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/vm-summit/author.latex Wed Mar 25 13:20:53 2009 @@ -0,0 +1,7 @@ +\definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} + +\title[PyPy status / mobile perspectives]{PyPy status / mobile perspectives} +\author[H. Krekel]{Holger Krekel \\ http://merlinux.eu} + +\institute[OpenBossa 2009, Recife, Brazil]{OpenBossa 2009, Brazil} +\date{March 11, 2009} Added: pypy/extradoc/talk/pycon2009/vm-summit/makepdf ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/vm-summit/makepdf Wed Mar 25 13:20:53 2009 @@ -0,0 +1,14 @@ +#!/bin/bash + +# you can find rst2beamer.py here: +# http://codespeak.net/svn/user/antocuni/bin/rst2beamer.py + +# WARNING: to work, it needs this patch for docutils +# https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414 + +BASE=slides +python2.5 `which rst2beamer.py` --stylesheet=stylesheet.latex --documentoptions=14pt $BASE.txt $BASE.latex || exit +sed 's/\\date{}/\\input{author.latex}/' $BASE.latex >tmpfile || exit +sed 's/\\maketitle/\\input{title.latex}/' tmpfile >$BASE.latex || exit +pdflatex $BASE.latex || exit + Added: pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Wed Mar 25 13:20:53 2009 @@ -1,49 +1,70 @@ +PyPy - what is it? +================================= + +* a Python Interpreter +* a VM Generator -PyPy - Motivation +Python Interpreter ================================= -.. image:: picture.png - :scale: 50 - :align: center +* single source "specification" in RPython +* PyPy compiles it to native C, .NET, JVM -High level implementation - how exactly +RPython: static subset of Python ======================================= -* Raise the level at which you implement programming languages +* static subset of Python +* we do whole-program type-inference -* Python is high level enough +Interpreters written in RPython +======================================= -* We derived a static subset of Python that can be - efficiently compiled, called RPython +* directly testable on top of CPython -XXX show mario +* GC, threading, **JIT-Compiler** added automatically! Garbage Collection framework ==================================== -* Written in Python +* write GC in RPython +* test in simulation (with pdb!) +* weave into translation of *any* interpreter -* We introduced a bunch of low-level primitives +JIT-Compiler Generator +==================================== -* We can test a GC on top of Python (running specification) +* written in RPython +* test in simulation (with pdb!) +* weave into translation of *any* interpreter -* ... and translate to a target +JIT-generator for Python +==================================== -* Completely interpreter-agnostic +* removes object boxing, frame objects penalties +* but can present them if needed! +* current speedup: 20 times for simple examples -XXX show a piece of code in GC +Any Interpreter or VM? +==================================== + +.. image:: mario.png + :scale: 100 + :align: center + +Strong points +======================================== +* large automated test suite, good debugging tools +* Generating **efficient* Interpreters +* works for Python, a relatively complex language -Generating JIT Compilers +Challenges ======================================== -* We apply JIT generator to interpreters +* generate full JIT-Compiler for Python! -* A couple of manual hints is required +* release and distribute Python Interpreter -* We can try on top of Python as well +* get some more funding -Challenges -====================== -XXX out of time I suppose Added: pypy/extradoc/talk/pycon2009/vm-summit/stylesheet.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/vm-summit/stylesheet.latex Wed Mar 25 13:20:53 2009 @@ -0,0 +1,10 @@ +\usetheme{Boadilla} +\setbeamercovered{transparent} +\setbeamertemplate{navigation symbols}{} + +\definecolor{darkgreen}{rgb}{0, 0.5, 0.0} +\newcommand{\docutilsrolegreen}[1]{\color{darkgreen}#1\normalcolor} +\newcommand{\docutilsrolered}[1]{\color{red}#1\normalcolor} + +\newcommand{\green}[1]{\color{darkgreen}#1\normalcolor} +\newcommand{\red}[1]{\color{red}#1\normalcolor} Added: pypy/extradoc/talk/pycon2009/vm-summit/title.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/vm-summit/title.latex Wed Mar 25 13:20:53 2009 @@ -0,0 +1,7 @@ +\begin{titlepage} +\begin{figure}[h] +\includegraphics[width=64px,height=64px]{merlinux-logo.jpg} +\qquad +\includegraphics[width=80px]{../../img/py-web.png} +\end{figure} +\end{titlepage} From hpk at codespeak.net Wed Mar 25 14:54:42 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 25 Mar 2009 14:54:42 +0100 (CET) Subject: [pypy-svn] r63322 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090325135442.E628516842B@codespeak.net> Author: hpk Date: Wed Mar 25 14:54:39 2009 New Revision: 63322 Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: updats Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Wed Mar 25 14:54:39 2009 @@ -30,6 +30,13 @@ * test in simulation (with pdb!) * weave into translation of *any* interpreter +stackless / threading +==================================== + +* stackless transform for rpython programs +* inifite recursion, greenlets, co-routines in Python! +* composable! + JIT-Compiler Generator ==================================== From arigo at codespeak.net Wed Mar 25 15:00:15 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Mar 2009 15:00:15 +0100 (CET) Subject: [pypy-svn] r63323 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090325140015.6809D168497@codespeak.net> Author: arigo Date: Wed Mar 25 15:00:14 2009 New Revision: 63323 Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: Typo and minor clarifications. Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Wed Mar 25 15:00:14 2009 @@ -33,8 +33,8 @@ stackless / threading ==================================== -* stackless transform for rpython programs -* inifite recursion, greenlets, co-routines in Python! +* stackless transform for rpython programs (*any* interpreter) +* infinite recursion, greenlets, co-routines in Python! * composable! JIT-Compiler Generator @@ -68,7 +68,8 @@ Challenges ======================================== -* generate full JIT-Compiler for Python! +* improve the JIT generator until it can generate a + good JIT-Compiler for Python! * release and distribute Python Interpreter From hpk at codespeak.net Wed Mar 25 15:11:00 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 25 Mar 2009 15:11:00 +0100 (CET) Subject: [pypy-svn] r63324 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090325141100.ECD7B16806B@codespeak.net> Author: hpk Date: Wed Mar 25 15:11:00 2009 New Revision: 63324 Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Log: final i guess Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/slides.txt (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/slides.txt Wed Mar 25 15:11:00 2009 @@ -35,7 +35,6 @@ * stackless transform for rpython programs (*any* interpreter) * infinite recursion, greenlets, co-routines in Python! -* composable! JIT-Compiler Generator ==================================== @@ -62,7 +61,7 @@ ======================================== * large automated test suite, good debugging tools -* Generating **efficient* Interpreters +* Generating *efficient* Interpreters * works for Python, a relatively complex language Challenges From fijal at codespeak.net Wed Mar 25 23:33:44 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 25 Mar 2009 23:33:44 +0100 (CET) Subject: [pypy-svn] r63326 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090325223344.AA5811684A3@codespeak.net> Author: fijal Date: Wed Mar 25 23:33:42 2009 New Revision: 63326 Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (contents, props changed) Log: Add (somewhat rough) PyPy sandbox slides Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Wed Mar 25 23:33:42 2009 @@ -0,0 +1,126 @@ +========================== +Python in a sandbox +========================== + +This talk contents +================== + +* How to run sandboxed Python using + PyPy + +* A couple of demos + +* How to define security policies + +* Status, future, Q&A + +What is a sandboxed python? +============================ + +* A way to execute untrusted code separated + from application + +* Separation from each other + +* Eventual integration with existing APIs + +* Example: Google App Engine + +Other solutions +=============================== + +* There is a lot of implementation's out there + in the wild + +* They do subset of: + +* bytecode/source verification + +* CPython source modification/monkey patching + +* platform-level security (GAE) + +* restrict python language to something harmless + (zope's restricted python) + +Problems +=========== + +* Patchy approach - "we fix all places that moight be + potentially dangerous" + +* Tradeoffs - either usability suffer or security is + hard to control + +* "Noone cracked it so far" approach is not + "security by design" + +Our approach +============== + +* Modify all calls to platform (C) into something + harmless. XXX what? + +* Do that in a systematic manner, not touching the interpreter + source + +* Small code base to be trusted + +* Changes to interpreter doesn't break anything + +But there is more... +==================== + +* Memory limit (GC support) + +* CPU time limit + +* XXX ... + +Drawbacks +========== + +* Each sandbox is in a separate process + +* Sandbox doesn't have access directly to any + APIs (only via file descriptor reading/writing) + +How to use it? +=============== + +XXX + +Demo +===== + +XXX + +Embedding in your web app +========================= + +XXX + +Custom file access policies +============================ + +XXX + +Custom APIs +============ + +XXX + +What next? +========== + +* Definitely write more docs, advertise it a bit + more + +* Blog + +* Special web page + +Q&A +=== + +XXX From tismer at codespeak.net Thu Mar 26 02:37:39 2009 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 26 Mar 2009 02:37:39 +0100 (CET) Subject: [pypy-svn] r63330 - pypy/extradoc/sprintinfo/leysin-winter-2009 Message-ID: <20090326013739.896661684AD@codespeak.net> Author: tismer Date: Thu Mar 26 02:37:37 2009 New Revision: 63330 Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Log: added my info. I am an asshole. I don't want to share a room. Modified: pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2009/people.txt Thu Mar 26 02:37:37 2009 @@ -15,12 +15,15 @@ Antonio Cuni 15th-21st Ermina Samuele Pedroni 14th-22nd Ermina Anders Hammarquist 14th-22nd Ermina +Christian Tismer 14th-22nd Ermina ==================== ============== ======================= Samuele and Anders Hammarquist would like to share a two persons room. Antonio would like to share a room with someone, volunteers are welcome :-) +Christian is sorry but he needs a single room. + People on the following list were present at previous sprints: ==================== ============== ===================== From antocuni at codespeak.net Thu Mar 26 10:08:24 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 26 Mar 2009 10:08:24 +0100 (CET) Subject: [pypy-svn] r63335 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090326090824.30E2B168488@codespeak.net> Author: antocuni Date: Thu Mar 26 10:08:22 2009 New Revision: 63335 Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: typo, add an XXX Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Thu Mar 26 10:08:22 2009 @@ -46,7 +46,7 @@ Problems =========== -* Patchy approach - "we fix all places that moight be +* Patchy approach - "we fix all places that might be potentially dangerous" * Tradeoffs - either usability suffer or security is @@ -85,6 +85,9 @@ * Sandbox doesn't have access directly to any APIs (only via file descriptor reading/writing) +XXX: the sentence above is not clear: as it's written it seems you *can* +read/write everything on the disk + How to use it? =============== From hpk at codespeak.net Thu Mar 26 11:15:18 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 26 Mar 2009 11:15:18 +0100 (CET) Subject: [pypy-svn] r63344 - pypy/trunk/pypy Message-ID: <20090326101518.02B2F1684F3@codespeak.net> Author: hpk Date: Thu Mar 26 11:15:18 2009 New Revision: 63344 Modified: pypy/trunk/pypy/conftest.py Log: naming change in pytest Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Thu Mar 26 11:15:18 2009 @@ -43,7 +43,7 @@ default="host", callback=_set_platform, help="set up tests to use specified platform as compile/run target") - def pytest_pyfuncarg_space(self, pyfuncitem): + def pytest_funcarg_space(self, pyfuncitem): return gettestobjspace() ConftestPlugin = PyPyTestPlugin From hpk at codespeak.net Thu Mar 26 13:53:04 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 26 Mar 2009 13:53:04 +0100 (CET) Subject: [pypy-svn] r63362 - pypy/trunk/pypy Message-ID: <20090326125304.A13AD16852E@codespeak.net> Author: hpk Date: Thu Mar 26 13:53:04 2009 New Revision: 63362 Modified: pypy/trunk/pypy/conftest.py Log: py.test now uses djang-like way of having dispatch on function names Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Thu Mar 26 13:53:04 2009 @@ -43,7 +43,7 @@ default="host", callback=_set_platform, help="set up tests to use specified platform as compile/run target") - def pytest_funcarg_space(self, pyfuncitem): + def pytest_funcarg__space(self, pyfuncitem): return gettestobjspace() ConftestPlugin = PyPyTestPlugin From fijal at codespeak.net Thu Mar 26 15:15:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 26 Mar 2009 15:15:52 +0100 (CET) Subject: [pypy-svn] r63366 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090326141552.4C50416852F@codespeak.net> Author: fijal Date: Thu Mar 26 15:15:51 2009 New Revision: 63366 Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: kill XXX Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Thu Mar 26 15:15:51 2009 @@ -82,11 +82,8 @@ * Each sandbox is in a separate process -* Sandbox doesn't have access directly to any - APIs (only via file descriptor reading/writing) - -XXX: the sentence above is not clear: as it's written it seems you *can* -read/write everything on the disk +* Sandbox doesn't have a direct access to any + APIs How to use it? =============== From arigo at codespeak.net Thu Mar 26 15:51:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Mar 2009 15:51:14 +0100 (CET) Subject: [pypy-svn] r63373 - in pypy/trunk: . pypy/lang/prolog/interpreter pypy/lib pypy/module/_stackless/test pypy/rlib pypy/translator/js/examples/console Message-ID: <20090326145114.29AD2168548@codespeak.net> Author: arigo Date: Thu Mar 26 15:51:14 2009 New Revision: 63373 Modified: pypy/trunk/ (props changed) pypy/trunk/pypy/lang/prolog/interpreter/choice.py pypy/trunk/pypy/lib/stackless.py pypy/trunk/pypy/module/_stackless/test/test_greenlet.py pypy/trunk/pypy/rlib/rcoroutine.py pypy/trunk/pypy/translator/js/examples/console/session.py Log: Import greenlets from the new place, /svn/greenlet/trunk. Modified: pypy/trunk/pypy/lang/prolog/interpreter/choice.py ============================================================================== --- pypy/trunk/pypy/lang/prolog/interpreter/choice.py (original) +++ pypy/trunk/pypy/lang/prolog/interpreter/choice.py Thu Mar 26 15:51:14 2009 @@ -1,7 +1,7 @@ import os import py -from py.magic import greenlet +from greenlet import greenlet from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.rstack import yield_current_heap_to_caller from pypy.translator.c.test.test_stackless import StacklessTest Modified: pypy/trunk/pypy/lib/stackless.py ============================================================================== --- pypy/trunk/pypy/lib/stackless.py (original) +++ pypy/trunk/pypy/lib/stackless.py Thu Mar 26 15:51:14 2009 @@ -16,7 +16,7 @@ try: from _stackless import coroutine, greenlet except ImportError: # we are running from CPython - from py.magic import greenlet + from greenlet import greenlet try: from functools import partial except ImportError: # we are not running python 2.5 Modified: pypy/trunk/pypy/module/_stackless/test/test_greenlet.py ============================================================================== --- pypy/trunk/pypy/module/_stackless/test/test_greenlet.py (original) +++ pypy/trunk/pypy/module/_stackless/test/test_greenlet.py Thu Mar 26 15:51:14 2009 @@ -196,7 +196,7 @@ # ____________________________________________________________ # -# The tests from py.magic.greenlet +# The tests from greenlets. # For now, without the ones that involve threads # class AppTest_PyMagicTestGreenlet: Modified: pypy/trunk/pypy/rlib/rcoroutine.py ============================================================================== --- pypy/trunk/pypy/rlib/rcoroutine.py (original) +++ pypy/trunk/pypy/rlib/rcoroutine.py Thu Mar 26 15:51:14 2009 @@ -34,7 +34,7 @@ from pypy.rlib.objectmodel import we_are_translated try: - from py.magic import greenlet + from greenlet import greenlet main_greenlet = greenlet.getcurrent() except (ImportError, ValueError): def greenlet(*args, **kwargs): Modified: pypy/trunk/pypy/translator/js/examples/console/session.py ============================================================================== --- pypy/trunk/pypy/translator/js/examples/console/session.py (original) +++ pypy/trunk/pypy/translator/js/examples/console/session.py Thu Mar 26 15:51:14 2009 @@ -17,7 +17,7 @@ from pygreen.greensock2 import autogreenlet, Timer, Interrupted,\ meetingpoint from pygreen.pipe.fd import FDInput -from py.magic import greenlet +from greenlet import greenlet import time class Killed(Exception): From arigo at codespeak.net Thu Mar 26 15:53:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Mar 2009 15:53:32 +0100 (CET) Subject: [pypy-svn] r63374 - pypy/branch/pyjitpl5-simplify Message-ID: <20090326145332.D31F2168547@codespeak.net> Author: arigo Date: Thu Mar 26 15:53:32 2009 New Revision: 63374 Modified: pypy/branch/pyjitpl5-simplify/ (props changed) Log: Fix the version of the py lib used in this branch. From arigo at codespeak.net Thu Mar 26 16:36:53 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Mar 2009 16:36:53 +0100 (CET) Subject: [pypy-svn] r63375 - pypy/trunk/pypy/doc Message-ID: <20090326153653.B4A10168548@codespeak.net> Author: arigo Date: Thu Mar 26 16:36:52 2009 New Revision: 63375 Modified: pypy/trunk/pypy/doc/project-ideas.txt Log: Update project-ideas.txt. Modified: pypy/trunk/pypy/doc/project-ideas.txt ============================================================================== --- pypy/trunk/pypy/doc/project-ideas.txt (original) +++ pypy/trunk/pypy/doc/project-ideas.txt Thu Mar 26 16:36:52 2009 @@ -17,42 +17,25 @@ -Improve one of the JIT back-ends +JIT back-ends -------------------------------- -- PyPy's Just-In-Time compiler relies on two assembler backends for actual - code generation, one for PowerPC and the other for i386. A good project - would be to give the 386 backend a good refactoring, simplifying it, then - add support for missing features like floating-point arithmetic. Another - idea would be start a new backend for e.g. AMD64 (Intel IA-64) or even a - mobile device. - -- Another idea in a similar vein (but requiring some more interaction with the - rest of the JIT code) would be to use LLVM to re-compile functions that are - executed particularly frequently (LLVM cannot be used for *all* code - generation, since it can only work on a whole function at a time). - +PyPy's Just-In-Time compiler relies on backends for actual code +generation. Right now we are working on the ``pyjitpl5`` branch, which +is not stable. Working on the JIT backends should be soon possible. +Open ideas are to write a backend for AMD64 (Intel IA-64); or .NET or +Java (requires porting the JIT frontend to ootype too, which is not too +hard); or trying to use LLVM-JIT. CTypes ------ -- support ctypes on more backends. Right now ctypes is supported only when - compiling PyPy to C. A nice project would be to support it when compiling - to .NET or the JVM. That's not too hard, the only thing needed is to port a - small module that does the actual invocation of external libraries (a - related project would be to port this module to Jython or IronPython to get - support for ctypes there). - -More Interpreter Features -------------------------- - -- support some of the more recent features of CPython. A nice project would be - to support all of the remaining Python 2.5 language features. - -- another thing to do on our Python interpreter would be to port over the - changes to the standard library (which includes re-writing some of the - C-coded modules in RPython or pure Python) that happened in 2.5 or that we - are still missing in 2.4. +Support ctypes on more backends. Right now ctypes is supported only +when compiling PyPy to C. A nice project would be to support it when +compiling to .NET or the JVM. That's not too hard, the only thing needed +is to port a small module that does the actual invocation of external +libraries (a related project would be to port this module to Jython or +IronPython to get support for ctypes there). .. _distribution: @@ -77,37 +60,18 @@ uses several processes and uses transparent proxies to share object views. -Improving the automated test framework --------------------------------------- - -Every night, various kinds of PyPy tests run automatically on a -variety of different systems. Each set of tests displays its own -result on a different web page; for example, here are the results of -our `unit tests`_, `translation tests and benchmarks`_ and `pypy-c -compliance tests`_. - -.. _`unit tests`: http://wyvern.cs.uni-duesseldorf.de/pypytest/summary.html -.. _`translation tests and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`pypy-c compliance tests`: http://www.strakt.com/~pedronis/pypy-c-test/allworkingmodules/summary.html - -A possible project is to improve our testing infrastructure and build -a service that aggregates and displays the results of all the nightly -tests. - - Various Ideas ------------- - work on and improve the JavaScript backend - improve one of the existing interpreters (e.g. the Prolog, the Scheme or - the JavaScript interpreter or the Smalltalk VM) + the JavaScript interpreter or the Smalltalk VM), or start a new one - revive the logic object space, which tried to bring unification-like features to Python - Or else... ---------- From fijal at codespeak.net Thu Mar 26 17:08:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 26 Mar 2009 17:08:20 +0100 (CET) Subject: [pypy-svn] r63376 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090326160820.3DD6C16854C@codespeak.net> Author: fijal Date: Thu Mar 26 17:08:17 2009 New Revision: 63376 Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: update a tiny bit Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Thu Mar 26 17:08:17 2009 @@ -88,7 +88,11 @@ How to use it? =============== -XXX +* translate pypy with --sandbox (takes a while) + +* run using pypy_interact.py + +* implement your own custom policy Demo ===== @@ -98,7 +102,9 @@ Embedding in your web app ========================= -XXX +* XXX + +* XXX Custom file access policies ============================ From fijal at codespeak.net Thu Mar 26 17:24:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 26 Mar 2009 17:24:14 +0100 (CET) Subject: [pypy-svn] r63377 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090326162414.6254E16854C@codespeak.net> Author: fijal Date: Thu Mar 26 17:24:11 2009 New Revision: 63377 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_dlist.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vlist.py Log: Disable DelayedXxx and skip tests that fail (they're fixed on virtualizable-specnodes branch) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Thu Mar 26 17:24:11 2009 @@ -6,9 +6,9 @@ VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, - DelayedSpecNode, - SpecNodeWithBox, - DelayedFixedListSpecNode, +# DelayedSpecNode, +# SpecNodeWithBox, +# DelayedFixedListSpecNode, VirtualFixedListSpecNode, VirtualizableListSpecNode, ) @@ -63,9 +63,9 @@ self.cls = None self.origfields = r_dict(av_eq, av_hash) self.curfields = r_dict(av_eq, av_hash) - self.cleanfields = r_dict(av_eq, av_hash) - self.dirtyfields = r_dict(av_eq, av_hash) - self.expanded_fields = r_dict(av_eq, av_hash) + #self.cleanfields = r_dict(av_eq, av_hash) + #self.dirtyfields = r_dict(av_eq, av_hash) + #self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables @@ -119,8 +119,8 @@ known_class = self.cls.source else: known_class = other.cls.source - if (other.escaped and not other.virtualized and - not self.expanded_fields): + if (other.escaped and not other.virtualized):# and + #not self.expanded_fields): if self.cls is None: return NotSpecNode() if isinstance(known_class, FixedList): @@ -145,40 +145,40 @@ return VirtualFixedListSpecNode(known_class, fields, other.cursize) return VirtualInstanceSpecNode(known_class, fields) - if not other.virtualized and self.expanded_fields: - fields = [] - lst = self.expanded_fields.keys() - sort_descrs(lst) - for ofs in lst: - specnode = SpecNodeWithBox(self.origfields[ofs].source) - fields.append((ofs, specnode)) - if isinstance(known_class, FixedList): - return DelayedFixedListSpecNode(known_class, fields) - return DelayedSpecNode(known_class, fields) - else: - assert self is other - d = self.origfields.copy() - d.update(other.curfields) - offsets = d.keys() - sort_descrs(offsets) - fields = [] - for ofs in offsets: - if ofs in other.curfields: - node = other.curfields[ofs] - if ofs not in self.origfields: - box = node.source.clonebox() - self.origfields[ofs] = InstanceNode(box, escaped=False) - self.origfields[ofs].cls = node.cls - nodes[box] = self.origfields[ofs] - specnode = self.origfields[ofs].intersect(node, nodes) - else: - # ofs in self.origfields: - node = self.origfields[ofs] - specnode = node.intersect(node, nodes) - fields.append((ofs, specnode)) - if isinstance(known_class, FixedList): - return VirtualizableListSpecNode(known_class, fields) - return VirtualizableSpecNode(known_class, fields) + #if not other.virtualized and self.expanded_fields: + # fields = [] + # lst = self.expanded_fields.keys() + # sort_descrs(lst) + # for ofs in lst: + # specnode = SpecNodeWithBox(self.origfields[ofs].source) + # fields.append((ofs, specnode)) + # if isinstance(known_class, FixedList): + # return DelayedFixedListSpecNode(known_class, fields) + # return DelayedSpecNode(known_class, fields) + assert other.virtualized + assert self is other + d = self.origfields.copy() + d.update(other.curfields) + offsets = d.keys() + sort_descrs(offsets) + fields = [] + for ofs in offsets: + if ofs in other.curfields: + node = other.curfields[ofs] + if ofs not in self.origfields: + box = node.source.clonebox() + self.origfields[ofs] = InstanceNode(box, escaped=False) + self.origfields[ofs].cls = node.cls + nodes[box] = self.origfields[ofs] + specnode = self.origfields[ofs].intersect(node, nodes) + else: + # ofs in self.origfields: + node = self.origfields[ofs] + specnode = node.intersect(node, nodes) + fields.append((ofs, specnode)) + if isinstance(known_class, FixedList): + return VirtualizableListSpecNode(known_class, fields) + return VirtualizableSpecNode(known_class, fields) def __repr__(self): flags = '' @@ -264,8 +264,8 @@ self.dependency_graph.append((instnode, fieldnode)) instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode - if (self.first_escaping_op and instnode.cls): - instnode.expanded_fields[field] = None + #if (self.first_escaping_op and instnode.cls): + # instnode.expanded_fields[field] = None def find_nodes_getarrayitem(self, op): instnode = self.getnode(op.args[0]) @@ -516,32 +516,32 @@ if node.virtualized: self.prepare_rebuild_ops(node, rebuild_ops, memo) - # start of code for dirtyfields support - for node in self.nodes.values(): - for ofs, subnode in node.dirtyfields.items(): - box = node.source - if box not in memo and isinstance(box, Box): - memo[box] = box - #index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME - fieldbox = subnode.source - if fieldbox not in memo and isinstance(fieldbox, Box): - memo[fieldbox] = fieldbox - #fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | - # FLAG_BOXES_FROM_FRAME) - if (node.cls is not None and - isinstance(node.cls.source, FixedList)): - ld = node.cls.source - assert isinstance(ld, FixedList) - ad = ld.arraydescr - op1 = ResOperation(rop.SETARRAYITEM_GC, - [box, ofs, fieldbox], - None, descr=ad) - else: - assert isinstance(ofs, AbstractDescr) - op1 = ResOperation(rop.SETFIELD_GC, [box, fieldbox], - None, descr=ofs) - rebuild_ops.append(op1) - # end of code for dirtyfields support +# # start of code for dirtyfields support +# for node in self.nodes.values(): +# for ofs, subnode in node.dirtyfields.items(): +# box = node.source +# if box not in memo and isinstance(box, Box): +# memo[box] = box +# #index = (rev_boxes[box] << FLAG_SHIFT) | FLAG_BOXES_FROM_FRAME +# fieldbox = subnode.source +# if fieldbox not in memo and isinstance(fieldbox, Box): +# memo[fieldbox] = fieldbox +# #fieldindex = ((rev_boxes[fieldbox] << FLAG_SHIFT) | +# # FLAG_BOXES_FROM_FRAME) +# if (node.cls is not None and +# isinstance(node.cls.source, FixedList)): +# ld = node.cls.source +# assert isinstance(ld, FixedList) +# ad = ld.arraydescr +# op1 = ResOperation(rop.SETARRAYITEM_GC, +# [box, ofs, fieldbox], +# None, descr=ad) +# else: +# assert isinstance(ofs, AbstractDescr) +# op1 = ResOperation(rop.SETFIELD_GC, [box, fieldbox], +# None, descr=ofs) +# rebuild_ops.append(op1) +# # end of code for dirtyfields support op_fail.args = unoptboxes rebuild_ops.append(op_fail) @@ -572,21 +572,24 @@ # is just plain wrong #self.nodes[box] = InstanceNode(box.constbox(), const=True) #return True - if ofs in instnode.cleanfields: - self.nodes[box] = instnode.cleanfields[ofs] - return True - else: - instnode.cleanfields[ofs] = InstanceNode(box) - return False + #if ofs in instnode.cleanfields: + # self.nodes[box] = instnode.cleanfields[ofs] + # return True + #else: + # instnode.cleanfields[ofs] = InstanceNode(box) + # return False + return False def optimize_setfield(self, instnode, ofs, valuenode, valuebox): assert isinstance(ofs, AbstractValue) if instnode.virtual or instnode.virtualized: instnode.curfields[ofs] = valuenode + return True else: assert not valuenode.virtual - instnode.cleanfields[ofs] = self.nodes[valuebox] - instnode.dirtyfields[ofs] = self.nodes[valuebox] + return False + #instnode.cleanfields[ofs] = self.nodes[valuebox] + #instnode.dirtyfields[ofs] = self.nodes[valuebox] # we never perform this operation here, note def optimize_loop(self): @@ -616,7 +619,7 @@ for arg in args: if arg in self.nodes: assert not self.nodes[arg].virtual - self.cleanup_field_caches(newoperations) + #self.cleanup_field_caches(newoperations) op.args = args newoperations.append(op) break @@ -699,8 +702,8 @@ instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[1]] ofs = op.descr - self.optimize_setfield(instnode, ofs, valuenode, op.args[1]) - continue + if self.optimize_setfield(instnode, ofs, valuenode, op.args[1]): + continue elif opnum == rop.SETARRAYITEM_GC: instnode = self.nodes[op.args[0]] if instnode.cls is None: @@ -708,9 +711,9 @@ ofsbox = self.getsource(op.args[1]) if isinstance(ofsbox, ConstInt): valuenode = self.getnode(op.args[2]) - self.optimize_setfield(instnode, ofsbox, valuenode, - op.args[2]) - continue + if self.optimize_setfield(instnode, ofsbox, valuenode, + op.args[2]): + continue elif (opnum == rop.OOISNULL or opnum == rop.OONONNULL): instnode = self.getnode(op.args[0]) @@ -753,12 +756,12 @@ instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue - elif (not op.has_no_side_effect() - and opnum != rop.SETFIELD_GC and - opnum != rop.SETARRAYITEM_GC): + #elif (not op.has_no_side_effect() + # and opnum != rop.SETFIELD_GC and + # opnum != rop.SETARRAYITEM_GC): # the setfield operations do not clean up caches, although # they have side effects - self.cleanup_field_caches(newoperations) + #self.cleanup_field_caches(newoperations) if op.can_raise(): exception_might_have_happened = True box = op.result @@ -771,26 +774,26 @@ self.history.inputargs = newinputargs self.history.operations = newoperations - def cleanup_field_caches(self, newoperations): - # we need to invalidate everything - # XXX looping over self.nodes on each side-effecting operation - # XXX costs too much (quadratic time) - for node in self.nodes.values(): - for ofs, valuenode in node.dirtyfields.items(): - # XXX move to InstanceNode eventually - if (node.cls is not None and - isinstance(node.cls.source, FixedList)): - ld = node.cls.source - assert isinstance(ld, FixedList) - newoperations.append(ResOperation(rop.SETARRAYITEM_GC, - [node.source, ofs, valuenode.source], - None, ld.arraydescr)) - else: - assert isinstance(ofs, AbstractDescr) - newoperations.append(ResOperation(rop.SETFIELD_GC, - [node.source, valuenode.source], None, ofs)) - node.dirtyfields = r_dict(av_eq, av_hash) - node.cleanfields = r_dict(av_eq, av_hash) +# def cleanup_field_caches(self, newoperations): +# # we need to invalidate everything +# # XXX looping over self.nodes on each side-effecting operation +# # XXX costs too much (quadratic time) +# for node in self.nodes.values(): +# for ofs, valuenode in node.dirtyfields.items(): +# # XXX move to InstanceNode eventually +# if (node.cls is not None and +# isinstance(node.cls.source, FixedList)): +# ld = node.cls.source +# assert isinstance(ld, FixedList) +# newoperations.append(ResOperation(rop.SETARRAYITEM_GC, +# [node.source, ofs, valuenode.source], +# None, ld.arraydescr)) +# else: +# assert isinstance(ofs, AbstractDescr) +# newoperations.append(ResOperation(rop.SETFIELD_GC, +# [node.source, valuenode.source], None, ofs)) +# #node.dirtyfields = r_dict(av_eq, av_hash) +# #node.cleanfields = r_dict(av_eq, av_hash) def match_exactly(self, old_loop): assert len(old_loop.specnodes) == len(self.specnodes) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py Thu Mar 26 17:24:11 2009 @@ -34,15 +34,15 @@ # NotSpecNode matches everything return True -class SpecNodeWithBox(NotSpecNode): - # XXX what is this class used for? - def __init__(self, box): - self.box = box +#class SpecNodeWithBox(NotSpecNode): +# # XXX what is this class used for? +# def __init__(self, box): +# self.box = box - def equals(self, other): - if type(other) is SpecNodeWithBox: - return True - return False +# def equals(self, other): +# if type(other) is SpecNodeWithBox: +# return True +# return False class FixedClassSpecNode(SpecNode): def __init__(self, known_class): @@ -152,65 +152,65 @@ instnode.escaped = True SpecNodeWithFields.adapt_to(self, instnode) -class DelayedSpecNode(VirtualizedSpecNode): +# class DelayedSpecNode(VirtualizedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist): - from pypy.jit.metainterp.history import AbstractDescr - newboxlist.append(instnode.source) - for ofs, subspecnode in self.fields: - assert isinstance(subspecnode, SpecNodeWithBox) - if oplist is None: - instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append(instnode.curfields[ofs].source) - else: - if ofs in instnode.cleanfields: - newboxlist.append(instnode.cleanfields[ofs].source) - else: - box = subspecnode.box.clonebox() - assert isinstance(ofs, AbstractDescr) - oplist.append(ResOperation(rop.GETFIELD_GC, - [instnode.source], box, ofs)) - newboxlist.append(box) - -class DelayedFixedListSpecNode(DelayedSpecNode): - - def expand_boxlist(self, instnode, newboxlist, oplist): - from pypy.jit.metainterp.history import ResOperation - from pypy.jit.metainterp.resoperation import rop - from pypy.jit.metainterp.optimize import FixedList +# def expand_boxlist(self, instnode, newboxlist, oplist): +# from pypy.jit.metainterp.history import AbstractDescr +# newboxlist.append(instnode.source) +# for ofs, subspecnode in self.fields: +# assert isinstance(subspecnode, SpecNodeWithBox) +# if oplist is None: +# instnode.cleanfields[ofs] = instnode.origfields[ofs] +# newboxlist.append(instnode.curfields[ofs].source) +# else: +# if ofs in instnode.cleanfields: +# newboxlist.append(instnode.cleanfields[ofs].source) +# else: +# box = subspecnode.box.clonebox() +# assert isinstance(ofs, AbstractDescr) +# oplist.append(ResOperation(rop.GETFIELD_GC, +# [instnode.source], box, ofs)) +# newboxlist.append(box) + +# class DelayedFixedListSpecNode(DelayedSpecNode): + +# def expand_boxlist(self, instnode, newboxlist, oplist): +# from pypy.jit.metainterp.history import ResOperation +# from pypy.jit.metainterp.resoperation import rop +# from pypy.jit.metainterp.optimize import FixedList - newboxlist.append(instnode.source) - cls = self.known_class - assert isinstance(cls, FixedList) - arraydescr = cls.arraydescr - for ofs, subspecnode in self.fields: - assert isinstance(subspecnode, SpecNodeWithBox) - if oplist is None: - instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append(instnode.curfields[ofs].source) - else: - if ofs in instnode.cleanfields: - newboxlist.append(instnode.cleanfields[ofs].source) - else: - box = subspecnode.box.clonebox() - oplist.append(ResOperation(rop.GETARRAYITEM_GC, - [instnode.source, ofs], box, arraydescr)) - newboxlist.append(box) - - def extract_runtime_data(self, cpu, valuebox, resultlist): - from pypy.jit.metainterp.resoperation import rop - from pypy.jit.metainterp.optimize import FixedList - from pypy.jit.metainterp.history import check_descr +# newboxlist.append(instnode.source) +# cls = self.known_class +# assert isinstance(cls, FixedList) +# arraydescr = cls.arraydescr +# for ofs, subspecnode in self.fields: +# assert isinstance(subspecnode, SpecNodeWithBox) +# if oplist is None: +# instnode.cleanfields[ofs] = instnode.origfields[ofs] +# newboxlist.append(instnode.curfields[ofs].source) +# else: +# if ofs in instnode.cleanfields: +# newboxlist.append(instnode.cleanfields[ofs].source) +# else: +# box = subspecnode.box.clonebox() +# oplist.append(ResOperation(rop.GETARRAYITEM_GC, +# [instnode.source, ofs], box, arraydescr)) +# newboxlist.append(box) + +# def extract_runtime_data(self, cpu, valuebox, resultlist): +# from pypy.jit.metainterp.resoperation import rop +# from pypy.jit.metainterp.optimize import FixedList +# from pypy.jit.metainterp.history import check_descr - resultlist.append(valuebox) - cls = self.known_class - assert isinstance(cls, FixedList) - arraydescr = cls.arraydescr - check_descr(arraydescr) - for ofs, subspecnode in self.fields: - fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ofs], arraydescr) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) +# resultlist.append(valuebox) +# cls = self.known_class +# assert isinstance(cls, FixedList) +# arraydescr = cls.arraydescr +# check_descr(arraydescr) +# for ofs, subspecnode in self.fields: +# fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, +# [valuebox, ofs], arraydescr) +# subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualizableSpecNode(VirtualizedSpecNode): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_dlist.py Thu Mar 26 17:24:11 2009 @@ -2,6 +2,7 @@ import py from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin +py.test.skip("Disabled") class ListTests: def test_basic(self): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_list_optimize.py Thu Mar 26 17:24:11 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("Disabled") from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.metainterp.optimize import (PerfectSpecializer, Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Thu Mar 26 17:24:11 2009 @@ -29,6 +29,7 @@ self.check_loop_count(1) def test_loop_with_delayed_setfield(self): + py.test.skip("Disabled") myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res', 'a']) class A(object): def __init__(self): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Thu Mar 26 17:24:11 2009 @@ -574,6 +574,7 @@ ] def test_K0_optimize_loop(): + py.test.skip("Disabled") spec = PerfectSpecializer(Loop(K0.inputargs, K0.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -608,6 +609,7 @@ ] def test_K1_optimize_loop(): + py.test.skip("Disabled") spec = PerfectSpecializer(Loop(K1.inputargs, K1.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -641,6 +643,7 @@ ] def test_K_optimize_loop(): + py.test.skip("Disabled") spec = PerfectSpecializer(Loop(K.inputargs, K.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -672,6 +675,7 @@ ] def test_L_optimize_loop(): + py.test.skip("Disabled") spec = PerfectSpecializer(Loop(L.inputargs, L.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -703,6 +707,7 @@ ] def test_M_optimize_loop(): + py.test.skip("Disabled") spec = PerfectSpecializer(Loop(M.inputargs, M.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -734,6 +739,7 @@ ] def test_N_optimize_loop(): + py.test.skip("Disabled") spec = PerfectSpecializer(Loop(N.inputargs, N.ops)) spec.find_nodes() spec.intersect_input_and_output() Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Thu Mar 26 17:24:11 2009 @@ -10,7 +10,8 @@ VirtualizableSpecNode, VirtualInstanceSpecNode, NotSpecNode, - DelayedSpecNode) + FixedClassSpecNode) +# DelayedSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, equaloplists, Loop, @@ -196,7 +197,7 @@ assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == C.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], DelayedSpecNode) + assert isinstance(spec.specnodes[0].fields[0][1], FixedClassSpecNode) # ____________________________________________________________ Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Thu Mar 26 17:24:11 2009 @@ -423,7 +423,7 @@ res = self.meta_interp(f, [30], listops=True) self.check_loops(setarrayitem_gc=0) - #self.check_loop_count(2) -- this is hard to predict right now: + #self.check_loop_count(2) # -- this is hard to predict right now: # what occurs is that one path through the loop is compiled, # then exits; then later when we compile again we see the other # path of the loop by chance, then exits; then finally we see @@ -439,6 +439,7 @@ assert isinstance(op.args[1], history.BoxInt) def test_virtual_obj_on_always_virtual(self): + py.test.skip("XXX") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) @@ -475,6 +476,7 @@ def test_virtual_obj_on_always_virtual_more_bridges(self): + py.test.skip("XXX") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vlist.py Thu Mar 26 17:24:11 2009 @@ -58,7 +58,7 @@ res = self.meta_interp(f, [10], listops=True) assert res == f(10) # one setitem should be gone by now - self.check_loops(call=1, setarrayitem_gc=1, getarrayitem_gc=1) + self.check_loops(call=1, setarrayitem_gc=2, getarrayitem_gc=1) def test_ll_fixed_setitem_fast(self): jitdriver = JitDriver(greens = [], reds = ['n', 'l']) From arigo at codespeak.net Thu Mar 26 17:41:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Mar 2009 17:41:17 +0100 (CET) Subject: [pypy-svn] r63378 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc Message-ID: <20090326164117.ADA6C168549@codespeak.net> Author: arigo Date: Thu Mar 26 17:41:16 2009 New Revision: 63378 Added: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt (contents, props changed) Log: Checkin the start of a document. Added: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt Thu Mar 26 17:41:16 2009 @@ -0,0 +1,69 @@ +======================================================================== + Loops +======================================================================== + + +Basics +----------------- + +*Loop Tree* = tree of operations. Its root (i.e. start) corresponds to +a ``can_enter_jit`` marker, so it is when an application-level loop was +closed. Its branches end in a JUMP back, corresponding to closing the +application-level loop. The JUMPs themselves may go to the same or to +another loop tree, but for now we assume that all loop trees connected +in this way correspond to the same application-level loop. + +We use Perfect Specialization to find out exactly how specialized each +loop should be. + + +Theory +----------------- + +In theory, Perfect Specialization of a complete tree means the +following: + +* find how much of the input arguments' structure is needed; +* find how much structure the output arguments have; +* do the intersection. + +The input arguments' structure is the most precise structure that works +for all branches. It describes how much information, at most, we would +like to have at the root. + +The output arguments' structure is, similarly, the most precise +structure that correctly describes the output of all branches. It +describes how much information, at most, we can pass to the next +iteration. + +More precisely, we use the following *specnode* classes to represent +the level of specialization:: + + . VirtualSpec(cls, name1=spec1, ...) + | + VirtualizableSpec(cls, name1=spec1, ...) + | + FixedClassSpec(cls) + | + NotSpec + +For (a simplified) example, ``VirtualizableSpec(PyFrame, x = +VirtualSpec(W_IntObject, value = NotSpec))`` describes the virtualizable +frame for a loop in which the only used variable is ``x``, which is a +virtual ``W_IntObject``. + +The intersection rules are: + +* the intersection of two ``VirtualSpec`` of the same ``cls`` is a + further ``VirtualSpec``, and we proceed with the intersection of + each field. + +* the intersection of two ``VirtualizableSpec`` of the same ``cls`` is + like the previous case, except that some names may be omitted + completely from a given ``VirtualizableSpec``; in the case a name is + present in only one of the ``VirtualizableSpec``, we just keep it + unmodified in the intersection. + +* in other cases, the result is ``FixedClassSpec`` if the two specnodes + have the same class, or ``NotSpec`` if any is a ``NotSpec`` or if the + two classes differ. From david at codespeak.net Thu Mar 26 18:16:27 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 26 Mar 2009 18:16:27 +0100 (CET) Subject: [pypy-svn] r63379 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090326171627.5E513168554@codespeak.net> Author: david Date: Thu Mar 26 18:16:25 2009 New Revision: 63379 Added: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/number.py pypy/branch/io-lang/pypy/lang/io/objspace.py pypy/branch/io-lang/pypy/lang/io/register.py pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py pypy/branch/io-lang/pypy/lang/io/test/test_model.py Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.io pypy/branch/io-lang/pypy/lang/io/parserhack.py pypy/branch/io-lang/pypy/lang/io/test/test_parse.py Log: (cfbolz, david) tried to interpret really simple code involving integers Added: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/model.py Thu Mar 26 18:16:25 2009 @@ -0,0 +1,79 @@ +class W_Object(object): + """Base class for all io objects""" + def __init__(self, space, protos = []): + self.slots = {} + self.protos = list(protos) + self.space = space + + def lookup(self, name): + try: + return self.slots[name] + except KeyError: + pass + for x in self.protos: + t = x.lookup(name) + if t is not None: + return t + +class W_Number(W_Object): + """Number""" + def __init__(self, space, value): + self.value = value + W_Object.__init__(self, space, [space.w_number]) + + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not self == other + +class W_List(W_Object): + pass +class W_Sequence(W_Object): + pass + +class W_CFunction(W_Object): + def __init__(self, space, function): + self.function = function + W_Object.__init__(self, space) + + def apply(self, w_receiver, w_message): + return self.function(w_receiver, w_message, None) + +class W_Message(W_Object): + def __init__(self, space, name, arguments, next = None): + self.name = name + self.literal_value = parse_literal(space, name) + self.arguments = arguments + self.next = next + W_Object.__init__(self, space) + + def __repr__(self): + return "Message(%r, %r, %r)" % (self.name, self.arguments, self.next) + + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not self == other + def eval(self, w_receiver): + if self.literal_value is not None: + w_result = self.literal_value + else: + w_method = w_receiver.lookup(self.name) + w_result = w_method.apply(w_receiver, self) + if self.next: + #TODO: optimize + return self.next.eval(w_result) + else: + return w_result + +def parse_literal(space, literal): + for t in [int, float, lambda x: int(x, 16)]: + try: + return W_Number(space, t(literal)) + except ValueError: + pass + Added: pypy/branch/io-lang/pypy/lang/io/number.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/number.py Thu Mar 26 18:16:25 2009 @@ -0,0 +1,11 @@ +from pypy.lang.io.register import register_method +from pypy.lang.io.model import W_Number + at register_method("Number", '+') +def w_number_add(w_target, w_message, w_context): + w_arg = w_message.arguments[0].eval(w_context) + return W_Number(w_target.space, w_target.value + w_arg.value) + + at register_method("Number", '-') +def w_number_minus(w_target, w_message, w_context): + w_arg = w_message.arguments[0].eval(w_context) + return W_Number(w_target.space, w_target.value - w_arg.value) \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/objspace.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/objspace.py Thu Mar 26 18:16:25 2009 @@ -0,0 +1,18 @@ +from pypy.rlib.objectmodel import instantiate +from pypy.lang.io.model import W_Number, W_Object, W_CFunction +import pypy.lang.io.number +from pypy.lang.io.register import cfunction_definitions + +class ObjSpace(object): + """docstring for ObjSpace""" + def __init__(self): + self.w_obj = W_Object(self) + self.w_lobby = W_Object(self) + self.init_w_number() + + def init_w_number(self): + self.w_number = instantiate(W_Number) + W_Object.__init__(self.w_number, self) + self.w_number.value = 0 + for key, function in cfunction_definitions['Number'].items(): + self.w_number.slots[key] = W_CFunction(self, function) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.io ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/parserhack.io (original) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.io Thu Mar 26 18:16:25 2009 @@ -1,22 +1,20 @@ -nil addAst := nil -nil addTail := nil -Message addAst := method( - "Ast(" print - next addAst -) +nil addArguments := nil +nil pythonize := nil + Message pythonize := method( - addAst - "implicit" print - addTail + "W_Message(space," print + addArguments + next pythonize + ")" print + ) -Message addTail := method( - ", \"" print +Message addArguments := method( + "\"" print name print "\"" print ", [" print arguments foreach(i, argument, argument pythonize; ", " print) - "])" print - next addTail + "]," print ) in := File standardInput Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/parserhack.py (original) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.py Thu Mar 26 18:16:25 2009 @@ -1,32 +1,20 @@ import py import os - -implicit = "implicit" +from pypy.lang.io.model import W_Number, parse_literal, W_Message +from pypy.lang.io.objspace import ObjSpace io_file = py.magic.autopath().dirpath().join("parserhack.io") -class Ast(object): - def __init__(self, receiver, name, arguments = None): - self.receiver = receiver - self.name = name - if arguments is None: - arguments = [] - self.arguments = arguments - - def __repr__(self): - return "Ast(%r, %r, %r)" % (self.receiver, self.name, self.arguments) - - def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.__dict__ == other.__dict__) - - def __ne__(self, other): - return not self == other - -def parse(input): +def parse(input, space=None): child_in, child_out_err = os.popen4("osxvm %s" % io_file) child_in.write(input) child_in.close() s = child_out_err.read().strip() + print s return eval(s) + +def interpret(code): + space = ObjSpace() + ast = parse(code, space) + return ast.eval(None) \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/register.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/register.py Thu Mar 26 18:16:25 2009 @@ -0,0 +1,7 @@ +cfunction_definitions = {} +def register_method(type_name, slot_name): + def register(function): + subdict = cfunction_definitions.setdefault(type_name, {}) + subdict[slot_name] = function + return function + return register \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py Thu Mar 26 18:16:25 2009 @@ -0,0 +1,13 @@ +from pypy.lang.io.parserhack import interpret + +def test_even_simpler(): + x = interpret("2") + assert x.value == 2 + +def test_simple(): + x = interpret("2 + 2") + assert x.value == 4 + +def test_simple_minus(): + x = interpret("2 - 2") + assert x.value == 0 \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_model.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_model.py Thu Mar 26 18:16:25 2009 @@ -0,0 +1,26 @@ +from pypy.lang.io.model import parse_literal, W_Number, W_Object +from pypy.lang.io.objspace import ObjSpace + +def test_parse_literal(): + space = ObjSpace() + assert parse_literal(space, "2").value == 2 + assert parse_literal(space, "0xFF").value == 255 + assert parse_literal(space, "2.3").value == 2.3 + +def test_lookup(): + obj = W_Object(None, ) + assert obj.lookup("fail") is None + a = obj.slots['fail'] = W_Object(None) + assert obj.lookup("fail") is a + +def test_lookup2(): + obj1 = W_Object(None) + obj2 = W_Object(None) + a = obj2.slots['foo'] = W_Object(None) + obj1.protos.append(obj2) + assert obj1.lookup("foo") is a + +def test_protos(): + space = ObjSpace() + x = W_Number(space, 2) + assert x.protos == [space.w_number] \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_parse.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_parse.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_parse.py Thu Mar 26 18:16:25 2009 @@ -1,12 +1,16 @@ -from pypy.lang.io.parserhack import parse, implicit, Ast +from pypy.lang.io.model import W_Message +from pypy.lang.io.parserhack import parse +from pypy.lang.io.objspace import ObjSpace def test_simple(): + space = ObjSpace() input = "a b c" - ast = parse(input) - assert ast == Ast(Ast(Ast(implicit, "a"), "b"), "c") + ast = parse(input, space) + assert ast == W_Message(space, "a", [], W_Message(space, "b", [], W_Message(space, "c", [],))) def test_simple_args(): + space = ObjSpace() input = "a + b c" - ast = parse(input) - assert ast == Ast(Ast(implicit, "a"), '+', [Ast(Ast(implicit, 'b'), 'c')]) + ast = parse(input, space) + assert ast == W_Message(space, "a", [], W_Message(space, '+', [W_Message(space, "b", [], W_Message(space, 'c', [],))])) From arigo at codespeak.net Thu Mar 26 18:22:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Mar 2009 18:22:32 +0100 (CET) Subject: [pypy-svn] r63380 - pypy/trunk/pypy/doc Message-ID: <20090326172232.8BB0E168549@codespeak.net> Author: arigo Date: Thu Mar 26 18:22:30 2009 New Revision: 63380 Modified: pypy/trunk/pypy/doc/project-ideas.txt Log: By Intel IA-64 I mean Intel 64. Modified: pypy/trunk/pypy/doc/project-ideas.txt ============================================================================== --- pypy/trunk/pypy/doc/project-ideas.txt (original) +++ pypy/trunk/pypy/doc/project-ideas.txt Thu Mar 26 18:22:30 2009 @@ -23,7 +23,7 @@ PyPy's Just-In-Time compiler relies on backends for actual code generation. Right now we are working on the ``pyjitpl5`` branch, which is not stable. Working on the JIT backends should be soon possible. -Open ideas are to write a backend for AMD64 (Intel IA-64); or .NET or +Open ideas are to write a backend for AMD64 (Intel 64); or .NET or Java (requires porting the JIT frontend to ootype too, which is not too hard); or trying to use LLVM-JIT. From fijal at codespeak.net Thu Mar 26 21:37:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 26 Mar 2009 21:37:00 +0100 (CET) Subject: [pypy-svn] r63381 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090326203700.E3C3D168539@codespeak.net> Author: fijal Date: Thu Mar 26 21:36:58 2009 New Revision: 63381 Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: Fill XXXs Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Thu Mar 26 21:36:58 2009 @@ -94,27 +94,25 @@ * implement your own custom policy -Demo -===== - -XXX +* demo Embedding in your web app ========================= -* XXX - -* XXX +* http://codespeak.net/svn/user/getxsick/django-sandbox/ Custom file access policies ============================ -XXX +* write your own python code to control it Custom APIs ============ -XXX +* provide an API that marshals/pickles data to + an outer layer + +* outer layer that accesses actual platform What next? ========== @@ -126,7 +124,13 @@ * Special web page +* besides that, it's ready to use + Q&A === -XXX +* http://merlinux.eu + +* http://pypy.org + +* We really need a special web page.... From fijal at codespeak.net Fri Mar 27 05:00:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Mar 2009 05:00:11 +0100 (CET) Subject: [pypy-svn] r63383 - pypy/extradoc/talk/pycon2009/vm-summit Message-ID: <20090327040011.C318516852C@codespeak.net> Author: fijal Date: Fri Mar 27 05:00:04 2009 New Revision: 63383 Modified: pypy/extradoc/talk/pycon2009/vm-summit/author.latex pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf Log: parts as it went Modified: pypy/extradoc/talk/pycon2009/vm-summit/author.latex ============================================================================== --- pypy/extradoc/talk/pycon2009/vm-summit/author.latex (original) +++ pypy/extradoc/talk/pycon2009/vm-summit/author.latex Fri Mar 27 05:00:04 2009 @@ -1,7 +1,8 @@ \definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} -\title[PyPy status / mobile perspectives]{PyPy status / mobile perspectives} -\author[H. Krekel]{Holger Krekel \\ http://merlinux.eu} +\title[PyPy VM]{PyPy VM} +\author[H. Krekel, M. Fijalkowski]{Holger Krekel \and Maciej Fijalkowski\\ +Merlinux GmbH} -\institute[OpenBossa 2009, Recife, Brazil]{OpenBossa 2009, Brazil} -\date{March 11, 2009} +\institute[PyCon 2009]{PyCon 2009 - Rosemont} +\date{March 28 2009} Modified: pypy/extradoc/talk/pycon2009/vm-summit/slides.pdf ============================================================================== Binary files. No diff available. From fijal at codespeak.net Fri Mar 27 05:01:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Mar 2009 05:01:09 +0100 (CET) Subject: [pypy-svn] r63384 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090327040109.9EE1416852C@codespeak.net> Author: fijal Date: Fri Mar 27 05:00:59 2009 New Revision: 63384 Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: a bit of update Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Fri Mar 27 05:00:59 2009 @@ -5,13 +5,13 @@ What this talk is about ======================= -* A bit of motivation +* Why we work on PyPy? -* What we can run on top of PyPy +* What you can run on top of PyPy * How fast is PyPy? -* 1.1 release coming +* Details about coming 1.1 release * Questions and Answers @@ -152,7 +152,6 @@ * exact naming of a list comprehension variable * relying on untested and undocumented private stuff - (zipimport._zip_directory_cache) * exact message matching in exception catching code @@ -173,11 +172,9 @@ =============================== * we're something between 0.8-4x slower than - CPython on various benchmarks. + CPython on various benchmarks without JIT -* steady but slow progress - -* we hope for our JIT to be a huge leap ahead +* our JIT is a huge leap ahead * pypy-c has fastest Interpreter startup @@ -193,6 +190,8 @@ * probably won't make it to 1.1 +* completely separated from the interpreter + Memory - comparison with CPython =================================== @@ -209,13 +208,13 @@ Threading / Stackless =================================== -* currently using GIL, quite robust +* currently using GIL * free threading? "it's work" * pypy-c has software threading / stackless -* added during translation +* no modifications to interpreter involved Other backends ============== From hpk at codespeak.net Fri Mar 27 15:07:49 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 27 Mar 2009 15:07:49 +0100 (CET) Subject: [pypy-svn] r63388 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090327140749.4346C168460@codespeak.net> Author: hpk Date: Fri Mar 27 15:07:46 2009 New Revision: 63388 Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: updates, an XXX. Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Fri Mar 27 15:07:46 2009 @@ -5,12 +5,11 @@ This talk contents ================== -* How to run sandboxed Python using - PyPy +* Problems with current sandboxing approaches -* A couple of demos +* PyPy sandboxing and virtualization -* How to define security policies +* A couple of demos * Status, future, Q&A @@ -55,82 +54,107 @@ * "Noone cracked it so far" approach is not "security by design" -Our approach -============== +"fixing all places manually" +================================= + +sidenote: enter the "browser hack" challenge a week ago: + +* **fully security-updated** IE8, Firefox, Safari access an URL + +* hacker answers the URL access + +* within a day above browsers were hacked + +**something is wrong with an approach +that despite so much attention and effort +is so easy to break** + +PyPy's sandboxing +================== -* Modify all calls to platform (C) into something - harmless. XXX what? +automatically transform all C-lib/os calls +in our low-level graph representation +of the interpreter. -* Do that in a systematic manner, not touching the interpreter - source +PyPy virtualized Interpreter +==================================== -* Small code base to be trusted +.. image:: img/sandbox1.png + :scale: 100 + :align: left -* Changes to interpreter doesn't break anything +Places to security-review +============================= -But there is more... +* algos for transforming the graphs +* interaction code controler<->sandbox +* controler process code + +Robustness and freedom! +========================== + +Changes to the interpreter don't break sandbox! + +Additional goodies ==================== * Memory limit (GC support) * CPU time limit -* XXX ... - Drawbacks ========== * Each sandbox is in a separate process -* Sandbox doesn't have a direct access to any - APIs +* Sandbox doesn't have direct access to any APIs -How to use it? -=============== +How to use it today? +======================= * translate pypy with --sandbox (takes a while) * run using pypy_interact.py -* implement your own custom policy - * demo Embedding in your web app ========================= -* http://codespeak.net/svn/user/getxsick/django-sandbox/ +http://codespeak.net/svn/user/getxsick/django-sandbox/ Custom file access policies ============================ -* write your own python code to control it +code your own policy in plain python Custom APIs ============ +XXX why "Custom APIs" in the title? find this slide confusing + * provide an API that marshals/pickles data to an outer layer -* outer layer that accesses actual platform +* controling process accesses actual platform What next? ========== -* Definitely write more docs, advertise it a bit - more +* come up with nice methods of integrating with + App code, try PyPy's transparent proxies? -* Blog +* Improve docs, spawn separate project -* Special web page - -* besides that, it's ready to use +* get funding for teaching and helping + companies to make full use of it. Q&A === -* http://merlinux.eu +Maciej Fijalkowski, Holger Krekel at + +http://merlinux.eu -* http://pypy.org +Project webpage: http://pypy.org -* We really need a special web page.... From david at codespeak.net Fri Mar 27 15:38:56 2009 From: david at codespeak.net (david at codespeak.net) Date: Fri, 27 Mar 2009 15:38:56 +0100 (CET) Subject: [pypy-svn] r63389 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090327143856.E334F168569@codespeak.net> Author: david Date: Fri Mar 27 15:38:54 2009 New Revision: 63389 Added: pypy/branch/io-lang/pypy/lang/io/object.py Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/objspace.py pypy/branch/io-lang/pypy/lang/io/parserhack.io pypy/branch/io-lang/pypy/lang/io/parserhack.py pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py pypy/branch/io-lang/pypy/lang/io/test/test_model.py pypy/branch/io-lang/pypy/lang/io/test/test_parse.py Log: (cfbolz, david) Added setSlot and basic object graph Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Fri Mar 27 15:38:54 2009 @@ -5,6 +5,13 @@ self.protos = list(protos) self.space = space + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not self == other + def lookup(self, name): try: return self.slots[name] @@ -19,19 +26,14 @@ """Number""" def __init__(self, space, value): self.value = value - W_Object.__init__(self, space, [space.w_number]) - - def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.__dict__ == other.__dict__) - - def __ne__(self, other): - return not self == other + W_Object.__init__(self, space, [space.w_number]) class W_List(W_Object): pass -class W_Sequence(W_Object): - pass +class W_ImmutableSequence(W_Object): + def __init__(self, space, string): + self.value = string + class W_CFunction(W_Object): def __init__(self, space, function): @@ -52,12 +54,7 @@ def __repr__(self): return "Message(%r, %r, %r)" % (self.name, self.arguments, self.next) - def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.__dict__ == other.__dict__) - - def __ne__(self, other): - return not self == other + def eval(self, w_receiver): if self.literal_value is not None: w_result = self.literal_value @@ -76,4 +73,7 @@ return W_Number(space, t(literal)) except ValueError: pass + if literal.startswith('"') and literal.endswith('"'): + return W_ImmutableSequence(space, literal[1:-1]) + Added: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/object.py Fri Mar 27 15:38:54 2009 @@ -0,0 +1,12 @@ +from pypy.lang.io.register import register_method +from pypy.lang.io.model import W_ImmutableSequence + + at register_method('Object', 'setSlot') +def w_object_set_slot(w_target, w_message, w_context): + w_name = w_message.arguments[0].eval(w_context) + w_value = w_message.arguments[1].eval(w_context) + assert isinstance(w_name, W_ImmutableSequence) + w_target.slots[w_name.value] = w_value + +# def w_object_get_slot(w_target, w_message, w_context): +# pass \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/objspace.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/objspace.py (original) +++ pypy/branch/io-lang/pypy/lang/io/objspace.py Fri Mar 27 15:38:54 2009 @@ -1,13 +1,25 @@ from pypy.rlib.objectmodel import instantiate from pypy.lang.io.model import W_Number, W_Object, W_CFunction -import pypy.lang.io.number from pypy.lang.io.register import cfunction_definitions +import pypy.lang.io.number +import pypy.lang.io.object + class ObjSpace(object): """docstring for ObjSpace""" def __init__(self): - self.w_obj = W_Object(self) + self.init_w_object() self.w_lobby = W_Object(self) + self.w_protos = W_Object(self) + self.w_core = W_Object(self) + + self.w_core.protos.append(self.w_object) + + self.w_protos.protos.append(self.w_core) + self.w_protos.slots['Core'] = self.w_core + + self.init_w_lobby() + self.init_w_number() def init_w_number(self): @@ -15,4 +27,14 @@ W_Object.__init__(self.w_number, self) self.w_number.value = 0 for key, function in cfunction_definitions['Number'].items(): - self.w_number.slots[key] = W_CFunction(self, function) \ No newline at end of file + self.w_number.slots[key] = W_CFunction(self, function) + + def init_w_lobby(self): + self.w_lobby.protos.append(self.w_protos) + self.w_lobby.slots['Lobby'] = self.w_lobby + self.w_lobby.slots['Protos'] = self.w_protos + + def init_w_object(self): + self.w_object = W_Object(self) + for key, function in cfunction_definitions['Object'].items(): + self.w_object.slots[key] = W_CFunction(self, function) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.io ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/parserhack.io (original) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.io Fri Mar 27 15:38:54 2009 @@ -10,7 +10,7 @@ ) Message addArguments := method( "\"" print - name print + name asMutable escape print "\"" print ", [" print arguments foreach(i, argument, argument pythonize; ", " print) Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/parserhack.py (original) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.py Fri Mar 27 15:38:54 2009 @@ -16,5 +16,5 @@ def interpret(code): space = ObjSpace() ast = parse(code, space) - return ast.eval(None) + return ast.eval(space.w_lobby), space \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py Fri Mar 27 15:38:54 2009 @@ -1,13 +1,17 @@ from pypy.lang.io.parserhack import interpret - +from pypy.lang.io.model import W_Number def test_even_simpler(): - x = interpret("2") + x, _ = interpret("2") assert x.value == 2 def test_simple(): - x = interpret("2 + 2") + x, _ = interpret("2 + 2") assert x.value == 4 def test_simple_minus(): - x = interpret("2 - 2") - assert x.value == 0 \ No newline at end of file + x, _ = interpret("2 - 2") + assert x.value == 0 + +def test_set_slot(): + x, space = interpret("a := 1") + assert space.w_lobby.slots['a'] == W_Number(space, 1) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_model.py Fri Mar 27 15:38:54 2009 @@ -6,6 +6,7 @@ assert parse_literal(space, "2").value == 2 assert parse_literal(space, "0xFF").value == 255 assert parse_literal(space, "2.3").value == 2.3 + assert parse_literal(space, '"a"').value == 'a' def test_lookup(): obj = W_Object(None, ) Modified: pypy/branch/io-lang/pypy/lang/io/test/test_parse.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_parse.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_parse.py Fri Mar 27 15:38:54 2009 @@ -1,4 +1,4 @@ -from pypy.lang.io.model import W_Message +from pypy.lang.io.model import W_Message, W_ImmutableSequence from pypy.lang.io.parserhack import parse from pypy.lang.io.objspace import ObjSpace @@ -14,3 +14,11 @@ ast = parse(input, space) assert ast == W_Message(space, "a", [], W_Message(space, '+', [W_Message(space, "b", [], W_Message(space, 'c', [],))])) +def test_set_slot(): + space = ObjSpace() + input = "a := b" + ast = parse(input, space) + a = W_Message(space, '"a"', []) + a.literal_value = W_ImmutableSequence(space, 'a') + + assert ast == W_Message(space, "setSlot", [a, W_Message(space, 'b', [])], ) \ No newline at end of file From fijal at codespeak.net Fri Mar 27 15:45:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Mar 2009 15:45:39 +0100 (CET) Subject: [pypy-svn] r63390 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090327144539.C222D168568@codespeak.net> Author: fijal Date: Fri Mar 27 15:45:39 2009 New Revision: 63390 Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: Kill the slide. We have no support for that, it's just a wild idea Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Fri Mar 27 15:45:39 2009 @@ -128,16 +128,6 @@ code your own policy in plain python -Custom APIs -============ - -XXX why "Custom APIs" in the title? find this slide confusing - -* provide an API that marshals/pickles data to - an outer layer - -* controling process accesses actual platform - What next? ========== From fijal at codespeak.net Fri Mar 27 15:54:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Mar 2009 15:54:38 +0100 (CET) Subject: [pypy-svn] r63391 - pypy/extradoc/talk/pycon2009/pypy-sandbox Message-ID: <20090327145438.87B1616856C@codespeak.net> Author: fijal Date: Fri Mar 27 15:54:37 2009 New Revision: 63391 Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.pdf (contents, props changed) Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Log: PDF Added: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt (original) +++ pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox.txt Fri Mar 27 15:54:37 2009 @@ -79,9 +79,9 @@ PyPy virtualized Interpreter ==================================== -.. image:: img/sandbox1.png - :scale: 100 - :align: left +.. image:: sandbox1.png + :scale: 50 + :align: center Places to security-review ============================= From david at codespeak.net Fri Mar 27 17:47:50 2009 From: david at codespeak.net (david at codespeak.net) Date: Fri, 27 Mar 2009 17:47:50 +0100 (CET) Subject: [pypy-svn] r63392 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090327164750.2A2BA168561@codespeak.net> Author: david Date: Fri Mar 27 17:47:48 2009 New Revision: 63392 Added: pypy/branch/io-lang/pypy/lang/io/test/test_method.py Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/number.py pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/parserhack.py pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py pypy/branch/io-lang/pypy/lang/io/test/test_model.py Log: (cfbolz, david) implememted basic method calling Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Fri Mar 27 17:47:48 2009 @@ -21,6 +21,9 @@ t = x.lookup(name) if t is not None: return t + + def apply(self, space, w_receiver, w_message, w_context): + return self class W_Number(W_Object): """Number""" @@ -30,6 +33,7 @@ class W_List(W_Object): pass + class W_ImmutableSequence(W_Object): def __init__(self, space, string): self.value = string @@ -40,8 +44,8 @@ self.function = function W_Object.__init__(self, space) - def apply(self, w_receiver, w_message): - return self.function(w_receiver, w_message, None) + def apply(self, space, w_receiver, w_message, w_context): + return self.function(space, w_receiver, w_message, w_context) class W_Message(W_Object): def __init__(self, space, name, arguments, next = None): @@ -55,25 +59,41 @@ return "Message(%r, %r, %r)" % (self.name, self.arguments, self.next) - def eval(self, w_receiver): - if self.literal_value is not None: + def eval(self, space, w_receiver, w_context): + if self.name == ';': + # xxx is this correct? + w_result = w_context + elif self.literal_value is not None: w_result = self.literal_value else: w_method = w_receiver.lookup(self.name) - w_result = w_method.apply(w_receiver, self) + w_result = w_method.apply(space, w_receiver, self, w_context) if self.next: #TODO: optimize - return self.next.eval(w_result) + return self.next.eval(space, w_result, w_context) else: return w_result - + +class W_Block(W_Object): + def __init__(self, space, arguments, body): + self.arguments = arguments + self.body = body + W_Object.__init__(self, space) + + def apply(self, space, w_receiver, w_message, w_context): + assert not self.arguments + return self.body.eval(space, w_receiver, w_context) + + +def parse_hex(string): + if not string.startswith("0x"): + raise ValueError + return int(string, 16) def parse_literal(space, literal): - for t in [int, float, lambda x: int(x, 16)]: + for t in [int, float, parse_hex]: try: return W_Number(space, t(literal)) except ValueError: pass if literal.startswith('"') and literal.endswith('"'): - return W_ImmutableSequence(space, literal[1:-1]) - - + return W_ImmutableSequence(space, literal[1:-1]) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/number.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/number.py (original) +++ pypy/branch/io-lang/pypy/lang/io/number.py Fri Mar 27 17:47:48 2009 @@ -1,11 +1,11 @@ from pypy.lang.io.register import register_method from pypy.lang.io.model import W_Number @register_method("Number", '+') -def w_number_add(w_target, w_message, w_context): - w_arg = w_message.arguments[0].eval(w_context) - return W_Number(w_target.space, w_target.value + w_arg.value) +def w_number_add(space, w_target, w_message, w_context): + w_arg = w_message.arguments[0].eval(space, w_context, w_context) + return W_Number(space, w_target.value + w_arg.value) @register_method("Number", '-') -def w_number_minus(w_target, w_message, w_context): - w_arg = w_message.arguments[0].eval(w_context) - return W_Number(w_target.space, w_target.value - w_arg.value) \ No newline at end of file +def w_number_minus(space, w_target, w_message, w_context): + w_arg = w_message.arguments[0].eval(space, w_context, w_context) + return W_Number(space, w_target.value - w_arg.value) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Fri Mar 27 17:47:48 2009 @@ -1,12 +1,20 @@ from pypy.lang.io.register import register_method -from pypy.lang.io.model import W_ImmutableSequence +from pypy.lang.io.model import W_ImmutableSequence, W_Block @register_method('Object', 'setSlot') -def w_object_set_slot(w_target, w_message, w_context): - w_name = w_message.arguments[0].eval(w_context) - w_value = w_message.arguments[1].eval(w_context) +def w_object_set_slot(space, w_target, w_message, w_context): + w_name = w_message.arguments[0].eval(space, w_context, w_context) + w_value = w_message.arguments[1].eval(space, w_context, w_context) assert isinstance(w_name, W_ImmutableSequence) w_target.slots[w_name.value] = w_value + return w_value + + at register_method('Object', 'method') +def w_object_method(space, w_target, w_message, w_context): + w_body = w_message.arguments[-1] + w_arguments = w_message.arguments[:-1] + names = [x.name for x in w_arguments] + return W_Block(space, names, w_body) # def w_object_get_slot(w_target, w_message, w_context): # pass \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/parserhack.py (original) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.py Fri Mar 27 17:47:48 2009 @@ -16,5 +16,5 @@ def interpret(code): space = ObjSpace() ast = parse(code, space) - return ast.eval(space.w_lobby), space + return ast.eval(space, space.w_lobby, space.w_lobby), space \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_interpreter.py Fri Mar 27 17:47:48 2009 @@ -14,4 +14,7 @@ def test_set_slot(): x, space = interpret("a := 1") - assert space.w_lobby.slots['a'] == W_Number(space, 1) \ No newline at end of file + w_number = W_Number(space, 1) + assert space.w_lobby.slots['a'] == w_number + assert x == w_number + assert space.w_lobby.slots['a'] is x \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_method.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_method.py Fri Mar 27 17:47:48 2009 @@ -0,0 +1,16 @@ +from pypy.lang.io.parserhack import parse, interpret +import py.test +# "W_Message(space,"method", [W_Message(space,"1", [],), ],)" +def test_get_slot(): + input = "a := 1; a" + #import pdb; pdb.set_trace() + res, space = interpret(input) + assert res.value == 1 + +def test_parse_method(): + # py.test.skip() + inp = "a := method(1)\na" + # import pdb; pdb.set_trace() + res,space = interpret(inp) + assert res.value == 1 + Modified: pypy/branch/io-lang/pypy/lang/io/test/test_model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_model.py Fri Mar 27 17:47:48 2009 @@ -7,7 +7,8 @@ assert parse_literal(space, "0xFF").value == 255 assert parse_literal(space, "2.3").value == 2.3 assert parse_literal(space, '"a"').value == 'a' - + assert parse_literal(space, 'a') is None + def test_lookup(): obj = W_Object(None, ) assert obj.lookup("fail") is None @@ -24,4 +25,5 @@ def test_protos(): space = ObjSpace() x = W_Number(space, 2) - assert x.protos == [space.w_number] \ No newline at end of file + assert x.protos == [space.w_number] + \ No newline at end of file From fijal at codespeak.net Fri Mar 27 18:12:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Mar 2009 18:12:04 +0100 (CET) Subject: [pypy-svn] r63393 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090327171204.28C3B16856E@codespeak.net> Author: fijal Date: Fri Mar 27 18:12:01 2009 New Revision: 63393 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py Log: Port changes from virtualizable-specnode branch. First go - MatchEverythingSpecNode that makes virtualizable spec nodes equal (the don't match correctly, so bridges are not working, but at least loop is reused correctly) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Fri Mar 27 18:12:01 2009 @@ -37,6 +37,11 @@ def sort_key(self): return self.ofs + def equals(self, other): + if not isinstance(other, Descr): + return False + return self.sort_key() == other.sort_key() + def __lt__(self, other): raise TypeError("cannot use comparison on Descrs") def __le__(self, other): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Fri Mar 27 18:12:01 2009 @@ -3,15 +3,9 @@ ResOperation, AbstractDescr, Options, AbstractValue, ConstPtr) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, - VirtualInstanceSpecNode, - VirtualizableSpecNode, - NotSpecNode, -# DelayedSpecNode, -# SpecNodeWithBox, -# DelayedFixedListSpecNode, - VirtualFixedListSpecNode, - VirtualizableListSpecNode, - ) + VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, + VirtualFixedListSpecNode, VirtualizableListSpecNode, + MatchEverythingSpecNode) from pypy.jit.metainterp import executor from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import lltype, llmemory @@ -68,6 +62,7 @@ #self.expanded_fields = r_dict(av_eq, av_hash) self.cursize = -1 self.vdesc = None # for virtualizables + self.allfields = None def is_nonzero(self): return self.cls is not None or self.nonzero @@ -75,7 +70,7 @@ def is_zero(self): return self.const and not self.source.getptr_base() - def escape_if_startbox(self, memo): + def escape_if_startbox(self, memo, cpu): if self in memo: return memo[self] = None @@ -83,23 +78,32 @@ self.escaped = True if not self.virtualized: for node in self.curfields.values(): - node.escape_if_startbox(memo) + node.escape_if_startbox(memo, cpu) else: for key, node in self.curfields.items(): if self.vdesc is not None and av_list_in(self.vdesc, key): - node.virtualized = True - if node.cls is None: - node.cls = InstanceNode(FixedClass(), const=True) - node.escape_if_startbox(memo) + node.initialize_virtualizable(cpu) + node.escape_if_startbox(memo, cpu) # we also need to escape fields that are only read, never written, # if they're not marked specifically as ones that does not escape for key, node in self.origfields.items(): if key not in self.curfields: if self.vdesc is not None and av_list_in(self.vdesc, key): - node.virtualized = True - if node.cls is None: - node.cls = InstanceNode(FixedClass(), const=True) - node.escape_if_startbox(memo) + node.initialize_virtualizable(cpu) + node.escape_if_startbox(memo, cpu) + + def initialize_virtualizable(self, cpu): + self.virtualized = True + if self.cls is None or not isinstance(self.cls.source, FixedList): + # XXX this is of course wrong, but let's at least not + # explode + self.allfields = self.origfields.keys() + if self.cls is None: + self.cls = InstanceNode(FixedClass(), const=True) + else: + ad = self.cls.source.arraydescr + lgtbox = cpu.do_arraylen_gc([self.source], ad) + self.allfields = [ConstInt(i) for i in range(lgtbox.getint())] def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) @@ -157,9 +161,7 @@ # return DelayedSpecNode(known_class, fields) assert other.virtualized assert self is other - d = self.origfields.copy() - d.update(other.curfields) - offsets = d.keys() + offsets = self.allfields sort_descrs(offsets) fields = [] for ofs in offsets: @@ -171,10 +173,11 @@ self.origfields[ofs].cls = node.cls nodes[box] = self.origfields[ofs] specnode = self.origfields[ofs].intersect(node, nodes) - else: - # ofs in self.origfields: + elif ofs in self.origfields: node = self.origfields[ofs] specnode = node.intersect(node, nodes) + else: + specnode = MatchEverythingSpecNode() fields.append((ofs, specnode)) if isinstance(known_class, FixedList): return VirtualizableListSpecNode(known_class, fields) @@ -374,6 +377,7 @@ instnode.cls = InstanceNode(op.args[1], const=True) if op.vdesc: instnode.vdesc = op.vdesc.virtuals + instnode.allfields = op.vdesc.fields continue elif op.is_always_pure(): for arg in op.args: @@ -403,7 +407,7 @@ for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): - self.nodes[end_box].escape_if_startbox(memo) + self.nodes[end_box].escape_if_startbox(memo, self.cpu) for i in range(len(end_args)): box = self.history.inputargs[i] other_box = end_args[i] @@ -567,11 +571,9 @@ if ofs in instnode.curfields: return True # this means field comes from a virtualizable but is never - # written. Cool, simply make the result constant - # XXX uh??? making it constant in the resulting assembler - # is just plain wrong - #self.nodes[box] = InstanceNode(box.constbox(), const=True) - #return True + # written. + self.nodes[box] = InstanceNode(box) + return True #if ofs in instnode.cleanfields: # self.nodes[box] = instnode.cleanfields[ofs] # return True Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py Fri Mar 27 18:12:01 2009 @@ -34,6 +34,9 @@ # NotSpecNode matches everything return True +class MatchEverythingSpecNode(SpecNode): + pass + #class SpecNodeWithBox(NotSpecNode): # # XXX what is this class used for? # def __init__(self, box): @@ -89,10 +92,11 @@ FixedClassSpecNode.mutate_nodes(self, instnode) curfields = r_dict(av_eq, av_hash) for ofs, subspecnode in self.fields: - subinstnode = instnode.origfields[ofs] - # should really be there - subspecnode.mutate_nodes(subinstnode) - curfields[ofs] = subinstnode + if not isinstance(subspecnode, MatchEverythingSpecNode): + subinstnode = instnode.origfields[ofs] + # should really be there + subspecnode.mutate_nodes(subinstnode) + curfields[ofs] = subinstnode instnode.curfields = curfields def equals(self, other): @@ -123,22 +127,37 @@ def expand_boxlist(self, instnode, newboxlist, start): for ofs, subspecnode in self.fields: - subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start) + if not isinstance(subspecnode, MatchEverythingSpecNode): + subinstnode = instnode.curfields[ofs] # should really be there + subspecnode.expand_boxlist(subinstnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: from pypy.jit.metainterp.history import AbstractDescr assert isinstance(ofs, AbstractDescr) - fieldbox = executor.execute(cpu, rop.GETFIELD_GC, - [valuebox], ofs) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + if not isinstance(subspecnode, MatchEverythingSpecNode): + fieldbox = executor.execute(cpu, rop.GETFIELD_GC, + [valuebox], ofs) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): for ofs, subspecnode in self.fields: subspecnode.adapt_to(instnode.curfields[ofs]) class VirtualizedSpecNode(SpecNodeWithFields): + + def equals(self, other): + if not self.known_class.equals(other.known_class): + return False + assert len(self.fields) == len(other.fields) + for i in range(len(self.fields)): + if (isinstance(self.fields[i][1], MatchEverythingSpecNode) or + isinstance(other.fields[i][1], MatchEverythingSpecNode)): + continue + assert self.fields[i][0].equals(other.fields[i][0]) + if not self.fields[i][1].equals(other.fields[i][1]): + return False + return True def expand_boxlist(self, instnode, newboxlist, start): newboxlist.append(instnode.source) @@ -217,7 +236,7 @@ def equals(self, other): if not isinstance(other, VirtualizableSpecNode): return False - return SpecNodeWithFields.equals(self, other) + return VirtualizedSpecNode.equals(self, other) def adapt_to(self, instnode): instnode.virtualized = True @@ -228,7 +247,7 @@ def equals(self, other): if not isinstance(other, VirtualizableListSpecNode): return False - return SpecNodeWithFields.equals(self, other) + return VirtualizedSpecNode.equals(self, other) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.resoperation import rop @@ -241,9 +260,10 @@ arraydescr = cls.arraydescr check_descr(arraydescr) for ofs, subspecnode in self.fields: - fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, - [valuebox, ofs], arraydescr) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + if not isinstance(subspecnode, MatchEverythingSpecNode): + fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC, + [valuebox, ofs], arraydescr) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) def adapt_to(self, instnode): instnode.virtualized = True Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Fri Mar 27 18:12:01 2009 @@ -25,13 +25,13 @@ ('parent', rclass.OBJECT), ('vable_base', llmemory.Address), ('vable_rti', VABLERTIPTR), - ('x', lltype.Signed), - ('l', lltype.Ptr(lltype.GcArray(lltype.Signed))), - ('node', lltype.Ptr(NODE)), + ('inst_x', lltype.Signed), + ('inst_l', lltype.Ptr(lltype.GcArray(lltype.Signed))), + ('inst_node', lltype.Ptr(NODE)), hints = {'virtualizable2': True, 'virtuals':()}, adtmeths = {'access': VirtualizableAccessor()}) -XY._adtmeths['access'].initialize(XY, ['x', 'node', 'l']) +XY._adtmeths['access'].initialize(XY, ['inst_x', 'inst_node', 'inst_l']) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True) @@ -66,24 +66,24 @@ # ____________________________________________________________ class A: - ofs_node = runner.CPU.fielddescrof(XY, 'node') - ofs_l = runner.CPU.fielddescrof(XY, 'l') + ofs_node = runner.CPU.fielddescrof(XY, 'inst_node') + ofs_l = runner.CPU.fielddescrof(XY, 'inst_l') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # frame = lltype.malloc(XY) frame.vable_rti = lltype.nullptr(XY.vable_rti.TO) - frame.node = lltype.malloc(NODE) - frame.node.value = 20 + frame.inst_node = lltype.malloc(NODE) + frame.inst_node.value = 20 sum = BoxInt(0) fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) - n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) nextnode = lltype.malloc(NODE) nextnode.value = 19 n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) - v = BoxInt(frame.node.value) + v = BoxInt(frame.inst_node.value) v2 = BoxInt(nextnode.value) - sum2 = BoxInt(0 + frame.node.value) + sum2 = BoxInt(0 + frame.inst_node.value) inputargs = [sum, fr] ops = [ ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu)], @@ -98,7 +98,7 @@ ResOperation('setfield_gc', [fr, n2], None, ofs_node), ResOperation('jump', [sum2, fr], None), ] - ops[1].vdesc = xy_desc + ops[0].vdesc = xy_desc def test_A_find_nodes(): spec = PerfectSpecializer(Loop(A.inputargs, A.ops)) @@ -130,16 +130,16 @@ # ____________________________________________________________ class B: - ofs_node = runner.CPU.fielddescrof(XY, 'node') + ofs_node = runner.CPU.fielddescrof(XY, 'inst_node') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # frame = lltype.malloc(XY) frame.vable_rti = lltype.nullptr(XY.vable_rti.TO) - frame.node = lltype.malloc(NODE) - frame.node.value = 20 + frame.inst_node = lltype.malloc(NODE) + frame.inst_node.value = 20 fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) - n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) v = BoxInt(13) inputargs = [fr] ops = [ @@ -149,7 +149,7 @@ ResOperation('getfield_gc', [n1], v, ofs_value), ResOperation('jump', [fr], None), ] - ops[1].vdesc = xy_desc + ops[0].vdesc = xy_desc def test_B_intersect_input_and_output(): spec = PerfectSpecializer(Loop(B.inputargs, B.ops)) @@ -159,15 +159,15 @@ assert spec.nodes[B.fr].virtualized assert spec.nodes[B.n1].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) - assert len(spec.specnodes[0].fields) == 1 - assert spec.specnodes[0].fields[0][0] == B.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) + assert len(spec.specnodes[0].fields) == 3 + assert spec.specnodes[0].fields[2][0] == B.ofs_node + assert isinstance(spec.specnodes[0].fields[2][1], NotSpecNode) # ____________________________________________________________ class C: locals().update(B.__dict__) - n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) v2 = BoxInt(13) inputargs = [fr] ops = [ @@ -184,7 +184,7 @@ # ResOperation('jump', [fr], None), ] - ops[1].vdesc = xy_desc + ops[0].vdesc = xy_desc def test_C_intersect_input_and_output(): spec = PerfectSpecializer(Loop(C.inputargs, C.ops)) @@ -195,9 +195,9 @@ assert spec.nodes[C.n1].escaped assert spec.nodes[C.n2].escaped assert isinstance(spec.specnodes[0], VirtualizableSpecNode) - assert len(spec.specnodes[0].fields) == 1 - assert spec.specnodes[0].fields[0][0] == C.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], FixedClassSpecNode) + assert len(spec.specnodes[0].fields) == 3 + assert spec.specnodes[0].fields[2][0] == C.ofs_node + assert isinstance(spec.specnodes[0].fields[2][1], FixedClassSpecNode) # ____________________________________________________________ @@ -209,9 +209,9 @@ pass locals().update(A.__dict__) - n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) v2 = BoxInt(13) - l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.inst_node)) inputargs = [fr] ops = [ ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Fri Mar 27 18:12:01 2009 @@ -439,7 +439,7 @@ assert isinstance(op.args[1], history.BoxInt) def test_virtual_obj_on_always_virtual(self): - py.test.skip("XXX") + py.test.skip("XX") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py Fri Mar 27 18:12:01 2009 @@ -12,3 +12,17 @@ "NOT_RPYTHON" self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for name in TOPSTRUCT._hints['virtuals']] + self.fields = self.catch_all_fields(cpu, STRUCTTYPE) + + def catch_all_fields(self, cpu, S): + lst = [] + p = S + while True: + lst.extend(p._names) + if getattr(p, 'super', None) is not None: + p = p.super + else: + break + return [cpu.fielddescrof(S, name) for name in lst if + name.startswith('inst_')] + From hpk at codespeak.net Sat Mar 28 12:45:48 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 28 Mar 2009 12:45:48 +0100 (CET) Subject: [pypy-svn] r63403 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328114548.6CFD01684EC@codespeak.net> Author: hpk Date: Sat Mar 28 12:45:45 2009 New Revision: 63403 Added: pypy/extradoc/talk/pycon2009/status/pypy-multitarget.png (props changed) - copied unchanged from r63384, pypy/extradoc/talk/openbossa2009/pypy-mobile/pypy-multitarget.png Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: merging a bit of openbossa slides, talking about GC/memory more from user perspective. Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Sat Mar 28 12:45:45 2009 @@ -15,6 +15,17 @@ * Questions and Answers + +PyPy - user motivation +======================= + +* use Python rather than C for performance + +* have a more speedy, resource efficient interpreter + +* support more programming paradigms + + PyPy - motivation ================================= @@ -22,21 +33,20 @@ * IronPython, Jython - bound to the specific VM -* Separate language specification from low-level details, - such as GC or platform to run - * Psyco and Stackless Python hard to maintain -PyPy - user motivation -======================= +PyPy: generating Python Interpreter +===================================== + +* **high level Python specification**! -* One should never be forced to write anything in C - for performance reasons (with some exceptions possibly) +* layer GCs, JIT, Stackless atop the spec -* Just-in-time compiler should make number-crunching - and static-enough code fast enough +* **generate interpreters** for targets -* One should never care about low-level details +.. image:: pypy-multitarget.png + :scale: 50 + :align: center Brief history of PyPy ========================== @@ -195,15 +205,14 @@ Memory - comparison with CPython =================================== -* PyPy has pluggable Garbage Collection +* PyPy has smaller Python objects -* gcbench - 0.8 (because of our faster GCs) +* user class instances often 50% of CPython size! -* better handling of unusual patterns +* PyPy has pluggable Garbage Collection -* care needed with communication with C +* gcbench - 0.8 (because of our faster GCs) -* GCs are semi-decent Threading / Stackless =================================== From arigo at codespeak.net Sat Mar 28 14:11:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 14:11:38 +0100 (CET) Subject: [pypy-svn] r63404 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc Message-ID: <20090328131138.DD0A2168534@codespeak.net> Author: arigo Date: Sat Mar 28 14:11:37 2009 New Revision: 63404 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt Log: The overall approach starts to get clearer. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt Sat Mar 28 14:11:37 2009 @@ -8,20 +8,15 @@ *Loop Tree* = tree of operations. Its root (i.e. start) corresponds to a ``can_enter_jit`` marker, so it is when an application-level loop was -closed. Its branches end in a JUMP back, corresponding to closing the -application-level loop. The JUMPs themselves may go to the same or to -another loop tree, but for now we assume that all loop trees connected -in this way correspond to the same application-level loop. +closed. Its branches end in a JUMP going either back to the head of the +same loop tree, or to the head of another one. -We use Perfect Specialization to find out exactly how specialized each -loop should be. +Perfect Specialization +------------------------------- -Theory ------------------ - -In theory, Perfect Specialization of a complete tree means the -following: +In theory, Perfect Specialization of a sequence of operations forming a +loop means the following: * find how much of the input arguments' structure is needed; * find how much structure the output arguments have; @@ -67,3 +62,35 @@ * in other cases, the result is ``FixedClassSpec`` if the two specnodes have the same class, or ``NotSpec`` if any is a ``NotSpec`` or if the two classes differ. + + +Overall Approach +----------------------------- + +Start tracing: + +1. when we interpret normally and see a ``can_enter_jit`` marker often + enough; + +2. or when a guard in the running machine code fails often enough. + +Stop tracing when we encounter the next ``can_enter_jit``. + +Call "the loop" the sequence of instructions from the old +``can_enter_jit`` to the new one. In the case 2 above, this means that +we must insert into the loop all unoptimized operations that go before +the guard failure; this is necessary to see a complete loop. + +Apply Perfect Specialization to the loop. + +Case A: We are seeing a new loop header (i.e. we did not see before this +combination of specnodes at this bytecode position). Compile the new +loop completely, and jump to it. + +Case B: We get the same specnodes as a previously-compiled loop (which +may be the same loop as the one we started with, or not). Compile only +a bridge, going from the guard failure to the new loop head. If we were +in case 1 above, the "guard failure" is actually the start from the +interpreter; so this combination of cases means compile a bridge going +efficiently from the interpreter (with no specialization) to the loop +in machine code (with specialization). From fijal at codespeak.net Sat Mar 28 14:18:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 28 Mar 2009 14:18:14 +0100 (CET) Subject: [pypy-svn] r63405 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328131814.9C1EE168446@codespeak.net> Author: fijal Date: Sat Mar 28 14:18:13 2009 New Revision: 63405 Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: this point does not belong there Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Sat Mar 28 14:18:13 2009 @@ -211,9 +211,6 @@ * PyPy has pluggable Garbage Collection -* gcbench - 0.8 (because of our faster GCs) - - Threading / Stackless =================================== From fijal at codespeak.net Sat Mar 28 14:18:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 28 Mar 2009 14:18:36 +0100 (CET) Subject: [pypy-svn] r63406 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328131836.734BA168446@codespeak.net> Author: fijal Date: Sat Mar 28 14:18:35 2009 New Revision: 63406 Added: pypy/extradoc/talk/pycon2009/status/status.pdf (contents, props changed) Log: a pdf Added: pypy/extradoc/talk/pycon2009/status/status.pdf ============================================================================== Binary file. No diff available. From arigo at codespeak.net Sat Mar 28 14:34:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 14:34:09 +0100 (CET) Subject: [pypy-svn] r63407 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328133409.C2AE7168050@codespeak.net> Author: arigo Date: Sat Mar 28 14:34:08 2009 New Revision: 63407 Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: fix it fix it fix it Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Sat Mar 28 14:34:08 2009 @@ -225,9 +225,9 @@ Other backends ============== -* PyPy-jvm runs! +* PyPy-CLI runs! Still needs a bit more integration with .NET -* more integration between pypy-cli and .NET +* PyPy-JVM runs, little integration so far * general speed improvements From fijal at codespeak.net Sat Mar 28 14:35:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 28 Mar 2009 14:35:43 +0100 (CET) Subject: [pypy-svn] r63408 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328133543.1C42D1683FF@codespeak.net> Author: fijal Date: Sat Mar 28 14:35:42 2009 New Revision: 63408 Modified: pypy/extradoc/talk/pycon2009/status/status.pdf pypy/extradoc/talk/pycon2009/status/status.txt Log: Ommit 32bit info on ctypes, update pdf Modified: pypy/extradoc/talk/pycon2009/status/status.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Sat Mar 28 14:35:42 2009 @@ -91,7 +91,7 @@ * part of google sponsoring -* note: 32bit and a bit slow +* note: a bit slow Sqlite ====== From arigo at codespeak.net Sat Mar 28 14:36:16 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 14:36:16 +0100 (CET) Subject: [pypy-svn] r63409 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328133616.940DF1683FF@codespeak.net> Author: arigo Date: Sat Mar 28 14:36:16 2009 New Revision: 63409 Modified: pypy/extradoc/talk/pycon2009/status/status.txt Log: Detail. Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Sat Mar 28 14:36:16 2009 @@ -263,7 +263,7 @@ - help e.g. by writing ctypes modules -- hopefully next month +- hopefully released next month Contact / Q&A ========================== From arigo at codespeak.net Sat Mar 28 15:11:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 15:11:11 +0100 (CET) Subject: [pypy-svn] r63410 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc Message-ID: <20090328141111.87040168465@codespeak.net> Author: arigo Date: Sat Mar 28 15:11:09 2009 New Revision: 63410 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt Log: Add "we will see later". Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/doc/loop.txt Sat Mar 28 15:11:09 2009 @@ -76,6 +76,13 @@ Stop tracing when we encounter the next ``can_enter_jit``. +Call "the old ``can_enter_jit``" the ``can_enter_jit`` that we started +with in case 1, or the one that is at the start of the existing loop +before the guard failure in case 2. If the old and the new +``can_enter_jit`` are not at the same bytecode position, we are not +seeing a loop at all; this is a corner case for now (let's see later). +We will assume that the bytecode position is the same for the sequel. + Call "the loop" the sequence of instructions from the old ``can_enter_jit`` to the new one. In the case 2 above, this means that we must insert into the loop all unoptimized operations that go before From arigo at codespeak.net Sat Mar 28 16:30:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 16:30:35 +0100 (CET) Subject: [pypy-svn] r63412 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090328153035.3B4301684E5@codespeak.net> Author: arigo Date: Sat Mar 28 16:30:29 2009 New Revision: 63412 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py Log: The next failure. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_send.py Sat Mar 28 16:30:29 2009 @@ -348,6 +348,26 @@ assert res == f(198) self.check_loop_count(3) + def test_two_behaviors(self): + py.test.skip("XXX fix me!!!!!!! problem in optimize.py") + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + class Int: + def __init__(self, value): + self.value = value + cases = [True]*100 + [False, True]*10 + [False]*20 + def f(y): + x = Int(0) + while y > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + y -= 1 + if cases[y]: + x = Int(x.value + 1) + return x.value + res = self.meta_interp(f, [len(cases)]) + assert res == 110 + self.check_loop_count(2) + class TestOOtype(SendTests, OOJitMixin): pass From fijal at codespeak.net Sat Mar 28 19:01:50 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 28 Mar 2009 19:01:50 +0100 (CET) Subject: [pypy-svn] r63413 - pypy/extradoc/talk/pycon2009/status Message-ID: <20090328180150.7F7F61684D2@codespeak.net> Author: fijal Date: Sat Mar 28 19:01:48 2009 New Revision: 63413 Modified: pypy/extradoc/talk/pycon2009/status/status.pdf pypy/extradoc/talk/pycon2009/status/status.txt Log: a slide about stackless Modified: pypy/extradoc/talk/pycon2009/status/status.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon2009/status/status.txt Sat Mar 28 19:01:48 2009 @@ -139,6 +139,15 @@ * http://twistedmatrix.com/ +Stackless +========= + +* We support stackless + +* tasklets, frame pickling, greenlets + +* fully cross-platform + Other software ============== From arigo at codespeak.net Sat Mar 28 19:16:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 19:16:07 +0100 (CET) Subject: [pypy-svn] r63414 - pypy/branch/pyjitpl5-loop Message-ID: <20090328181607.3162D1684D5@codespeak.net> Author: arigo Date: Sat Mar 28 19:16:06 2009 New Revision: 63414 Added: pypy/branch/pyjitpl5-loop/ - copied from r63413, pypy/branch/pyjitpl5-simplify/ Log: Yet Another Branch to experiment with metainterp/doc/loop.txt. From arigo at codespeak.net Sat Mar 28 19:16:57 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 28 Mar 2009 19:16:57 +0100 (CET) Subject: [pypy-svn] r63415 - pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph Message-ID: <20090328181657.518961684E8@codespeak.net> Author: arigo Date: Sat Mar 28 19:16:57 2009 New Revision: 63415 Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py Log: [untested] the extended backend interface. Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/llimpl.py Sat Mar 28 19:16:57 2009 @@ -243,6 +243,14 @@ del _variables[:] return _to_opaque(CompiledLoop()) +def compile_restart(fail_position): + fail_op = _from_opaque(fail_position) + del _variables[:] + c = CompiledLoop() + assert fail_op.is_guard() + fail_op.subloop = c + return _to_opaque(c) + def compile_start_int_var(loop): loop = _from_opaque(loop) assert not loop.operations @@ -320,16 +328,13 @@ op.jump_target = loop_target assert op.opnum == rop.JUMP assert len(op.args) == len(loop_target.inputargs) - if loop_target == loop: - log.info("compiling new loop") - else: - log.info("compiling new bridge") def compile_add_fail(loop, fail_index): loop = _from_opaque(loop) op = loop.operations[-1] assert op.opnum == rop.FAIL op.fail_index = fail_index + return _to_opaque(op) def compile_suboperations(loop): loop = _from_opaque(loop) @@ -926,18 +931,22 @@ COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop")) +OPERATION = lltype.Ptr(lltype.OpaqueType("Operation")) FRAME = lltype.Ptr(lltype.OpaqueType("Frame")) MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast")) _TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO +_TO_OPAQUE[Operation] = OPERATION.TO _TO_OPAQUE[Frame] = FRAME.TO _TO_OPAQUE[MemoCast] = MEMOCAST.TO s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP) +s_Operation = annmodel.SomePtr(OPERATION) s_Frame = annmodel.SomePtr(FRAME) s_MemoCast = annmodel.SomePtr(MEMOCAST) setannotation(compile_start, s_CompiledLoop) +setannotation(compile_restart, s_CompiledLoop) setannotation(compile_start_int_var, annmodel.SomeInteger()) setannotation(compile_start_ptr_var, annmodel.SomeInteger()) setannotation(compile_add, annmodel.s_None) @@ -948,7 +957,7 @@ setannotation(compile_add_int_result, annmodel.SomeInteger()) setannotation(compile_add_ptr_result, annmodel.SomeInteger()) setannotation(compile_add_jump_target, annmodel.s_None) -setannotation(compile_add_fail, annmodel.s_None) +setannotation(compile_add_fail, s_Operation) setannotation(compile_suboperations, s_CompiledLoop) setannotation(new_frame, s_Frame) Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py Sat Mar 28 19:16:57 2009 @@ -75,14 +75,29 @@ self.mixlevelann = annmixlevel self.fielddescrof_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr') - def compile_operations(self, loop): + def compile_loop(self, loop): """In a real assembler backend, this should assemble the given list of operations. Here we just generate a similar CompiledLoop instance. The code here is RPython, whereas the code in llimpl - is not. + is not. Returns the compiled loop instance (a black box passed + back to execute_operations()). """ c = llimpl.compile_start() - loop._compiled_version = c + var2index = self._get_loop_args(c, loop) + self._compile_branch(c, loop.operations, var2index, rop.JUMP) + return c + + def compile_bridge(self, fail_op, bridge): + """Like compile_loop, but produce the bridge operations going from + the guard that precedes the given FAIL operation. It should patch + the conditional jump on this guard to now execute the given bridge. + """ + c = llimpl.compile_restart(fail_op._fail_position) + var2index = self._get_loop_args(c, bridge) + self._compile_branch(c, bridge.operations, var2index, rop.JUMP) + return c + + def _get_loop_args(self, c, loop): var2index = {} for box in loop.inputargs: if isinstance(box, history.BoxInt): @@ -91,9 +106,9 @@ var2index[box] = llimpl.compile_start_ptr_var(c) else: raise Exception("box is: %r" % (box,)) - self._compile_branch(c, loop.operations, var2index) + return var2index - def _compile_branch(self, c, operations, var2index): + def _compile_branch(self, c, operations, var2index, expected_end): for op in operations: llimpl.compile_add(c, op.opnum) if op.descr is not None: @@ -112,7 +127,8 @@ x)) if op.is_guard(): c2 = llimpl.compile_suboperations(c) - self._compile_branch(c2, op.suboperations, var2index.copy()) + self._compile_branch(c2, op.suboperations, var2index.copy(), + rop.FAIL) x = op.result if x is not None: if isinstance(x, history.BoxInt): @@ -124,10 +140,11 @@ x)) op = operations[-1] assert op.is_final() + assert op.opnum == expected_end if op.opnum == rop.JUMP: llimpl.compile_add_jump_target(c, op.jump_target._compiled_version) elif op.opnum == rop.FAIL: - llimpl.compile_add_fail(c, len(self.fail_ops)) + op._fail_position = llimpl.compile_add_fail(c, len(self.fail_ops)) self.fail_ops.append(op) def execute_operations(self, loop, valueboxes): From fijal at codespeak.net Sun Mar 29 21:34:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 29 Mar 2009 21:34:23 +0200 (CEST) Subject: [pypy-svn] r63419 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090329193423.A3087168059@codespeak.net> Author: fijal Date: Sun Mar 29 21:34:20 2009 New Revision: 63419 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Log: Port one more fix from virtualizable-specnodes, less terrible than on the branch Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Sun Mar 29 21:34:20 2009 @@ -137,6 +137,9 @@ # ____________________________________________________________ +def update_loop(loop, spec): + pass + def compile_fresh_bridge(metainterp, old_loops, resumekey): #temp = TreeLoop('temp') #temp.operations = metainterp.history.operations Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Sun Mar 29 21:34:20 2009 @@ -162,6 +162,8 @@ assert other.virtualized assert self is other offsets = self.allfields + if offsets is None: + return None sort_descrs(offsets) fields = [] for ofs in offsets: @@ -217,8 +219,14 @@ perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop): - perfect_specializer.adapt_for_match(old_loop) + # xxx slow, maybe + for node in perfect_specializer.nodes.values(): + if node.startbox: + node.cls = None + assert not node.virtual + ofs = perfect_specializer.adapt_for_match(old_loop) perfect_specializer.optimize_loop() + perfect_specializer.update_loop(ofs, old_loop) return old_loop return None # no loop matches @@ -436,14 +444,13 @@ specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes - def expanded_version_of(self, boxlist, oplist): - # oplist is None means at the start + def expanded_version_of(self, boxlist): newboxlist = [] assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) + specnode.expand_boxlist(self.nodes[box], newboxlist) return newboxlist def prepare_rebuild_ops(self, instnode, rebuild_ops, memo): @@ -572,7 +579,9 @@ return True # this means field comes from a virtualizable but is never # written. - self.nodes[box] = InstanceNode(box) + node = InstanceNode(box) + self.nodes[box] = node + instnode.curfields[ofs] = node return True #if ofs in instnode.cleanfields: # self.nodes[box] = instnode.cleanfields[ofs] @@ -604,20 +613,15 @@ for i in range(len(self.specnodes)): box = self.history.inputargs[i] self.specnodes[i].mutate_nodes(self.nodes[box]) - newinputargs = self.expanded_version_of(self.history.inputargs, - None) + newinputargs = self.expanded_version_of(self.history.inputargs) else: # making a bridge - for node in self.nodes.values(): # xxx slow, maybe - if node.startbox: - node.cls = None - assert not node.virtual newinputargs = None # for op in self.history.operations: opnum = op.opnum if opnum == rop.JUMP: - args = self.expanded_version_of(op.args, newoperations) + args = self.expanded_version_of(op.args) for arg in args: if arg in self.nodes: assert not self.nodes[arg].virtual @@ -821,10 +825,59 @@ jump_op = self.history.operations[-1] assert jump_op.opnum == rop.JUMP self.specnodes = old_loop.specnodes + all_offsets = [] for i in range(len(old_loop.specnodes)): old_specnode = old_loop.specnodes[i] new_instnode = self.getnode(jump_op.args[i]) - old_specnode.adapt_to(new_instnode) + offsets = [] + old_specnode.adapt_to(new_instnode, offsets) + all_offsets.append(offsets) + return all_offsets + + def update_loop(self, offsets, loop): + j = 0 + new_inputargs = [] + new_jumpargs = [] + if loop.operations[-1].jump_target is loop: + patch_jump = True + jumpargs = loop.operations[-1].args + else: + patch_jump = False + jumpargs = [] + prev_ofs = 0 + rebuild_ops = [] + memo = {} + for i in range(len(offsets)): + for specnode, descr, parentnode, rel_ofs, node in offsets[i]: + while parentnode.source != loop.inputargs[j]: + j += 1 + ofs = j + rel_ofs + 1 + new_inputargs.extend(loop.inputargs[prev_ofs:ofs]) + if patch_jump: + new_jumpargs.extend(jumpargs[prev_ofs:ofs]) + prev_ofs = ofs + boxlist = [] + specnode.expand_boxlist(node, boxlist) + new_inputargs.extend(boxlist) + new_jumpargs.extend(boxlist) + box = self.prepare_rebuild_ops(node, rebuild_ops, memo) + if (parentnode.cls and + isinstance(parentnode.cls.source, FixedList)): + rebuild_ops.append(ResOperation(rop.SETARRAYITEM_GC, + [parentnode.source, descr, box], None, + parentnode.cls.source.arraydescr)) + else: + rebuild_ops.append(ResOperation(rop.SETFIELD_GC, + [parentnode.source, box], None, descr)) + new_inputargs.extend(loop.inputargs[prev_ofs:]) + loop.inputargs = new_inputargs + if patch_jump: + new_jumpargs.extend(loop.operations[-1].args[prev_ofs:]) + loop.operations[-1].args = new_jumpargs + for op in loop.operations: + if op.is_guard(): + op.suboperations = (op.suboperations[:-1] + rebuild_ops + + [op.suboperations[-1]]) def get_in_list(dict, boxes_or_consts): result = [] @@ -851,6 +904,7 @@ ## # done ## return [currentvalues[box] for box in guard_op.unoptboxes] +# --------------------------------------------------------------- def partition(array, left, right): last_item = array[right] Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py Sun Mar 29 21:34:20 2009 @@ -3,13 +3,13 @@ class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist): newboxlist.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) - def adapt_to(self, instnode): + def adapt_to(self, instnode, offsets): instnode.escaped = True def mutate_nodes(self, instnode): @@ -21,6 +21,9 @@ def matches(self, other): raise NotImplementedError + def compute_number_of_nodes(self): + raise NotImplementedError + class NotSpecNode(SpecNode): def mutate_nodes(self, instnode): instnode.cursize = -1 @@ -34,8 +37,13 @@ # NotSpecNode matches everything return True + def compute_number_of_nodes(self): + return 1 + class MatchEverythingSpecNode(SpecNode): - pass + + def compute_number_of_nodes(self): + return 0 #class SpecNodeWithBox(NotSpecNode): # # XXX what is this class used for? @@ -71,6 +79,9 @@ return False return instnode.cls.source.equals(self.known_class) + def compute_number_of_nodes(self): + return 1 + ##class FixedListSpecNode(FixedClassSpecNode): ## def equals(self, other): @@ -125,11 +136,11 @@ return False return True - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist): for ofs, subspecnode in self.fields: if not isinstance(subspecnode, MatchEverythingSpecNode): subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist, start) + subspecnode.expand_boxlist(subinstnode, newboxlist) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: @@ -140,9 +151,15 @@ [valuebox], ofs) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, offsets): + for ofs, subspecnode in self.fields: + subspecnode.adapt_to(instnode.curfields[ofs], offsets) + + def compute_number_of_nodes(self): + counter = 0 for ofs, subspecnode in self.fields: - subspecnode.adapt_to(instnode.curfields[ofs]) + counter += subspecnode.compute_number_of_nodes() + return counter class VirtualizedSpecNode(SpecNodeWithFields): @@ -158,18 +175,50 @@ if not self.fields[i][1].equals(other.fields[i][1]): return False return True + + def matches(self, instnode): + for key, value in self.fields: + if not isinstance(value, MatchEverythingSpecNode): + if key not in instnode.curfields: + return False + if value is not None and not value.matches(instnode.curfields[key]): + return False + return True - def expand_boxlist(self, instnode, newboxlist, start): + def expand_boxlist(self, instnode, newboxlist): newboxlist.append(instnode.source) - SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) + SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, offsets_relative_to): instnode.escaped = True - SpecNodeWithFields.adapt_to(self, instnode) + fields = [] + offsets_so_far = 0 + for ofs, subspecnode in self.fields: + if isinstance(subspecnode, MatchEverythingSpecNode): + node = None + if ofs in instnode.curfields: + node = instnode.curfields[ofs] + orignode = instnode.origfields[ofs] + subspecnode = orignode.intersect(node, {}) + elif ofs in instnode.origfields: + node = instnode.origfields[ofs] + subspecnode = node.intersect(node, {}) + orignode = node + if node is not None: + subspecnode.mutate_nodes(orignode) + offsets_relative_to.append((subspecnode, ofs, instnode, + offsets_so_far, orignode)) + else: + subspecnode.adapt_to(instnode.curfields[ofs], + offsets_relative_to) + offsets_so_far += subspecnode.compute_number_of_nodes() + fields.append((ofs, subspecnode)) + + self.fields = fields # class DelayedSpecNode(VirtualizedSpecNode): @@ -238,9 +287,9 @@ return False return VirtualizedSpecNode.equals(self, other) - def adapt_to(self, instnode): + def adapt_to(self, instnode, offsets): instnode.virtualized = True - VirtualizedSpecNode.adapt_to(self, instnode) + VirtualizedSpecNode.adapt_to(self, instnode, offsets) class VirtualizableListSpecNode(VirtualizedSpecNode): @@ -265,15 +314,15 @@ [valuebox, ofs], arraydescr) subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) - def adapt_to(self, instnode): + def adapt_to(self, instnode, offsets): instnode.virtualized = True - VirtualizedSpecNode.adapt_to(self, instnode) + VirtualizedSpecNode.adapt_to(self, instnode, offsets) class VirtualSpecNode(SpecNodeWithFields): - def adapt_to(self, instnode): + def adapt_to(self, instnode, offsets): instnode.virtual = True - SpecNodeWithFields.adapt_to(self, instnode) + SpecNodeWithFields.adapt_to(self, instnode, offsets) def mutate_nodes(self, instnode): SpecNodeWithFields.mutate_nodes(self, instnode) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Sun Mar 29 21:34:20 2009 @@ -423,7 +423,7 @@ res = self.meta_interp(f, [30], listops=True) self.check_loops(setarrayitem_gc=0) - #self.check_loop_count(2) # -- this is hard to predict right now: + self.check_loop_count(2) # -- this is hard to predict right now: # what occurs is that one path through the loop is compiled, # then exits; then later when we compile again we see the other # path of the loop by chance, then exits; then finally we see @@ -439,7 +439,6 @@ assert isinstance(op.args[1], history.BoxInt) def test_virtual_obj_on_always_virtual(self): - py.test.skip("XX") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) From fijal at codespeak.net Sun Mar 29 22:27:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 29 Mar 2009 22:27:11 +0200 (CEST) Subject: [pypy-svn] r63420 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090329202711.EE91216845E@codespeak.net> Author: fijal Date: Sun Mar 29 22:27:08 2009 New Revision: 63420 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Log: pass one more test, branch seems to be merged Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Sun Mar 29 22:27:08 2009 @@ -834,16 +834,33 @@ all_offsets.append(offsets) return all_offsets + def _patch(self, origargs, newargs): + i = 0 + res = [] + for arg in newargs: + if arg is None: + res.append(origargs[i]) + i += 1 + else: + res.append(arg) + return res + + def _patch_loop(self, operations, inpargs, rebuild_ops, loop): + for op in operations: + if op.is_guard(): + if op.suboperations[-1].opnum == rop.FAIL: + op.suboperations = (op.suboperations[:-1] + rebuild_ops + + [op.suboperations[-1]]) + else: + self._patch_loop(op.suboperations, inpargs, rebuild_ops, + loop) + jump = operations[-1] + if jump.opnum == rop.JUMP and jump.jump_target is loop: + jump.args = self._patch(jump.args, inpargs) + def update_loop(self, offsets, loop): j = 0 new_inputargs = [] - new_jumpargs = [] - if loop.operations[-1].jump_target is loop: - patch_jump = True - jumpargs = loop.operations[-1].args - else: - patch_jump = False - jumpargs = [] prev_ofs = 0 rebuild_ops = [] memo = {} @@ -852,14 +869,11 @@ while parentnode.source != loop.inputargs[j]: j += 1 ofs = j + rel_ofs + 1 - new_inputargs.extend(loop.inputargs[prev_ofs:ofs]) - if patch_jump: - new_jumpargs.extend(jumpargs[prev_ofs:ofs]) + new_inputargs.extend([None] * (ofs - prev_ofs)) prev_ofs = ofs boxlist = [] specnode.expand_boxlist(node, boxlist) new_inputargs.extend(boxlist) - new_jumpargs.extend(boxlist) box = self.prepare_rebuild_ops(node, rebuild_ops, memo) if (parentnode.cls and isinstance(parentnode.cls.source, FixedList)): @@ -869,15 +883,9 @@ else: rebuild_ops.append(ResOperation(rop.SETFIELD_GC, [parentnode.source, box], None, descr)) - new_inputargs.extend(loop.inputargs[prev_ofs:]) - loop.inputargs = new_inputargs - if patch_jump: - new_jumpargs.extend(loop.operations[-1].args[prev_ofs:]) - loop.operations[-1].args = new_jumpargs - for op in loop.operations: - if op.is_guard(): - op.suboperations = (op.suboperations[:-1] + rebuild_ops + - [op.suboperations[-1]]) + new_inputargs.extend([None] * (len(loop.inputargs) - prev_ofs)) + loop.inputargs = self._patch(loop.inputargs, new_inputargs) + self._patch_loop(loop.operations, new_inputargs, rebuild_ops, loop) def get_in_list(dict, boxes_or_consts): result = [] Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py Sun Mar 29 22:27:08 2009 @@ -475,7 +475,6 @@ def test_virtual_obj_on_always_virtual_more_bridges(self): - py.test.skip("XXX") jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'], virtualizables = ['frame']) From fijal at codespeak.net Sun Mar 29 22:58:07 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 29 Mar 2009 22:58:07 +0200 (CEST) Subject: [pypy-svn] r63421 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090329205807.E5E1F168464@codespeak.net> Author: fijal Date: Sun Mar 29 22:58:05 2009 New Revision: 63421 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py Log: fix virtualizable for attributes that are constant-folded away (space ie) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/virtualizable.py Sun Mar 29 22:58:05 2009 @@ -24,5 +24,5 @@ else: break return [cpu.fielddescrof(S, name) for name in lst if - name.startswith('inst_')] + name.startswith('inst_') and hasattr(S, name)] From fijal at codespeak.net Sun Mar 29 23:15:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 29 Mar 2009 23:15:08 +0200 (CEST) Subject: [pypy-svn] r63422 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090329211508.A1E1C168457@codespeak.net> Author: fijal Date: Sun Mar 29 23:15:07 2009 New Revision: 63422 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Log: make sure we never modify the default argument Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Sun Mar 29 23:15:07 2009 @@ -649,8 +649,10 @@ resume_info.append((frame.jitcode, frame.pc, const_part, frame.exception_target)) if box is not None: - extraargs = [box] + extraargs - guard_op = self.metainterp.history.record(opnum, extraargs, None) + moreargs = [box] + extraargs + else: + moreargs = [] + guard_op = self.metainterp.history.record(opnum, moreargs, None) op = history.ResOperation(rop.FAIL, liveboxes, None) op.key = ResumeKey(guard_op, resume_info) guard_op.suboperations = [op] From fijal at codespeak.net Sun Mar 29 23:22:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 29 Mar 2009 23:22:52 +0200 (CEST) Subject: [pypy-svn] r63423 - pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph Message-ID: <20090329212252.7BA91168464@codespeak.net> Author: fijal Date: Sun Mar 29 23:22:47 2009 New Revision: 63423 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Log: ignore those. The reason why they appear is that if variables became const at optimize, it lands at the backend. To be fixed Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Sun Mar 29 23:22:47 2009 @@ -162,6 +162,10 @@ elif isinstance(box, history.BoxPtr): value = llimpl.frame_ptr_getvalue(frame, i) box.changevalue_ptr(value) + elif isinstance(box, history.ConstInt): + pass + elif isinstance(box, history.ConstPtr): + pass else: raise Exception("bad box in 'fail': %r" % (box,)) return op From arigo at codespeak.net Mon Mar 30 12:05:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 30 Mar 2009 12:05:30 +0200 (CEST) Subject: [pypy-svn] r63431 - in pypy/branch/pyjitpl5-loop/pypy/jit: backend/llgraph metainterp Message-ID: <20090330100530.4581316841D@codespeak.net> Author: arigo Date: Mon Mar 30 12:05:28 2009 New Revision: 63431 Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py Log: Check this in for now. I am going to look more at the pyjitpl5-simplify branch instead. Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py Mon Mar 30 12:05:28 2009 @@ -98,6 +98,20 @@ return c def _get_loop_args(self, c, loop): + var2index = self._get_loop_args(c, loop) + self._compile_branch(c, loop.operations, var2index, rop.JUMP) + + def compile_bridge(self, fail_op, bridge): + """Like compile_loop, but produce the bridge operations going from + the guard that precedes the given FAIL operation. It should patch + the conditional jump on this guard to now execute the given bridge. + """ + c = llimpl.compile_restart(fail_op._fail_position) + bridge._compiled_version = c + var2index = self._get_loop_args(c, bridge) + self._compile_branch(c, bridge.operations, var2index, rop.JUMP) + + def _get_loop_args(self, c, loop): var2index = {} for box in loop.inputargs: if isinstance(box, history.BoxInt): Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py Mon Mar 30 12:05:28 2009 @@ -113,7 +113,7 @@ loop.operations = history.operations loop.operations[-1].jump_target = loop mark_keys_in_loop(loop, loop.operations) - send_loop_to_backend(metainterp, loop, True) + send_loop_to_backend(metainterp, loop) metainterp.stats.loops.append(loop) old_loops.append(loop) return loop @@ -126,14 +126,11 @@ if op.opnum == rop.FAIL: op.key.loop = loop -def send_loop_to_backend(metainterp, loop, is_loop): - metainterp.cpu.compile_operations(loop) +def send_loop_to_backend(metainterp, loop): + metainterp.cpu.compile_loop(loop) metainterp.stats.compiled_count += 1 if not we_are_translated(): - if is_loop: - log.info("compiling new loop") - else: - log.info("compiling new bridge") + log.info("compiling new loop") # ____________________________________________________________ @@ -153,3 +150,8 @@ mark_keys_in_loop(source_loop, guard_op.suboperations) send_loop_to_backend(metainterp, source_loop, False) return target_loop + +def send_bridge_to_backend(metainterp, bridge): + xxx + if not we_are_translated(): + log.info("compiling new bridge") Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py Mon Mar 30 12:05:28 2009 @@ -338,7 +338,7 @@ # self.inputargs = list of distinct Boxes # self.operations = list of ResOperations # ops of the kind 'guard_xxx' contain a further list of operations, - # which may itself contain 'guard_xxx' and so on, making a tree. + # which must end with a FAIL. def _all_operations(self, omit_fails=False): "NOT_RPYTHON" Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py Mon Mar 30 12:05:28 2009 @@ -209,18 +209,6 @@ perfect_specializer.optimize_loop() return None -def optimize_bridge(options, old_loops, history, cpu=None): - if not options.specialize: # for tests only - return old_loops[0] - - perfect_specializer = PerfectSpecializer(history, options, cpu) - perfect_specializer.find_nodes() - for old_loop in old_loops: - if perfect_specializer.match(old_loop): - perfect_specializer.adapt_for_match(old_loop) - perfect_specializer.optimize_loop() - return old_loop - return None # no loop matches class PerfectSpecializer(object): _allow_automatic_node_creation = False @@ -507,7 +495,7 @@ assert len(op.suboperations) == 1 op_fail = op.suboperations[0] assert op_fail.opnum == rop.FAIL - old_boxes = op.suboperations[0].args + old_boxes = op_fail.args unoptboxes = [] for box in old_boxes: if isinstance(box, Const): @@ -547,8 +535,10 @@ # rebuild_ops.append(op1) # # end of code for dirtyfields support + op_fail = op_fail.clone() op_fail.args = unoptboxes rebuild_ops.append(op_fail) + op = op.clone() op.suboperations = rebuild_ops return op @@ -622,6 +612,7 @@ if arg in self.nodes: assert not self.nodes[arg].virtual #self.cleanup_field_caches(newoperations) + op = op.clone() op.args = args newoperations.append(op) break @@ -746,6 +737,7 @@ self.nodes[box] = instnode continue # default handling of arguments and return value + op = op.clone() op.args = self.new_arguments(op) if op.is_always_pure(): for box in op.args: @@ -806,25 +798,58 @@ return False return True - def match(self, old_loop): - jump_op = self.history.operations[-1] - assert jump_op.opnum == rop.JUMP - assert len(old_loop.specnodes) == len(jump_op.args) - for i in range(len(old_loop.specnodes)): - old_specnode = old_loop.specnodes[i] - new_instnode = self.getnode(jump_op.args[i]) - if not old_specnode.matches(new_instnode): - return False - return True + def _patch(self, origargs, newargs): + i = 0 + res = [] + for arg in newargs: + if arg is None: + res.append(origargs[i]) + i += 1 + else: + res.append(arg) + return res - def adapt_for_match(self, old_loop): - jump_op = self.history.operations[-1] - assert jump_op.opnum == rop.JUMP - self.specnodes = old_loop.specnodes - for i in range(len(old_loop.specnodes)): - old_specnode = old_loop.specnodes[i] - new_instnode = self.getnode(jump_op.args[i]) - old_specnode.adapt_to(new_instnode) + def _patch_loop(self, operations, inpargs, rebuild_ops, loop): + for op in operations: + if op.is_guard(): + if op.suboperations[-1].opnum == rop.FAIL: + op.suboperations = (op.suboperations[:-1] + rebuild_ops + + [op.suboperations[-1]]) + else: + self._patch_loop(op.suboperations, inpargs, rebuild_ops, + loop) + jump = operations[-1] + if jump.opnum == rop.JUMP and jump.jump_target is loop: + jump.args = self._patch(jump.args, inpargs) + + def update_loop(self, offsets, loop): + j = 0 + new_inputargs = [] + prev_ofs = 0 + rebuild_ops = [] + memo = {} + for i in range(len(offsets)): + for specnode, descr, parentnode, rel_ofs, node in offsets[i]: + while parentnode.source != loop.inputargs[j]: + j += 1 + ofs = j + rel_ofs + 1 + new_inputargs.extend([None] * (ofs - prev_ofs)) + prev_ofs = ofs + boxlist = [] + specnode.expand_boxlist(node, boxlist) + new_inputargs.extend(boxlist) + box = self.prepare_rebuild_ops(node, rebuild_ops, memo) + if (parentnode.cls and + isinstance(parentnode.cls.source, FixedList)): + rebuild_ops.append(ResOperation(rop.SETARRAYITEM_GC, + [parentnode.source, descr, box], None, + parentnode.cls.source.arraydescr)) + else: + rebuild_ops.append(ResOperation(rop.SETFIELD_GC, + [parentnode.source, box], None, descr)) + new_inputargs.extend([None] * (len(loop.inputargs) - prev_ofs)) + loop.inputargs = self._patch(loop.inputargs, new_inputargs) + self._patch_loop(loop.operations, new_inputargs, rebuild_ops, loop) def get_in_list(dict, boxes_or_consts): result = [] Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py Mon Mar 30 12:05:28 2009 @@ -32,13 +32,10 @@ self.descr = descr def clone(self): - "NOT_RPYTHON" # for tests only res = ResOperation(self.opnum, self.args, self.result, self.descr) res.jump_target = self.jump_target res.key = self.key res.vdesc = self.vdesc - if self.suboperations is not None: - res.suboperations = [op.clone() for op in self.suboperations] return res def __repr__(self): From igorto at codespeak.net Mon Mar 30 13:04:14 2009 From: igorto at codespeak.net (igorto at codespeak.net) Date: Mon, 30 Mar 2009 13:04:14 +0200 (CEST) Subject: [pypy-svn] r63432 - pypy/dist/pypy/module/gdbm Message-ID: <20090330110414.09217168422@codespeak.net> Author: igorto Date: Mon Mar 30 13:04:13 2009 New Revision: 63432 Added: pypy/dist/pypy/module/gdbm/ pypy/dist/pypy/module/gdbm/gdbm.py Log: create gdbm rffi module Added: pypy/dist/pypy/module/gdbm/gdbm.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/gdbm/gdbm.py Mon Mar 30 13:04:13 2009 @@ -0,0 +1,32 @@ +from pypy.rpython.lltypesystem.lltype import * +from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rpython.lltypesystem.rffi import * +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.rpython.rtyper import RPythonTyper + +import py +import sys + +datum = GcStruct('datum',('dptr',CCHARP), ('dsize', lltype.Signed)) + +class Gdbm: + def __init__(self): + self.eci = ExternalCompilationInfo(includes=['gdbm.h'], libraries=['gdbm']) + self.gdbm_file = CStructPtr( 'GDBM_FILE', ('dummy', INT)) + #self.struct_gdbm = lltype.malloc(self.gdbm_file.TO, flavor='raw') + + def open(self, name, blocksize, read_write, mode): + err_func = lltype.Ptr(lltype.FuncType([], lltype.Void)) + open_gdbm = rffi.llexternal('gdbm_open', [CCHARP, INT, INT, INT, err_func], self.gdbm_file, compilation_info=self.eci) + self.struct_gdbm = open_gdbm(name, blocksize, read_write, mode, 0) + + def fetch(self, dbf, key): + fetch_gdbm = rffi.llexternal('gdbm_fetch', [self.gdbm_file, CCHARP], datum, compilation_info=self.eci) + return fetch_gdbm(dbf, key) + + def close(self): + close_gdbm = rffi.llexternal('gdbm_close', [self.gdbm_file], INT, compilation_info = self.eci) + close_gdbm(self.struct_gdbm) + From igorto at codespeak.net Mon Mar 30 13:07:00 2009 From: igorto at codespeak.net (igorto at codespeak.net) Date: Mon, 30 Mar 2009 13:07:00 +0200 (CEST) Subject: [pypy-svn] r63433 - pypy/dist/pypy/module/gdbm Message-ID: <20090330110700.4950E168422@codespeak.net> Author: igorto Date: Mon Mar 30 13:06:59 2009 New Revision: 63433 Removed: pypy/dist/pypy/module/gdbm/ Log: Oops .. removing from dist From arigo at codespeak.net Mon Mar 30 13:10:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 30 Mar 2009 13:10:31 +0200 (CEST) Subject: [pypy-svn] r63434 - in pypy/branch/pyjitpl5-loop/pypy/jit: backend/llgraph metainterp Message-ID: <20090330111031.F0036168424@codespeak.net> Author: arigo Date: Mon Mar 30 13:10:30 2009 New Revision: 63434 Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py Log: Clean up (broken checkin) Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py Mon Mar 30 13:10:30 2009 @@ -93,20 +93,6 @@ the conditional jump on this guard to now execute the given bridge. """ c = llimpl.compile_restart(fail_op._fail_position) - var2index = self._get_loop_args(c, bridge) - self._compile_branch(c, bridge.operations, var2index, rop.JUMP) - return c - - def _get_loop_args(self, c, loop): - var2index = self._get_loop_args(c, loop) - self._compile_branch(c, loop.operations, var2index, rop.JUMP) - - def compile_bridge(self, fail_op, bridge): - """Like compile_loop, but produce the bridge operations going from - the guard that precedes the given FAIL operation. It should patch - the conditional jump on this guard to now execute the given bridge. - """ - c = llimpl.compile_restart(fail_op._fail_position) bridge._compiled_version = c var2index = self._get_loop_args(c, bridge) self._compile_branch(c, bridge.operations, var2index, rop.JUMP) Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py Mon Mar 30 13:10:30 2009 @@ -798,58 +798,6 @@ return False return True - def _patch(self, origargs, newargs): - i = 0 - res = [] - for arg in newargs: - if arg is None: - res.append(origargs[i]) - i += 1 - else: - res.append(arg) - return res - - def _patch_loop(self, operations, inpargs, rebuild_ops, loop): - for op in operations: - if op.is_guard(): - if op.suboperations[-1].opnum == rop.FAIL: - op.suboperations = (op.suboperations[:-1] + rebuild_ops + - [op.suboperations[-1]]) - else: - self._patch_loop(op.suboperations, inpargs, rebuild_ops, - loop) - jump = operations[-1] - if jump.opnum == rop.JUMP and jump.jump_target is loop: - jump.args = self._patch(jump.args, inpargs) - - def update_loop(self, offsets, loop): - j = 0 - new_inputargs = [] - prev_ofs = 0 - rebuild_ops = [] - memo = {} - for i in range(len(offsets)): - for specnode, descr, parentnode, rel_ofs, node in offsets[i]: - while parentnode.source != loop.inputargs[j]: - j += 1 - ofs = j + rel_ofs + 1 - new_inputargs.extend([None] * (ofs - prev_ofs)) - prev_ofs = ofs - boxlist = [] - specnode.expand_boxlist(node, boxlist) - new_inputargs.extend(boxlist) - box = self.prepare_rebuild_ops(node, rebuild_ops, memo) - if (parentnode.cls and - isinstance(parentnode.cls.source, FixedList)): - rebuild_ops.append(ResOperation(rop.SETARRAYITEM_GC, - [parentnode.source, descr, box], None, - parentnode.cls.source.arraydescr)) - else: - rebuild_ops.append(ResOperation(rop.SETFIELD_GC, - [parentnode.source, box], None, descr)) - new_inputargs.extend([None] * (len(loop.inputargs) - prev_ofs)) - loop.inputargs = self._patch(loop.inputargs, new_inputargs) - self._patch_loop(loop.operations, new_inputargs, rebuild_ops, loop) def get_in_list(dict, boxes_or_consts): result = [] From igorto at codespeak.net Mon Mar 30 13:14:12 2009 From: igorto at codespeak.net (igorto at codespeak.net) Date: Mon, 30 Mar 2009 13:14:12 +0200 (CEST) Subject: [pypy-svn] r63435 - pypy/trunk/pypy/module/gdbm Message-ID: <20090330111412.264B9168424@codespeak.net> Author: igorto Date: Mon Mar 30 13:14:11 2009 New Revision: 63435 Added: pypy/trunk/pypy/module/gdbm/ pypy/trunk/pypy/module/gdbm/gdbm.py Log: now make the right commit, create gdbm rffi module Added: pypy/trunk/pypy/module/gdbm/gdbm.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/gdbm/gdbm.py Mon Mar 30 13:14:11 2009 @@ -0,0 +1,32 @@ +from pypy.rpython.lltypesystem.lltype import * +from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rpython.lltypesystem.rffi import * +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.rpython.rtyper import RPythonTyper + +import py +import sys + +datum = GcStruct('datum',('dptr',CCHARP), ('dsize', lltype.Signed)) + +class Gdbm: + def __init__(self): + self.eci = ExternalCompilationInfo(includes=['gdbm.h'], libraries=['gdbm']) + self.gdbm_file = CStructPtr( 'GDBM_FILE', ('dummy', INT)) + #self.struct_gdbm = lltype.malloc(self.gdbm_file.TO, flavor='raw') + + def open(self, name, blocksize, read_write, mode): + err_func = lltype.Ptr(lltype.FuncType([], lltype.Void)) + open_gdbm = rffi.llexternal('gdbm_open', [CCHARP, INT, INT, INT, err_func], self.gdbm_file, compilation_info=self.eci) + self.struct_gdbm = open_gdbm(name, blocksize, read_write, mode, 0) + + def fetch(self, dbf, key): + fetch_gdbm = rffi.llexternal('gdbm_fetch', [self.gdbm_file, CCHARP], datum, compilation_info=self.eci) + return fetch_gdbm(dbf, key) + + def close(self): + close_gdbm = rffi.llexternal('gdbm_close', [self.gdbm_file], INT, compilation_info = self.eci) + close_gdbm(self.struct_gdbm) + From afa at codespeak.net Mon Mar 30 15:07:33 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 30 Mar 2009 15:07:33 +0200 (CEST) Subject: [pypy-svn] r63436 - pypy/trunk/pypy/module/pyexpat Message-ID: <20090330130733.73A97168426@codespeak.net> Author: afa Date: Mon Mar 30 15:07:32 2009 New Revision: 63436 Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Log: Allow context=None when calling ExternalEntityParserCreate. Modified: pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py ============================================================================== --- pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py (original) +++ pypy/trunk/pypy/module/pyexpat/interp_pyexpat.py Mon Mar 30 15:07:32 2009 @@ -454,10 +454,15 @@ XML_SetBase(self.itself, base) SetBase.unwrap_spec = ['self', ObjSpace, str] - def ExternalEntityParserCreate(self, space, context, w_encoding=None): + def ExternalEntityParserCreate(self, space, w_context, w_encoding=None): """ExternalEntityParserCreate(context[, encoding]) Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler.""" + if space.is_w(w_context, space.w_None): + context = None + else: + context = space.str_w(w_context) + if space.is_w(w_encoding, space.w_None): encoding = None else: @@ -477,7 +482,7 @@ parser.handlers[i] = self.handlers[i] return space.wrap(parser) - ExternalEntityParserCreate.unwrap_spec = ['self', ObjSpace, str, W_Root] + ExternalEntityParserCreate.unwrap_spec = ['self', ObjSpace, W_Root, W_Root] def flush_character_buffer(self, space): if not self.buffer_w: From fijal at codespeak.net Mon Mar 30 15:55:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 30 Mar 2009 15:55:35 +0200 (CEST) Subject: [pypy-svn] r63437 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090330135535.04A86168440@codespeak.net> Author: fijal Date: Mon Mar 30 15:55:32 2009 New Revision: 63437 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Log: (pedronis, fijal) * Skipped test to decide what to do * Reset the counter when tracing didn't succeed on a guard failure Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Mar 30 15:55:32 2009 @@ -839,7 +839,11 @@ self.interpret() assert False, "should always raise" except GenerateMergePoint, gmp: - target_loop = self.compile_bridge(key, gmp.argboxes) + try: + target_loop = self.compile_bridge(key, gmp.argboxes) + except self.ContinueRunningNormally: + guard_failure.key.counter = 0 + raise return self.designate_target_loop(gmp, target_loop) def designate_target_loop(self, gmp, loop): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Mon Mar 30 15:55:32 2009 @@ -431,3 +431,39 @@ assert main_interpreter_loop(5) == 5 * 10 * 3 res = self.meta_interp(main_interpreter_loop, [5]) assert res == 5 * 10 * 3 + + def test_outer_and_inner_loop(self): + py.test.skip("fix me") + jitdriver = JitDriver(greens = ['p', 'code'], reds = ['i', 'j', + 'total']) + + codes = [[], [0, 0, 1, 1]] + + def interpret(num): + code = codes[num] + p = 0 + i = 0 + j = 0 + total = 0 + while p < len(code): + jitdriver.jit_merge_point(code=code, p=p, i=i, j=j, total=total) + total += i + e = code[p] + if e == 0: + p += 1 + elif e == 1: + if i < p * 20: + p = 3 - p + i += 1 + jitdriver.can_enter_jit(code=code, p=p, j=j, i=i, + total=total) + else: + j += 1 + i = j + p += 1 + return total + + res = self.meta_interp(interpret, [1]) + assert res == interpret(1) + # XXX it's unsure how many loops should be there + self.check_loop_count(3) From fijal at codespeak.net Mon Mar 30 20:17:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 30 Mar 2009 20:17:10 +0200 (CEST) Subject: [pypy-svn] r63441 - pypy/trunk/pypy/module/gdbm Message-ID: <20090330181710.8F2B81684AA@codespeak.net> Author: fijal Date: Mon Mar 30 20:17:09 2009 New Revision: 63441 Removed: pypy/trunk/pypy/module/gdbm/ Log: This module: a) contains tabs b) contains no tests c) is not a mixed module besides, it doesn't work, but I don't care that much since it has no chance of doing so without all of the above From cfbolz at codespeak.net Tue Mar 31 11:26:34 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 31 Mar 2009 11:26:34 +0200 (CEST) Subject: [pypy-svn] r63443 - in pypy/extradoc/talk/icooolps2009: . code Message-ID: <20090331092634.B6D43168480@codespeak.net> Author: cfbolz Date: Tue Mar 31 11:26:33 2009 New Revision: 63443 Added: pypy/extradoc/talk/icooolps2009/ pypy/extradoc/talk/icooolps2009/Makefile pypy/extradoc/talk/icooolps2009/acm_proc_article-sp.cls pypy/extradoc/talk/icooolps2009/code/ pypy/extradoc/talk/icooolps2009/code/full.txt (contents, props changed) pypy/extradoc/talk/icooolps2009/code/no-green-folding.txt (contents, props changed) pypy/extradoc/talk/icooolps2009/code/normal-tracing.txt (contents, props changed) pypy/extradoc/talk/icooolps2009/code/tlr-paper-full.py (contents, props changed) pypy/extradoc/talk/icooolps2009/code/tlr-paper.py (contents, props changed) pypy/extradoc/talk/icooolps2009/paper.bib pypy/extradoc/talk/icooolps2009/paper.tex Log: A draft for a paper about the tracing JIT that I will maybe submit to ICOOOLPS. Added: pypy/extradoc/talk/icooolps2009/Makefile ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/Makefile Tue Mar 31 11:26:33 2009 @@ -0,0 +1,10 @@ + +pypy-jit.pdf: paper.tex paper.bib + pdflatex paper + bibtex paper + pdflatex paper + pdflatex paper + mv paper.pdf pypy-jit.pdf + +view: pypy-jit.pdf + evince pypy-jit.pdf & Added: pypy/extradoc/talk/icooolps2009/acm_proc_article-sp.cls ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/acm_proc_article-sp.cls Tue Mar 31 11:26:33 2009 @@ -0,0 +1,1391 @@ +% ACM_PROC_ARTICLE-SP.CLS - VERSION 2.7SP +% COMPATIBLE WITH THE "ACM_PROC_ARTICLE.CLS" V2.5 +% Gerald Murray October 15th., 2004 +% +% ---- Start of 'updates' ---- +% +% Allowance made to switch default fonts between those systems using +% METAFONT and those using 'Type 1' or 'Truetype' fonts. +% See LINE NUMBER 266 for details. +% Also provided for enumerated/annotated Corollaries 'surrounded' by +% enumerated Theorems (line 838). +% Gerry November 11th. 1999 +% +% Made the Permission Statement / Conference Info / Copyright Info +% 'user definable' in the source .tex file OR automatic if +% not specified. +% This 'sp' version does NOT produce the permission block. +% +% Major change in January 2000 was to include a "blank line" in between +% new paragraphs. This involved major changes to the, then, acmproc-sp.cls 1.0SP +% file, precipitating a 'new' name: "acm_proc_article-sp.cls" V2.01SP. +% +% Georgia fixed bug in sub-sub-section numbering in paragraphs (July 29th. 2002) +% JS/GM fix to vertical spacing before Proofs (July 30th. 2002) +% +% Footnotes inside table cells using \minipage (Oct. 2002) +% +% ---- End of 'updates' ---- +% +\def\fileversion{V2.7SP} % for ACM's tracking purposes +\def\filedate{October 15, 2004} % Gerry Murray's tracking data +\def\docdate {Friday 15th. October 2004} % Gerry Murray (with deltas to doc} +\usepackage{epsfig} +\usepackage{amssymb} +\usepackage{amsmath} +\usepackage{amsfonts} +% +% ACM_PROC_ARTICLE-SP DOCUMENT STYLE +% G.K.M. Tobin August-October 1999 +% adapted from ARTICLE document style by Ken Traub, Olin Shivers +% also using elements of esub2acm.cls +% LATEST REVISION V2.7SP - OCTOBER 2004 +% ARTICLE DOCUMENT STYLE -- Released 16 March 1988 +% for LaTeX version 2.09 +% Copyright (C) 1988 by Leslie Lamport +% +% +%%% ACM_PROC_ARTICLE-SP is a document style for producing two-column camera-ready pages for +%%% ACM conferences, according to ACM specifications. The main features of +%%% this style are: +%%% +%%% 1) Two columns. +%%% 2) Side and top margins of 4.5pc, bottom margin of 6pc, column gutter of +%%% 2pc, hence columns are 20pc wide and 55.5pc tall. (6pc =3D 1in, approx) +%%% 3) First page has title information, and an extra 6pc of space at the +%%% bottom of the first column for the ACM copyright notice. +%%% 4) Text is 9pt on 10pt baselines; titles (except main) are 9pt bold. +%%% +%%% +%%% There are a few restrictions you must observe: +%%% +%%% 1) You cannot change the font size; ACM wants you to use 9pt. +%%% 3) You must start your paper with the \maketitle command. Prior to the +%%% \maketitle you must have \title and \author commands. If you have a +%%% \date command it will be ignored; no date appears on the paper, since +%%% the proceedings will have a date on the front cover. +%%% 4) Marginal paragraphs, tables of contents, lists of figures and tables, +%%% and page headings are all forbidden. +%%% 5) The `figure' environment will produce a figure one column wide; if you +%%% want one that is two columns wide, use `figure*'. +%%% +% +%%% Copyright Space: +%%% This style automatically leaves 1" blank space at the bottom of page 1/ +%%% column 1. This space can optionally be filled with some text using the +%%% \toappear{...} command. If used, this command must be BEFORE the \maketitle +%%% command. If this command is defined AND [preprint] is on, then the +%%% space is filled with the {...} text (at the bottom); otherwise, it is +%%% blank. If you use \toappearbox{...} instead of \toappear{...} then a +%%% box will be drawn around the text (if [preprint] is on). +%%% +%%% A typical usage looks like this: +%%% \toappear{To appear in the Ninth AES Conference on Medievil Lithuanian +%%% Embalming Technique, June 1991, Alfaretta, Georgia.} +%%% This will be included in the preprint, and left out of the conference +%%% version. +%%% +%%% WARNING: +%%% Some dvi-ps converters heuristically allow chars to drift from their +%%% true positions a few pixels. This may be noticeable with the 9pt sans-serif +%%% bold font used for section headers. +%%% You may turn this hackery off via the -e option: +%%% dvips -e 0 foo.dvi >foo.ps +%%% +\typeout{Document Class 'acm_proc_article-sp' <15th. October '04>. Modified by G.K.M. Tobin} +\typeout{Based in part upon document Style `acmconf' <22 May 89>. Hacked 4/91 by} +\typeout{shivers at cs.cmu.edu, 4/93 by theobald at cs.mcgill.ca} +\typeout{Excerpts were taken from (Journal Style) 'esub2acm.cls'.} +\typeout{****** Bugs/comments/suggestions to Gerry Murray -- murray at hq.acm.org ******} + +\oddsidemargin 4.5pc +\evensidemargin 4.5pc +\advance\oddsidemargin by -1in % Correct for LaTeX gratuitousness +\advance\evensidemargin by -1in % Correct for LaTeX gratuitousness +\marginparwidth 0pt % Margin pars are not allowed. +\marginparsep 11pt % Horizontal space between outer margin and + % marginal note + + % Top of page: +\topmargin 4.5pc % Nominal distance from top of page to top of + % box containing running head. +\advance\topmargin by -1in % Correct for LaTeX gratuitousness +\headheight 0pt % Height of box containing running head. +\headsep 0pt % Space between running head and text. + % Bottom of page: +\footskip 30pt % Distance from baseline of box containing foot + % to baseline of last line of text. +\@ifundefined{footheight}{\newdimen\footheight}{}% this is for LaTeX2e +\footheight 12pt % Height of box containing running foot. + + +%% Must redefine the top margin so there's room for headers and +%% page numbers if you are using the preprint option. Footers +%% are OK as is. Olin. +\advance\topmargin by -37pt % Leave 37pt above text for headers +\headheight 12pt % Height of box containing running head. +\headsep 25pt % Space between running head and text. + +\textheight 666pt % 9 1/4 column height +\textwidth 42pc % Width of text line. + % For two-column mode: +\columnsep 2pc % Space between columns +\columnseprule 0pt % Width of rule between columns. +\hfuzz 1pt % Allow some variation in column width, otherwise it's + % too hard to typeset in narrow columns. + +\footnotesep 5.6pt % Height of strut placed at the beginning of every + % footnote =3D height of normal \footnotesize strut, + % so no extra space between footnotes. + +\skip\footins 8.1pt plus 4pt minus 2pt % Space between last line of text and + % top of first footnote. +\floatsep 11pt plus 2pt minus 2pt % Space between adjacent floats moved + % to top or bottom of text page. +\textfloatsep 18pt plus 2pt minus 4pt % Space between main text and floats + % at top or bottom of page. +\intextsep 11pt plus 2pt minus 2pt % Space between in-text figures and + % text. +\@ifundefined{@maxsep}{\newdimen\@maxsep}{}% this is for LaTeX2e +\@maxsep 18pt % The maximum of \floatsep, + % \textfloatsep and \intextsep (minus + % the stretch and shrink). +\dblfloatsep 11pt plus 2pt minus 2pt % Same as \floatsep for double-column + % figures in two-column mode. +\dbltextfloatsep 18pt plus 2pt minus 4pt% \textfloatsep for double-column + % floats. +\@ifundefined{@dblmaxsep}{\newdimen\@dblmaxsep}{}% this is for LaTeX2e +\@dblmaxsep 18pt % The maximum of \dblfloatsep and + % \dbltexfloatsep. +\@fptop 0pt plus 1fil % Stretch at top of float page/column. (Must be + % 0pt plus ...) +\@fpsep 8pt plus 2fil % Space between floats on float page/column. +\@fpbot 0pt plus 1fil % Stretch at bottom of float page/column. (Must be + % 0pt plus ... ) +\@dblfptop 0pt plus 1fil % Stretch at top of float page. (Must be 0pt plus ...) +\@dblfpsep 8pt plus 2fil % Space between floats on float page. +\@dblfpbot 0pt plus 1fil % Stretch at bottom of float page. (Must be + % 0pt plus ... ) +\marginparpush 5pt % Minimum vertical separation between two marginal + % notes. + +\parskip 0pt % Extra vertical space between paragraphs. + % Set to 0pt outside sections, to keep section heads + % uniformly spaced. The value of parskip is set + % to leading value _within_ sections. + % 12 Jan 2000 gkmt +\parindent 0pt % Width of paragraph indentation. +\partopsep 2pt plus 1pt minus 1pt% Extra vertical space, in addition to + % \parskip and \topsep, added when user + % leaves blank line before environment. + +\@lowpenalty 51 % Produced by \nopagebreak[1] or \nolinebreak[1] +\@medpenalty 151 % Produced by \nopagebreak[2] or \nolinebreak[2] +\@highpenalty 301 % Produced by \nopagebreak[3] or \nolinebreak[3] + +\@beginparpenalty -\@lowpenalty % Before a list or paragraph environment. +\@endparpenalty -\@lowpenalty % After a list or paragraph environment. +\@itempenalty -\@lowpenalty % Between list items. + +\@namedef{ds at 10pt}{\@latexerr{The `10pt' option is not allowed in the `acmconf' + document style.}\@eha} +\@namedef{ds at 11pt}{\@latexerr{The `11pt' option is not allowed in the `acmconf' + document style.}\@eha} +\@namedef{ds at 12pt}{\@latexerr{The `12pt' option is not allowed in the `acmconf' + document style.}\@eha} + +\@options + +\lineskip 2pt % \lineskip is 1pt for all font sizes. +\normallineskip 2pt +\def\baselinestretch{1} + +\abovedisplayskip 9pt plus2pt minus4.5pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus3pt% +\belowdisplayshortskip 5.4pt plus3pt minus3pt% +\let\@listi\@listI % Setting of \@listi added 9 Jun 87 + +\def\small{\@setsize\small{9pt}\viiipt\@viiipt +\abovedisplayskip 7.6pt plus 3pt minus 4pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus2pt% +\belowdisplayshortskip 3.6pt plus2pt minus 2pt +\def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 +\topsep 4pt plus 2pt minus 2pt\parsep 2pt plus 1pt minus 1pt +\itemsep \parsep}} + +\def\footnotesize{\@setsize\footnotesize{9pt}\ixpt\@ixpt +\abovedisplayskip 6.4pt plus 2pt minus 4pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus 1pt% +\belowdisplayshortskip 2.7pt plus 1pt minus 2pt +\def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 +\topsep 3pt plus 1pt minus 1pt\parsep 2pt plus 1pt minus 1pt +\itemsep \parsep}} + +\newcount\aucount +\newcount\originalaucount +\newdimen\auwidth +\auwidth=\textwidth +\newdimen\auskip +\newcount\auskipcount +\newdimen\auskip +\global\auskip=1pc +\newdimen\allauboxes +\allauboxes=\auwidth +\newtoks\addauthors +\newcount\addauflag +\global\addauflag=0 %Haven't shown additional authors yet + +\newtoks\subtitletext +\gdef\subtitle#1{\subtitletext={#1}} + +\gdef\additionalauthors#1{\addauthors={#1}} + +\gdef\numberofauthors#1{\global\aucount=#1 +\ifnum\aucount>3\global\originalaucount=\aucount \global\aucount=3\fi %g} +\global\auskipcount=\aucount\global\advance\auskipcount by 1 +\global\multiply\auskipcount by 2 +\global\multiply\auskip by \auskipcount +\global\advance\auwidth by -\auskip +\global\divide\auwidth by \aucount} + +% \and was modified to count the number of authors. GKMT 12 Aug 1999 +\def\alignauthor{% % \begin{tabular} +\end{tabular}% + \begin{tabular}[t]{p{\auwidth}}\centering}% + +% *** NOTE *** NOTE *** NOTE *** NOTE *** +% If you have 'font problems' then you may need +% to change these, e.g. 'arialb' instead of "arialbd". +% Gerry Murray 11/11/1999 +% *** OR ** comment out block A and activate block B or vice versa. +% ********************************************** +% +% -- Start of block A -- (Type 1 or Truetype fonts) +%\newfont{\secfnt}{timesbd at 12pt} % was timenrb originally - now is timesbd +%\newfont{\secit}{timesbi at 12pt} %13 Jan 00 gkmt +%\newfont{\subsecfnt}{timesi at 11pt} % was timenrri originally - now is timesi +%\newfont{\subsecit}{timesbi at 11pt} % 13 Jan 00 gkmt -- was times changed to timesbi gm 2/4/2000 +% % because "normal" is italic, "italic" is Roman +%\newfont{\ttlfnt}{arialbd at 18pt} % was arialb originally - now is arialbd +%\newfont{\ttlit}{arialbi at 18pt} % 13 Jan 00 gkmt +%\newfont{\subttlfnt}{arial at 14pt} % was arialr originally - now is arial +%\newfont{\subttlit}{ariali at 14pt} % 13 Jan 00 gkmt +%\newfont{\subttlbf}{arialbd at 14pt} % 13 Jan 00 gkmt +%\newfont{\aufnt}{arial at 12pt} % was arialr originally - now is arial +%\newfont{\auit}{ariali at 12pt} % 13 Jan 00 gkmt +%\newfont{\affaddr}{arial at 10pt} % was arialr originally - now is arial +%\newfont{\affaddrit}{ariali at 10pt} %13 Jan 00 gkmt +%\newfont{\eaddfnt}{arial at 12pt} % was arialr originally - now is arial +%\newfont{\ixpt}{times at 9pt} % was timenrr originally - now is times +%\newfont{\confname}{timesi at 8pt} % was timenrri - now is timesi +%\newfont{\crnotice}{times at 8pt} % was timenrr originally - now is times +%\newfont{\ninept}{times at 9pt} % was timenrr originally - now is times + +% ********************************************* +% -- End of block A -- +% +% +% -- Start of block B -- METAFONT +% +++++++++++++++++++++++++++++++++++++++++++++ +% Next (default) block for those using Metafont +% Gerry Murray 11/11/1999 +% *** THIS BLOCK FOR THOSE USING METAFONT ***** +% ********************************************* +\newfont{\secfnt}{ptmb at 12pt} +\newfont{\secit}{ptmbi at 12pt} %13 Jan 00 gkmt +\newfont{\subsecfnt}{ptmri at 11pt} +\newfont{\subsecit}{ptmbi at 11pt} % 13 Jan 00 gkmt -- was ptmr changed to ptmbi gm 2/4/2000 + % because "normal" is italic, "italic" is Roman +\newfont{\ttlfnt}{phvb at 18pt} +\newfont{\ttlit}{phvbo at 18pt} % GM 2/4/2000 +\newfont{\subttlfnt}{phvr at 14pt} +\newfont{\subttlit}{phvro at 14pt} % GM 2/4/2000 +\newfont{\subttlbf}{phvb at 14pt} % 13 Jan 00 gkmt +\newfont{\aufnt}{phvr at 12pt} +\newfont{\auit}{phvro at 12pt} % GM 2/4/2000 +\newfont{\affaddr}{phvr at 10pt} +\newfont{\affaddrit}{phvro at 10pt} % GM 2/4/2000 +\newfont{\eaddfnt}{phvr at 12pt} +\newfont{\ixpt}{ptmr at 9pt} +\newfont{\confname}{ptmri at 8pt} +\newfont{\crnotice}{ptmr at 8pt} +\newfont{\ninept}{ptmr at 9pt} +% +++++++++++++++++++++++++++++++++++++++++++++ +% -- End of block B -- + +\def\email#1{{{\eaddfnt{\vskip 4pt#1}}}} + +\def\addauthorsection{\ifnum\originalaucount>3 + \section{Additional Authors}\the\addauthors + \fi} + +\newcount\savesection +\newcount\sectioncntr +\global\sectioncntr=1 + +\setcounter{secnumdepth}{3} + +\def\appendix{\par +\section*{APPENDIX} +\setcounter{section}{0} + \setcounter{subsection}{0} + \def\thesection{\Alph{section}} } + + +\leftmargini 22.5pt +\leftmarginii 19.8pt % > \labelsep + width of '(m)' +\leftmarginiii 16.8pt % > \labelsep + width of 'vii.' +\leftmarginiv 15.3pt % > \labelsep + width of 'M.' +\leftmarginv 9pt +\leftmarginvi 9pt + +\leftmargin\leftmargini +\labelsep 4.5pt +\labelwidth\leftmargini\advance\labelwidth-\labelsep + +\def\@listI{\leftmargin\leftmargini \parsep 3.6pt plus 2pt minus 1pt% +\topsep 7.2pt plus 2pt minus 4pt% +\itemsep 3.6pt plus 2pt minus 1pt} + +\let\@listi\@listI +\@listi + +\def\@listii{\leftmargin\leftmarginii + \labelwidth\leftmarginii\advance\labelwidth-\labelsep + \topsep 3.6pt plus 2pt minus 1pt + \parsep 1.8pt plus 0.9pt minus 0.9pt + \itemsep \parsep} + +\def\@listiii{\leftmargin\leftmarginiii + \labelwidth\leftmarginiii\advance\labelwidth-\labelsep + \topsep 1.8pt plus 0.9pt minus 0.9pt + \parsep \z@ \partopsep 1pt plus 0pt minus 1pt + \itemsep \topsep} + +\def\@listiv{\leftmargin\leftmarginiv + \labelwidth\leftmarginiv\advance\labelwidth-\labelsep} + +\def\@listv{\leftmargin\leftmarginv + \labelwidth\leftmarginv\advance\labelwidth-\labelsep} + +\def\@listvi{\leftmargin\leftmarginvi + \labelwidth\leftmarginvi\advance\labelwidth-\labelsep} + +\def\labelenumi{\theenumi.} +\def\theenumi{\arabic{enumi}} + +\def\labelenumii{(\theenumii)} +\def\theenumii{\alph{enumii}} +\def\p at enumii{\theenumi} + +\def\labelenumiii{\theenumiii.} +\def\theenumiii{\roman{enumiii}} +\def\p at enumiii{\theenumi(\theenumii)} + +\def\labelenumiv{\theenumiv.} +\def\theenumiv{\Alph{enumiv}} +\def\p at enumiv{\p at enumiii\theenumiii} + +\def\labelitemi{$\bullet$} +\def\labelitemii{\bf --} +\def\labelitemiii{$\ast$} +\def\labelitemiv{$\cdot$} + +\def\verse{\let\\=\@centercr + \list{}{\itemsep\z@ \itemindent -1.5em\listparindent \itemindent + \rightmargin\leftmargin\advance\leftmargin 1.5em}\item[]} +\let\endverse\endlist + +\def\quotation{\list{}{\listparindent 1.5em + \itemindent\listparindent + \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]} +\let\endquotation=\endlist + +\def\quote{\list{}{\rightmargin\leftmargin}\item[]} +\let\endquote=\endlist + +\def\descriptionlabel#1{\hspace\labelsep \bf #1} +\def\description{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + +\let\enddescription\endlist + +\def\theequation{\arabic{equation}} + +\arraycolsep 4.5pt % Half the space between columns in an array environment. +\tabcolsep 5.4pt % Half the space between columns in a tabular environment. +\arrayrulewidth .4pt % Width of rules in array and tabular environment. +\doublerulesep 1.8pt % Space between adjacent rules in array or tabular env. + +\tabbingsep \labelsep % Space used by the \' command. (See LaTeX manual.) + +\skip\@mpfootins =\skip\footins + +\fboxsep =2.7pt % Space left between box and text by \fbox and \framebox. +\fboxrule =.4pt % Width of rules in box made by \fbox and \framebox. + +\def\thepart{\Roman{part}} % Roman numeral part numbers. +\def\thesection {\arabic{section}} +\def\thesubsection {\thesection.\arabic{subsection}} +%\def\thesubsubsection {\thesubsection.\arabic{subsubsection}} % GM 7/30/2002 +%\def\theparagraph {\thesubsubsection.\arabic{paragraph}} % GM 7/30/2002 +\def\thesubparagraph {\theparagraph.\arabic{subparagraph}} + +\def\@pnumwidth{1.55em} +\def\@tocrmarg {2.55em} +\def\@dotsep{4.5} +\setcounter{tocdepth}{3} + +\def\tableofcontents{\@latexerr{\tableofcontents: Tables of contents are not + allowed in the `acmconf' document style.}\@eha} + +\def\l at part#1#2{\addpenalty{\@secpenalty} + \addvspace{2.25em plus 1pt} % space above part line + \begingroup + \@tempdima 3em % width of box holding part number, used by + \parindent \z@ \rightskip \@pnumwidth %% \numberline + \parfillskip -\@pnumwidth + {\large \bf % set line in \large boldface + \leavevmode % TeX command to enter horizontal mode. + #1\hfil \hbox to\@pnumwidth{\hss #2}}\par + \nobreak % Never break after part entry + \endgroup} + +\def\l at section#1#2{\addpenalty{\@secpenalty} % good place for page break + \addvspace{1.0em plus 1pt} % space above toc entry + \@tempdima 1.5em % width of box holding section number + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \bf % Boldface. + \leavevmode % TeX command to enter horizontal mode. + \advance\leftskip\@tempdima %% added 5 Feb 88 to conform to + \hskip -\leftskip %% 25 Jan 88 change to \numberline + #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par + \endgroup} + + +\def\l at subsection{\@dottedtocline{2}{1.5em}{2.3em}} +\def\l at subsubsection{\@dottedtocline{3}{3.8em}{3.2em}} +\def\l at paragraph{\@dottedtocline{4}{7.0em}{4.1em}} +\def\l at subparagraph{\@dottedtocline{5}{10em}{5em}} + +\def\listoffigures{\@latexerr{\listoffigures: Lists of figures are not + allowed in the `acmconf' document style.}\@eha} + +\def\l at figure{\@dottedtocline{1}{1.5em}{2.3em}} + +\def\listoftables{\@latexerr{\listoftables: Lists of tables are not + allowed in the `acmconf' document style.}\@eha} +\let\l at table\l at figure + +\def\footnoterule{\kern-3\p@ + \hrule width .4\columnwidth + \kern 2.6\p@} % The \hrule has default height of .4pt . +% ------ +\long\def\@makefntext#1{\noindent +%\hbox to .5em{\hss$^{\@thefnmark}$}#1} % original +\hbox to .5em{\hss\textsuperscript{\@thefnmark}}#1} % C. Clifton / GM Oct. 2nd. 2002 +% ------- + +\long\def\@maketntext#1{\noindent +#1} + +\long\def\@maketitlenotetext#1#2{\noindent + \hbox to 1.8em{\hss$^{#1}$}#2} + +\setcounter{topnumber}{2} +\def\topfraction{.7} +\setcounter{bottomnumber}{1} +\def\bottomfraction{.3} +\setcounter{totalnumber}{3} +\def\textfraction{.2} +\def\floatpagefraction{.5} +\setcounter{dbltopnumber}{2} +\def\dbltopfraction{.7} +\def\dblfloatpagefraction{.5} + +\long\def\@makecaption#1#2{ + \vskip \baselineskip + \setbox\@tempboxa\hbox{\textbf{#1: #2}} + \ifdim \wd\@tempboxa >\hsize % IF longer than one line: + \textbf{#1: #2}\par % THEN set as ordinary paragraph. + \else % ELSE center. + \hbox to\hsize{\hfil\box\@tempboxa\hfil}\par + \fi} + +\@ifundefined{figure}{\newcounter {figure}} % this is for LaTeX2e + +\def\fps at figure{tbp} +\def\ftype at figure{1} +\def\ext at figure{lof} +\def\fnum at figure{Figure \thefigure} +\def\figure{\@float{figure}} +\let\endfigure\end at float +\@namedef{figure*}{\@dblfloat{figure}} +\@namedef{endfigure*}{\end at dblfloat} + +\@ifundefined{table}{\newcounter {table}} % this is for LaTeX2e + +\def\fps at table{tbp} +\def\ftype at table{2} +\def\ext at table{lot} +\def\fnum at table{Table \thetable} +\def\table{\@float{table}} +\let\endtable\end at float +\@namedef{table*}{\@dblfloat{table}} +\@namedef{endtable*}{\end at dblfloat} + +\newtoks\titleboxnotes +\newcount\titleboxnoteflag + +\def\maketitle{\par + \begingroup + \def\thefootnote{\fnsymbol{footnote}} + \def\@makefnmark{\hbox + to 0pt{$^{\@thefnmark}$\hss}} + \twocolumn[\@maketitle] +\@thanks + \endgroup + \setcounter{footnote}{0} + \let\maketitle\relax + \let\@maketitle\relax + \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\gdef\@subtitle{}\let\thanks\relax + \@copyrightspace} + +%% CHANGES ON NEXT LINES +\newif\if at ll % to record which version of LaTeX is in use + +\expandafter\ifx\csname LaTeXe\endcsname\relax % LaTeX2.09 is used +\else% LaTeX2e is used, so set ll to true +\global\@lltrue +\fi + +\if at ll + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{acm_proc_article-sp} [2004/15/10 - V2.7SP - based on esub2acm.sty <23 April 96>] + \RequirePackage{latexsym}% QUERY: are these two really needed? + \let\dooptions\ProcessOptions +\else + \let\dooptions\@options +\fi +%% END CHANGES + +\def\@height{height} +\def\@width{width} +\def\@minus{minus} +\def\@plus{plus} +\def\hb at xt@{\hbox to} +\newif\if at faircopy +\@faircopyfalse +\def\ds at faircopy{\@faircopytrue} + +\def\ds at preprint{\@faircopyfalse} + +\@twosidetrue +\@mparswitchtrue +\def\ds at draft{\overfullrule 5\p@} +%% CHANGE ON NEXT LINE +\dooptions + +\lineskip \p@ +\normallineskip \p@ +\def\baselinestretch{1} +\def\@ptsize{0} %needed for amssymbols.sty + +%% CHANGES ON NEXT LINES +\if at ll% allow use of old-style font change commands in LaTeX2e +\@maxdepth\maxdepth +% +\DeclareOldFontCommand{\rm}{\ninept\rmfamily}{\mathrm} +\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} +\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} +\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} +\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} +\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} +\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} +\DeclareRobustCommand*{\cal}{\@fontswitch{\relax}{\mathcal}} +\DeclareRobustCommand*{\mit}{\@fontswitch{\relax}{\mathnormal}} +\fi +% +\if at ll + \renewcommand{\rmdefault}{cmr} % was 'ttm' +% Note! I have also found 'mvr' to work ESPECIALLY well. +% Gerry - October 1999 +% You may need to change your LV1times.fd file so that sc is +% mapped to cmcsc - -for smallcaps -- that is if you decide +% to change {cmr} to {times} above. (Not recommended) + \renewcommand{\@ptsize}{} + \renewcommand{\normalsize}{% + \@setfontsize\normalsize\@ixpt{10.5\p@}%\ninept% + \abovedisplayskip 6\p@ \@plus2\p@ \@minus\p@ + \belowdisplayskip \abovedisplayskip + \abovedisplayshortskip 6\p@ \@minus 3\p@ + \belowdisplayshortskip 6\p@ \@minus 3\p@ + \let\@listi\@listI + } +\else + \def\@normalsize{%changed next to 9 from 10 + \@setsize\normalsize{9\p@}\ixpt\@ixpt + \abovedisplayskip 6\p@ \@plus2\p@ \@minus\p@ + \belowdisplayskip \abovedisplayskip + \abovedisplayshortskip 6\p@ \@minus 3\p@ + \belowdisplayshortskip 6\p@ \@minus 3\p@ + \let\@listi\@listI + }% +\fi +\if at ll + \newcommand\scriptsize{\@setfontsize\scriptsize\@viipt{8\p@}} + \newcommand\tiny{\@setfontsize\tiny\@vpt{6\p@}} + \newcommand\large{\@setfontsize\large\@xiipt{14\p@}} + \newcommand\Large{\@setfontsize\Large\@xivpt{18\p@}} + \newcommand\LARGE{\@setfontsize\LARGE\@xviipt{20\p@}} + \newcommand\huge{\@setfontsize\huge\@xxpt{25\p@}} + \newcommand\Huge{\@setfontsize\Huge\@xxvpt{30\p@}} +\else + \def\scriptsize{\@setsize\scriptsize{8\p@}\viipt\@viipt} + \def\tiny{\@setsize\tiny{6\p@}\vpt\@vpt} + \def\large{\@setsize\large{14\p@}\xiipt\@xiipt} + \def\Large{\@setsize\Large{18\p@}\xivpt\@xivpt} + \def\LARGE{\@setsize\LARGE{20\p@}\xviipt\@xviipt} + \def\huge{\@setsize\huge{25\p@}\xxpt\@xxpt} + \def\Huge{\@setsize\Huge{30\p@}\xxvpt\@xxvpt} +\fi +\normalsize + +% make aubox hsize/number of authors up to 3, less gutter +% then showbox gutter showbox gutter showbox -- GKMT Aug 99 +\newbox\@acmtitlebox +\def\@maketitle{\newpage + \null + \setbox\@acmtitlebox\vbox{% +\baselineskip 20pt +\vskip 2em % Vertical space above title. + \begin{center} + {\ttlfnt \@title\par} % Title set in 18pt Helvetica (Arial) bold size. + \vskip 1.5em % Vertical space after title. +%This should be the subtitle. +{\subttlfnt \the\subtitletext\par}\vskip 1.25em%\fi + {\baselineskip 16pt\aufnt % each author set in \12 pt Arial, in a + \lineskip .5em % tabular environment + \begin{tabular}[t]{c}\@author + \end{tabular}\par} + \vskip 1.5em % Vertical space after author. + \end{center}} + \dimen0=\ht\@acmtitlebox + \advance\dimen0 by -12.75pc\relax % Increased space for title box -- KBT + \unvbox\@acmtitlebox + \ifdim\dimen0<0.0pt\relax\vskip-\dimen0\fi} + + +\newcount\titlenotecount +\global\titlenotecount=0 +\newtoks\tntoks +\newtoks\tntokstwo +\newtoks\tntoksthree +\newtoks\tntoksfour +\newtoks\tntoksfive + +\def\abstract{ +\ifnum\titlenotecount>0 % was =1 + \insert\footins{% + \reset at font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected at edef\@currentlabel{% + }% + \color at begingroup +\ifnum\titlenotecount=1 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=2 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=3 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=4 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\S$}\rule\z@\footnotesep\ignorespaces\the\tntoksfour\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=5 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\S$}\rule\z@\footnotesep\ignorespaces\the\tntoksfour\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\P$}\rule\z@\footnotesep\ignorespaces\the\tntoksfive\@finalstrut\strutbox}% +\fi + \color at endgroup} %g} +\fi +\setcounter{footnote}{0} +\section*{ABSTRACT}\normalsize %\the\parskip \the\baselineskip%\ninept +} + +\def\endabstract{\if at twocolumn\else\endquotation\fi} + +\def\keywords{\if at twocolumn +\section*{Keywords} +\else \small +\quotation +\fi} + +% I've pulled the check for 2 cols, since proceedings are _always_ +% two-column 11 Jan 2000 gkmt +\def\terms{%\if at twocolumn +\section*{General Terms} +%\else \small +%\quotation\the\parskip +%\fi} +} + +% -- Classification needs to be a bit smart due to optionals - Gerry/Georgia November 2nd. 1999 +\newcount\catcount +\global\catcount=1 + +\def\category#1#2#3{% +\ifnum\catcount=1 +\section*{Categories and Subject Descriptors} +\advance\catcount by 1\else{\unskip; }\fi + \@ifnextchar [{\@category{#1}{#2}{#3}}{\@category{#1}{#2}{#3}[]}% +} + +\def\@category#1#2#3[#4]{% + \begingroup + \let\and\relax + #1 [\textbf{#2}]% + \if!#4!% + \if!#3!\else : #3\fi + \else + :\space + \if!#3!\else #3\kern\z at ---\hskip\z@\fi + \textit{#4}% + \fi + \endgroup +} +% + +%%% This section (written by KBT) handles the 1" box in the lower left +%%% corner of the left column of the first page by creating a picture, +%%% and inserting the predefined string at the bottom (with a negative +%%% displacement to offset the space allocated for a non-existent +%%% caption). +%%% +\newtoks\copyrightnotice +\def\ftype at copyrightbox{8} +\def\@copyrightspace{ +\@float{copyrightbox}[b] +\begin{center} +\setlength{\unitlength}{1pc} +\begin{picture}(20,6) %Space for copyright notice +\put(0,-0.95){\crnotice{\@toappear}} +\end{picture} +\end{center} +\end at float} + +\def\@toappear{} % Default setting blank - commands below change this. +\long\def\toappear#1{\def\@toappear{\parbox[b]{20pc}{\baselineskip 9pt#1}}} +\def\toappearbox#1{\def\@toappear{\raisebox{5pt}{\framebox[20pc]{\parbox[b]{19pc}{#1}}}}} + +\newtoks\conf +\newtoks\confinfo +\def\conferenceinfo#1#2{\global\conf={#1}\global\confinfo{#2}} + + +\def\marginpar{\@latexerr{The \marginpar command is not allowed in the + `acmconf' document style.}\@eha} + +\mark{{}{}} % Initializes TeX's marks + +\def\today{\ifcase\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\fi + \space\number\day, \number\year} + +\def\@begintheorem#1#2{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {{\sc #1}\hskip 5\p@\relax#2.}% + ] + \it +} +\def\@opargbegintheorem#1#2#3{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\sc #1\ #2\ % This mod by Gerry to enumerate corollaries + \setbox\@tempboxa\hbox{(#3)} % and bracket the 'corollary title' + \ifdim \wd\@tempboxa>\z@ % and retain the correct numbering of e.g. theorems + \hskip 5\p@\relax % if they occur 'around' said corollaries. + \box\@tempboxa % Gerry - Nov. 1999. + \fi.}% + ] + \it +} +\newif\if at qeded +\global\@qededfalse + +% -- original +%\def\proof{% +% \vspace{-\parskip} % GM July 2000 (for tighter spacing) +% \global\@qededfalse +% \@ifnextchar[{\@xproof}{\@proof}% +%} +% -- end of original + +% (JSS) Fix for vertical spacing bug - Gerry Murray July 30th. 2002 +\def\proof{% +\vspace{-\lastskip}\vspace{-\parsep}\penalty-51% +\global\@qededfalse +\@ifnextchar[{\@xproof}{\@proof}% +} + +\def\endproof{% + \if at qeded\else\qed\fi + \endtrivlist +} +\def\@proof{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\sc Proof.}% + ] + \ignorespaces +} +\def\@xproof[#1]{% + \trivlist + \item[\hskip 10\p@\hskip \labelsep{\sc Proof #1.}]% + \ignorespaces +} +\def\qed{% + \unskip + \kern 10\p@ + \begingroup + \unitlength\p@ + \linethickness{.4\p@}% + \framebox(6,6){}% + \endgroup + \global\@qededtrue +} + +\def\newdef#1#2{% + \expandafter\@ifdefinable\csname #1\endcsname + {\@definecounter{#1}% + \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}% + \global\@namedef{#1}{\@defthm{#1}{#2}}% + \global\@namedef{end#1}{\@endtheorem}% + }% +} +\def\@defthm#1#2{% + \refstepcounter{#1}% + \@ifnextchar[{\@ydefthm{#1}{#2}}{\@xdefthm{#1}{#2}}% +} +\def\@xdefthm#1#2{% + \@begindef{#2}{\csname the#1\endcsname}% + \ignorespaces +} +\def\@ydefthm#1#2[#3]{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\it #2% + \savebox\@tempboxa{#3}% + \ifdim \wd\@tempboxa>\z@ + \ \box\@tempboxa + \fi.% + }]% + \ignorespaces +} +\def\@begindef#1#2{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\it #1\ \rm #2.}% + ]% +} +\def\theequation{\arabic{equation}} + +\newcounter{part} +\newcounter{section} +\newcounter{subsection}[section] +\newcounter{subsubsection}[subsection] +\newcounter{paragraph}[subsubsection] +\def\thepart{\Roman{part}} +\def\thesection{\arabic{section}} +\def\thesubsection{\thesection.\arabic{subsection}} +\def\thesubsubsection{\thesubsection.\arabic{subsubsection}} %removed \subsecfnt 29 July 2002 gkmt +\def\theparagraph{\thesubsubsection.\arabic{paragraph}} %removed \subsecfnt 29 July 2002 gkmt + +\newif\if at uchead +\@ucheadfalse + +%% CHANGES: NEW NOTE +%% NOTE: OK to use old-style font commands below, since they were +%% suitably redefined for LaTeX2e +%% END CHANGES +\setcounter{secnumdepth}{3} +\def\part{% + \@startsection{part}{9}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@} + {4\p@}{\normalsize\@ucheadtrue}% +} + +% Rationale for changes made in next four definitions: +% "Before skip" is made elastic to provide some give in setting columns (vs. +% parskip, which is non-elastic to keep section headers "anchored" to their +% subsequent text. +% +% "After skip" is minimized -- BUT setting it to 0pt resulted in run-in heads, despite +% the documentation asserted only after-skip < 0pt would have result. +% +% Baselineskip added to style to ensure multi-line section titles, and section heads +% followed by another section head rather than text, are decently spaced vertically. +% 12 Jan 2000 gkmt +\def\section{% + \@startsection{section}{1}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% + {0.5pt}{\baselineskip=14pt\secfnt\@ucheadtrue}% +} + +\def\subsection{% + \@startsection{subsection}{2}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@} + {0.5pt}{\baselineskip=14pt\secfnt}% +} +\def\subsubsection{% + \@startsection{subsubsection}{3}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% + {0.5pt}{\baselineskip=14pt\subsecfnt}% +} + +\def\paragraph{% + \@startsection{paragraph}{3}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% + {0.5pt}{\baselineskip=14pt\subsecfnt}% +} + +\let\@period=. +\def\@startsection#1#2#3#4#5#6{% + \if at noskipsec %gkmt, 11 aug 99 + \global\let\@period\@empty + \leavevmode + \global\let\@period.% + \fi + \par + \@tempskipa #4\relax + \@afterindenttrue + \ifdim \@tempskipa <\z@ + \@tempskipa -\@tempskipa + \@afterindentfalse + \fi + %\if at nobreak 11 Jan 00 gkmt + %\everypar{} + %\else + \addpenalty\@secpenalty + \addvspace\@tempskipa + %\fi + \parskip=0pt + \@ifstar + {\@ssect{#3}{#4}{#5}{#6}} + {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}% +} + + +\def\@ssect#1#2#3#4#5{% + \@tempskipa #3\relax + \ifdim \@tempskipa>\z@ + \begingroup + #4{% + \@hangfrom{\hskip #1}% + \interlinepenalty \@M #5\@@par}% + \endgroup + \else + \def\@svsechd{#4{\hskip #1\relax #5}}% + \fi + \vskip -10.5pt %gkmt, 7 jan 00 -- had been -14pt, now set to parskip + \@xsect{#3}\parskip=10.5pt} % within the starred section, parskip = leading 12 Jan 2000 gkmt + + +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c at secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + \edef\@svsec{% + \begingroup + %\ifnum#2>2 \noexpand\rm \fi % changed to next 29 July 2002 gkmt + \ifnum#2>2 \noexpand#6 \fi + \csname the#1\endcsname + \endgroup + \ifnum #2=1\relax .\fi + \hskip 1em + }% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup + #6\relax + \@hangfrom{\hskip #3\relax\@svsec}% + \begingroup + \interlinepenalty \@M + \if at uchead + \uppercase{#8}% + \else + #8% + \fi + \par + \endgroup + \endgroup + \csname #1mark\endcsname{#7}% + \vskip -10.5pt % -14pt gkmt, 11 aug 99 -- changed to -\parskip 11 Jan 2000 + \addcontentsline{toc}{#1}{% + \ifnum #2>\c at secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7% + }% + \else + \def\@svsechd{% + #6% + \hskip #3\relax + \@svsec + \if at uchead + \uppercase{#8}% + \else + #8% + \fi + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c at secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7% + }% + }% + \fi + \@xsect{#5}\parskip=10.5pt% within the section, parskip = leading 12 Jan 2000 gkmt +} +\def\@xsect#1{% + \@tempskipa #1\relax + \ifdim \@tempskipa>\z@ + \par + \nobreak + \vskip \@tempskipa + \@afterheading + \else + \global\@nobreakfalse + \global\@noskipsectrue + \everypar{% + \if at noskipsec + \global\@noskipsecfalse + \clubpenalty\@M + \hskip -\parindent + \begingroup + \@svsechd + \@period + \endgroup + \unskip + \@tempskipa #1\relax + \hskip -\@tempskipa + \else + \clubpenalty \@clubpenalty + \everypar{}% + \fi + }% + \fi + \ignorespaces +} + +\def\@trivlist{% + \@topsepadd\topsep + \if at noskipsec + \global\let\@period\@empty + \leavevmode + \global\let\@period.% + \fi + \ifvmode + \advance\@topsepadd\partopsep + \else + \unskip + \par + \fi + \if at inlabel + \@noparitemtrue + \@noparlisttrue + \else + \@noparlistfalse + \@topsep\@topsepadd + \fi + \advance\@topsep \parskip + \leftskip\z at skip + \rightskip\@rightskip + \parfillskip\@flushglue + \@setpar{\if at newlist\else{\@@par}\fi} + \global\@newlisttrue + \@outerparskip\parskip +} + +%%% Actually, 'abbrev' works just fine as the default - Gerry Feb. 2000 +%%% Bibliography style. + +\parindent 0pt +\typeout{Using 'Abbrev' bibliography style} +\newcommand\bibyear[2]{% + \unskip\quad\ignorespaces#1\unskip + \if#2..\quad \else \quad#2 \fi +} +\newcommand{\bibemph}[1]{{\em#1}} +\newcommand{\bibemphic}[1]{{\em#1\/}} +\newcommand{\bibsc}[1]{{\sc#1}} +\def\@normalcite{% + \def\@cite##1##2{[##1\if at tempswa , ##2\fi]}% +} +\def\@citeNB{% + \def\@cite##1##2{##1\if at tempswa , ##2\fi}% +} +\def\@citeRB{% + \def\@cite##1##2{##1\if at tempswa , ##2\fi]}% +} +\def\start at cite#1#2{% + \edef\citeauthoryear##1##2##3{% + ###1% + \ifnum#2=\z@ \else\ ###2\fi + }% + \ifnum#1=\thr@@ + \let\@@cite\@citeyear + \else + \let\@@cite\@citenormal + \fi + \@ifstar{\@citeNB\@@cite}{\@normalcite\@@cite}% +} +\def\cite{\start at cite23} +\def\citeNP{\cite*} +\def\citeA{\start at cite10} +\def\citeANP{\citeA*} +\def\shortcite{\start at cite23} +\def\shortciteNP{\shortcite*} +\def\shortciteA{\start at cite20} +\def\shortciteANP{\shortciteA*} +\def\citeyear{\start at cite30} +\def\citeyearNP{\citeyear*} +\def\citeN{% + \@citeRB + \def\citeauthoryear##1##2##3{##1\ [##3% + \def\reserved at a{##1}% + \def\citeauthoryear####1####2####3{% + \def\reserved at b{####1}% + \ifx\reserved at a\reserved at b + ####3% + \else + \errmessage{Package acmart Error: author mismatch + in \string\citeN^^J^^J% + See the acmart package documentation for explanation}% + \fi + }% + }% + \@ifstar\@citeyear\@citeyear +} +\def\shortciteN{% + \@citeRB + \def\citeauthoryear##1##2##3{##2\ [##3% + \def\reserved at a{##2}% + \def\citeauthoryear####1####2####3{% + \def\reserved at b{####2}% + \ifx\reserved at a\reserved at b + ####3% + \else + \errmessage{Package acmart Error: author mismatch + in \string\shortciteN^^J^^J% + See the acmart package documentation for explanation}% + \fi + }% + }% + \@ifstar\@citeyear\@citeyear % changed from "\@ifstart" 12 Jan 2000 gkmt +} + +\def\@citenormal{% + \@ifnextchar [{\@tempswatrue\@citex;} + {\@tempswafalse\@citex,[]}% was ; Gerry 2/24/00 +} +\def\@citeyear{% + \@ifnextchar [{\@tempswatrue\@citex,}% + {\@tempswafalse\@citex,[]}% +} +\def\@citex#1[#2]#3{% + \let\@citea\@empty + \@cite{% + \@for\@citeb:=#3\do{% + \@citea + \def\@citea{#1 }% + \edef\@citeb{\expandafter\@iden\@citeb}% + \if at filesw + \immediate\write\@auxout{\string\citation{\@citeb}}% + \fi + \@ifundefined{b@\@citeb}{% + {\bf ?}% + \@warning{% + Citation `\@citeb' on page \thepage\space undefined% + }% + }% + {\csname b@\@citeb\endcsname}% + }% + }{#2}% +} +\let\@biblabel\@gobble +\newdimen\bibindent +\setcounter{enumi}{1} +\bibindent=0em +\def\thebibliography#1{% +\ifnum\addauflag=0\addauthorsection\global\addauflag=1\fi + \section{% + {References} % was uppercased but this affects pdf bookmarks (SP/GM Oct. 2004) + \@mkboth{{\refname}}{{\refname}}% + }% + \list{[\arabic{enumi}]}{% + \settowidth\labelwidth{[#1]}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep + \advance\leftmargin\bibindent + \itemindent -\bibindent + \listparindent \itemindent + \usecounter{enumi} + }% + \let\newblock\@empty + \raggedright %% 7 JAN 2000 gkmt + \sloppy + \sfcode`\.=1000\relax +} + + +\gdef\balancecolumns +{\vfill\eject +\global\@colht=\textheight +\global\ht\@cclv=\textheight +} + +\newcount\colcntr +\global\colcntr=0 +\newbox\savebox + +\gdef \@makecol {% +\global\advance\colcntr by 1 +\ifnum\colcntr>2 \global\colcntr=1\fi + \ifvoid\footins + \setbox\@outputbox \box\@cclv + \else + \setbox\@outputbox \vbox{% +\boxmaxdepth \@maxdepth + \@tempdima\dp\@cclv + \unvbox \@cclv + \vskip-\@tempdima + \vskip \skip\footins + \color at begingroup + \normalcolor + \footnoterule + \unvbox \footins + \color at endgroup + }% + \fi + \xdef\@freelist{\@freelist\@midlist}% + \global \let \@midlist \@empty + \@combinefloats + \ifvbox\@kludgeins + \@makespecialcolbox + \else + \setbox\@outputbox \vbox to\@colht {% +\@texttop + \dimen@ \dp\@outputbox + \unvbox \@outputbox + \vskip -\dimen@ + \@textbottom + }% + \fi + \global \maxdepth \@maxdepth +} +\def\titlenote{\@ifnextchar[\@xtitlenote{\stepcounter\@mpfn +\global\advance\titlenotecount by 1 +\ifnum\titlenotecount=1 + \raisebox{9pt}{$\ast$} +\fi +\ifnum\titlenotecount=2 + \raisebox{9pt}{$\dagger$} +\fi +\ifnum\titlenotecount=3 + \raisebox{9pt}{$\ddagger$} +\fi +\ifnum\titlenotecount=4 +\raisebox{9pt}{$\S$} +\fi +\ifnum\titlenotecount=5 +\raisebox{9pt}{$\P$} +\fi + \@titlenotetext +}} + +\long\def\@titlenotetext#1{\insert\footins{% +\ifnum\titlenotecount=1\global\tntoks={#1}\fi +\ifnum\titlenotecount=2\global\tntokstwo={#1}\fi +\ifnum\titlenotecount=3\global\tntoksthree={#1}\fi +\ifnum\titlenotecount=4\global\tntoksfour={#1}\fi +\ifnum\titlenotecount=5\global\tntoksfive={#1}\fi + \reset at font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected at edef\@currentlabel{% + }% + \color at begingroup + \color at endgroup}} + +%%%%%%%%%%%%%%%%%%%%%%%%% +\ps at plain +\baselineskip=11pt +\let\thepage\relax % For NO page numbers - Gerry Nov. 30th. 1999 +\def\setpagenumber#1{\global\setcounter{page}{#1}} +%\pagenumbering{arabic} % Arabic page numbers but commented out for NO page numbes - Gerry Nov. 30th. 1999 +\twocolumn % Double column. +\flushbottom % Even bottom -- alas, does not balance columns at end of document +\pagestyle{plain} + +% Need Copyright Year and Copyright Data to be user definable (in .tex file). +% Gerry Nov. 30th. 1999 +\newtoks\copyrtyr +\newtoks\acmcopyr +\newtoks\boilerplate +\def\CopyrightYear#1{\global\copyrtyr{#1}} +\def\crdata#1{\global\acmcopyr{#1}} +\def\permission#1{\global\boilerplate{#1}} +% +\newtoks\copyrightetc +\global\copyrightetc{\ } % Need to have 'something' so that adequate space is left for pasting in a line if "confinfo" is supplied. + +\toappear{\the\boilerplate\par +{\confname{\the\conf}} \the\confinfo\par \the\copyrightetc} +% End of ACM_PROC_ARTICLE-SP.CLS -- V2.7SP - 10/15/2004 -- +% Gerry Murray -- October 15th. 2004 Added: pypy/extradoc/talk/icooolps2009/code/full.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/code/full.txt Tue Mar 31 11:26:33 2009 @@ -0,0 +1,22 @@ +\begin{verbatim} +loop_start(a0, regs0) +# MOV_R_A 0 +a1 = call(Const(<* fn list_getitem>), regs0, Const(0)) +# DECR_A +a2 = int_sub(a1, Const(1)) +# MOV_A_R 0 +call(Const(<* fn list_setitem>), regs0, Const(0), a2) +# MOV_R_A 2 +a3 = call(Const(<* fn list_getitem>), regs0, Const(2)) +# ADD_R_TO_A 1 +i0 = call(Const(<* fn list_getitem>), regs0, Const(1)) +a4 = int_add(a3, i0) +# MOV_A_R 2 +call(Const(<* fn list_setitem>), regs0, Const(2), a4) +# MOV_R_A 0 +a5 = call(Const(<* fn list_getitem>), regs0, Const(0)) +# JUMP_IF_A 4 +i1 = int_is_true(a5) +guard_true(i1) +jump(a5, regs0) +\end{verbatim} Added: pypy/extradoc/talk/icooolps2009/code/no-green-folding.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/code/no-green-folding.txt Tue Mar 31 11:26:33 2009 @@ -0,0 +1,62 @@ +{\small +\begin{verbatim} +loop_start(a0, regs0, bytecode0, pc0) +# MOV_R_A 0 +opcode0 = strgetitem(bytecode0, pc0) +pc1 = int_add(pc0, Const(1)) +guard_value(opcode0, Const(2)) +n1 = strgetitem(bytecode0, pc1) +pc2 = int_add(pc1, Const(1)) +a1 = call(Const(<* fn list_getitem>), regs0, n1) +# DECR_A +opcode1 = strgetitem(bytecode0, pc2) +pc3 = int_add(pc2, Const(1)) +guard_value(opcode1, Const(7)) +a2 = int_sub(a1, Const(1)) +# MOV_A_R 0 +opcode1 = strgetitem(bytecode0, pc3) +pc4 = int_add(pc3, Const(1)) +guard_value(opcode1, Const(1)) +n2 = strgetitem(bytecode0, pc4) +pc5 = int_add(pc4, Const(1)) +call(Const(<* fn list_setitem>), regs0, n2, a2) +# MOV_R_A 2 +opcode2 = strgetitem(bytecode0, pc5) +pc6 = int_add(pc5, Const(1)) +guard_value(opcode2, Const(2)) +n3 = strgetitem(bytecode0, pc6) +pc7 = int_add(pc6, Const(1)) +a3 = call(Const(<* fn list_getitem>), regs0, n3) +# ADD_R_TO_A 1 +opcode3 = strgetitem(bytecode0, pc7) +pc8 = int_add(pc7, Const(1)) +guard_value(opcode3, Const(5)) +n4 = strgetitem(bytecode0, pc8) +pc9 = int_add(pc8, Const(1)) +i0 = call(Const(<* fn list_getitem>), regs0, n4) +a4 = int_add(a3, i0) +# MOV_A_R 2 +opcode4 = strgetitem(bytecode0, pc9) +pc10 = int_add(pc9, Const(1)) +guard_value(opcode4, Const(1)) +n5 = strgetitem(bytecode0, pc10) +pc11 = int_add(pc10, Const(1)) +call(Const(<* fn list_setitem>), regs0, n5, a4) +# MOV_R_A 0 +opcode5 = strgetitem(bytecode0, pc11) +pc12 = int_add(pc11, Const(1)) +guard_value(opcode5, Const(2)) +n6 = strgetitem(bytecode0, pc12) +pc13 = int_add(pc12, Const(1)) +a5 = call(Const(<* fn list_getitem>), regs0, n6) +# JUMP_IF_A 4 +opcode6 = strgetitem(bytecode0, pc13) +pc14 = int_add(pc13, Const(1)) +guard_value(opcode6, Const(3)) +target0 = strgetitem(bytecode0, pc14) +pc15 = int_add(pc14, Const(1)) +i1 = int_is_true(a5) +guard_true(i1) +jump(a5, regs0, bytecode0, target0) +\end{verbatim} +} Added: pypy/extradoc/talk/icooolps2009/code/normal-tracing.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/code/normal-tracing.txt Tue Mar 31 11:26:33 2009 @@ -0,0 +1,8 @@ +\begin{verbatim} +loop_start(a0, regs0, bytecode0, pc0) +opcode0 = strgetitem(bytecode0, pc0) +pc1 = int_add(pc0, Const(1)) +guard_value(opcode0, Const(7)) +a1 = int_sub(a0, Const(1)) +jump(a1, regs0, bytecode0, pc1) +\end{verbatim} Added: pypy/extradoc/talk/icooolps2009/code/tlr-paper-full.py ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/code/tlr-paper-full.py Tue Mar 31 11:26:33 2009 @@ -0,0 +1,32 @@ +\begin{verbatim} +class TLRJitDriver(JitDriver): + greens = ['pc', 'bytecode'] + reds = ['a', 'regs'] + +tlrjitdriver = TLRJitDriver() + +def interpret(bytecode, a): + regs = [0] * 256 + pc = 0 + while True: + tlrjitdriver.jit_merge_point( + bytecode=bytecode, pc=pc, + a=a, regs=regs) + opcode = ord(bytecode[pc]) + pc += 1 + if opcode == JUMP_IF_A: + target = ord(bytecode[pc]) + pc += 1 + if a: + if target < pc: + tlrjitdriver.can_enter_jit( + bytecode=bytecode, pc=target, + a=a, regs=regs) + pc = target + elif opcode == MOV_A_R: + n = ord(bytecode[pc]) + pc += 1 + regs[n] = a + elif opcode == MOV_R_A: + ... # rest unmodified +\end{verbatim} Added: pypy/extradoc/talk/icooolps2009/code/tlr-paper.py ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/code/tlr-paper.py Tue Mar 31 11:26:33 2009 @@ -0,0 +1,29 @@ +\begin{verbatim} +def interpret(bytecode, a): + regs = [0] * 256 + pc = 0 + while True: + opcode = ord(bytecode[pc]) + pc += 1 + if opcode == JUMP_IF_A: + target = ord(bytecode[pc]) + pc += 1 + if a: + pc = target + elif opcode == MOV_A_R: + n = ord(bytecode[pc]) + pc += 1 + regs[n] = a + elif opcode == MOV_R_A: + n = ord(bytecode[pc]) + pc += 1 + a = regs[n] + elif opcode == ADD_R_TO_A: + n = ord(bytecode[pc]) + pc += 1 + a += regs[n] + elif opcode == DECR_A: + a -= 1 + elif opcode == RETURN_A: + return a +\end{verbatim} Added: pypy/extradoc/talk/icooolps2009/paper.bib ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/paper.bib Tue Mar 31 11:26:33 2009 @@ -0,0 +1,160 @@ +??? + at techreport{miranda_context_1999, + title = {Context Management in {VisualWorks} 5i}, + abstract = {Smalltalk-80 provides a reification of execution state in the form of context objects which represent procedure activation records. Smalltalk-80 also provides full closures with indefinite extent. These features pose interesting implementation challenges because a na??ve implementation entails instantiating context objects on every method activation, but typical Smalltalk-80 programs obey stack discipline for the vast majority of activations. Both software and hardware implementations of Smalltalk-80 have mapped contexts and closure activations to stack frames but not without overhead when compared to traditional stack-based activation and return in ???conventional??? languages. We present a new design for contexts and closures that significantly reduces the overall overhead of these features and imposes overhead only in code that actually manipulates execution state in the form of contexts.}, + institution = {{ParcPlace} Division, {CINCOM,} Inc.}, + author = {Eliot Miranda}, + year = {1999}, +}, + + at inproceedings{sullivan_dynamic_2003, + address = {San Diego, California}, + title = {Dynamic native optimization of interpreters}, + isbn = {1-58113-655-2}, + url = {http://portal.acm.org/citation.cfm?id=858570.858576}, + doi = {10.1145/858570.858576}, + abstract = {For domain specific languages, "scripting languages", dynamic languages, and for virtual machine-based languages, the most straightforward implementation strategy is to write an interpreter. A simple interpreter consists of a loop that fetches the next bytecode, dispatches to the routine handling that bytecode, then loops. There are many ways to improve upon this simple mechanism, but as long as the execution of the program is driven by a representation of the program other than as a stream of native instructions, there will be some "interpretive {overhead".There} is a long history of approaches to removing interpretive overhead from programming language implementations. In practice, what often happens is that, once an interpreted language becomes popular, pressure builds to improve performance until eventually a project is undertaken to implement a native Just In Time {(JIT)} compiler for the language. Implementing a {JIT} is usually a large effort, affects a significant part of the existing language implementation, and adds a significant amount of code and complexity to the overall code {base.In} this paper, we present an innovative approach that dynamically removes much of the interpreted overhead from language implementations, with minimal instrumentation of the original interpreter. While it does not give the performance improvements of hand-crafted native compilers, our system provides an appealing point on the language implementation spectrum.}, + booktitle = {Proceedings of the 2003 workshop on Interpreters, virtual machines and emulators}, + publisher = {{ACM}}, + author = {Gregory T. Sullivan and Derek L. Bruening and Iris Baron and Timothy Garnett and Saman Amarasinghe}, + year = {2003}, + pages = {50--57}, +}, + + at inbook{bolz_back_2008, + title = {Back to the Future in One Week ??? Implementing a Smalltalk {VM} in {PyPy}}, + url = {http://dx.doi.org/10.1007/978-3-540-89275-5_7}, + abstract = {We report on our experiences with the Spy project, including implementation details and benchmark results. Spy is a re-implementation of the Squeak (i.e. Smalltalk-80) {VM} using the {PyPy} toolchain. The {PyPy} project allows code written in {RPython,} a subset of Python, to be translated +to a multitude of different backends and architectures. During the translation, many aspects of the implementation can be +independently tuned, such as the garbage collection algorithm or threading implementation. In this way, a whole host of interpreters +can be derived from one abstract interpreter definition. Spy aims to bring these benefits to Squeak, allowing for greater portability and, eventually, improved performance. The current +Spy codebase is able to run a small set of benchmarks that demonstrate performance superior to many similar Smalltalk {VMs,} but +which still run slower than in Squeak itself. Spy was built from scratch over the course of a week during a joint {Squeak-PyPy} Sprint in Bern last autumn. +}, + booktitle = {{Self-Sustaining} Systems}, + author = {Carl Friedrich Bolz and Adrian Kuhn and Adrian Lienhard and Nicholas Matsakis and Oscar Nierstrasz and Lukas Renggli and Armin Rigo and Toon Verwaest}, + year = {2008}, + pages = {123--139} +}, + + at inproceedings{hlzle_optimizing_1994, + address = {Orlando, Florida, United States}, + title = {Optimizing dynamically-dispatched calls with run-time type feedback}, + isbn = {{0-89791-662-X}}, + url = {http://portal.acm.org/citation.cfm?id=178243.178478}, + doi = {10.1145/178243.178478}, + abstract = {Note: {OCR} errors may be found in this Reference List extracted from the full text article. {ACM} has opted to expose the complete List rather than only correct and linked references.}, + booktitle = {Proceedings of the {ACM} {SIGPLAN} 1994 conference on Programming language design and implementation}, + publisher = {{ACM}}, + author = {Urs H??lzle and David Ungar}, + year = {1994}, + pages = {326--336}, +}, + + at techreport{andreas_gal_incremental_2006, + title = {Incremental Dynamic Code Generation with Trace Trees}, + abstract = {The unit of compilation for traditional just-in-time compilers is the method. We have explored trace-based compilation, in which the unit of compilation is a loop, potentially spanning multiple methods and even library code. Using a new intermediate representation that is discovered and updated lazily on-demand while the program is being executed, our compiler generates code that is competitive with traditional dynamic compilers, but that uses only a fraction of the compile time and memory footprint.}, + number = {{ICS-TR-06-16}}, + institution = {Donald Bren School of Information and Computer Science, University of California, Irvine}, + author = {Andreas Gal and Michael Franz}, + month = nov, + year = {2006}, + pages = {11} +}, + + at techreport{mason_chang_efficient_2007, + title = {Efficient {Just-In-Time} Execution of Dynamically Typed Languages +Via Code Specialization Using Precise Runtime Type Inference}, + abstract = {Dynamically typed languages such as {JavaScript} present a challenge to just-in-time compilers. In contrast to statically typed languages such as {JVML,} in which there are specific opcodes for common operations on primitive types (such as iadd for integer addition), all operations in dynamically typed language such as {JavaScript} are late-bound. Often enough, types cannot be inferred with certainty ahead of execution. As a result, just-in-time compilers for dynamically typed languages have tended to perform worse than their statically-typed counterparts. We present a new approach to compiling dynamically typed languages in which code traces observed during execution are dynamically specialized for each actually observed run-time type. For most benchmark programs, our prototype {JavaScript} virtual machine outperforms every other {JavaScript} platform known to us.}, + number = {{ICS-TR-07-10}}, + institution = {Donald Bren School of Information and Computer Science, University of California, Irvine}, + author = {Mason Chang and Michael Bebenita and Alexander Yermolovich and Andreas Gal and Michael Franz}, + year = {2007}, +}, + + at inproceedings{andreas_gal_one_2007, + address = {Berlin, Germany}, + title = {One Method At A Time Is Quite a Waste of Time}, + abstract = {Most just-in-time compilers for object-oriented languages operate at the granularity of methods. Unfortunately, even ???hot??? methods often contain "cold" code paths. As a consequence, just-in-time compilers waste time compiling code that will be executed only rarely, if at all. We discuss an alternative approach in which only truly ???hot??? code is ever compiled. +}, + booktitle = {Proceedings of the Second Workshop on Implementation, Compilation, Optimization of {Object-Oriented} Languages, Programs and Systems {(ICOOOLPS'2007)}}, + author = {Andreas Gal and Michael Bebenita and Michael Franz}, + month = jul, + year = {2007}, + pages = {11--16}, +}, + + at inproceedings{carl_friedrich_bolz_to_2007, + title = {How to not write a Virtual Machine}, + abstract = {Typical modern dynamic languages have a growing number of implementations. We explore the reasons for this situation, and the limitations it imposes on open source or academic communities that lack the resources to fine-tune and maintain them all. It is sometimes proposed that implementing dynamic languages on top of a standardized general-purpose object-oriented virtual machine (like Java or {.NET)} would help reduce this burden. We propose a complementary alternative to writing custom virtual machine {(VMs)} by hand, validated by the {PyPy} project: flexibly generating {VMs} from a high-level "specification", +inserting features and low-level details automatically ??? including good just-in-time compilers tuned to the dynamic language at hand. +We believe this to be ultimately a better investment of efforts than the development of more and more advanced general-purpose object +oriented {VMs.} In this paper we compare these two approaches in detail.}, + booktitle = {Proceedings of 3rd Workshop on Dynamic Languages and Applications {(DYLA} 2007)}, + author = {Carl Friedrich Bolz and Armin Rigo}, + year = {2007} +}, + + at inproceedings{rigo_pypys_2006, + address = {Portland, Oregon, {USA}}, + title = {{PyPy's} approach to virtual machine construction}, + isbn = {{1-59593-491-X}}, + url = {http://portal.acm.org/citation.cfm?id=1176753}, + doi = {10.1145/1176617.1176753}, + abstract = {The {PyPy} project seeks to prove both on a research and a practical level the feasibility of constructing a virtual machine {(VM)} for a dynamic language in a dynamic language - in this case, Python. The aim is to translate (i.e. compile) the {VM} to arbitrary target environments, ranging in level from {C/Posix} to {Smalltalk/Squeak} via Java and {CLI/.NET,} while still being of reasonable efficiency within these {environments.A} key tool to achieve this goal is the systematic reuse of the Python language as a system programming language at various levels of our architecture and translation process. For each level, we design a corresponding type system and apply a generic type inference engine - for example, the garbage collector is written in a style that manipulates simulated pointer and address objects, and when translated to C these operations become C-level pointer and address instructions.}, + booktitle = {Companion to the 21st {ACM} {SIGPLAN} conference on Object-oriented programming systems, languages, and applications}, + publisher = {{ACM}}, + author = {Armin Rigo and Samuele Pedroni}, + year = {2006}, + pages = {944--953} +}, + + at article{bala_dynamo:transparent_2000, + title = {Dynamo: a transparent dynamic optimization system}, + volume = {35}, + url = {http://citeseer.ist.psu.edu/bala00dynamo.html}, + number = {5}, + journal = {{ACM} {SIG{\textbackslash}-PLAN} Notices}, + author = {Vasanth Bala and Evelyn Duesterwald and Sanjeev Banerjia}, + year = {2000}, + pages = {1--12} +}, + + at inproceedings{gal_hotpathvm:effective_2006, + address = {Ottawa, Ontario, Canada}, + title = {{HotpathVM:} an effective {JIT} compiler for resource-constrained devices}, + isbn = {1-59593-332-6}, + url = {http://portal.acm.org/citation.cfm?doid=1134760.1134780}, + doi = {10.1145/1134760.1134780}, + abstract = {We present a just-in-time compiler for a Java {VM} that is small enough to fit on resource-constrained devices, yet is surprisingly effective. Our system dynamically identifies traces of frequently executed bytecode instructions (which may span several basic blocks across several methods) and compiles them via Static Single Assignment {(SSA)} construction. Our novel use of {SSA} form in this context allows to hoist instructions across trace side-exits without necessitating expensive compensation code in off-trace paths. The overall memory consumption (code and data) of our system is only 150 {kBytes,} yet benchmarks show a speedup that in some cases rivals heavy-weight just-in-time compilers.}, + booktitle = {Proceedings of the 2nd international conference on Virtual execution environments}, + publisher = {{ACM}}, + author = {Andreas Gal and Christian W. Probst and Michael Franz}, + year = {2006}, + pages = {144--153} +}, + + at inproceedings{hlzle_optimizing_1991, + title = {Optimizing {Dynamically-Typed} {Object-Oriented} Languages With Polymorphic Inline Caches}, + isbn = {3-540-54262-0}, + url = {http://portal.acm.org/citation.cfm?id=679193&dl=ACM&coll=portal}, + booktitle = {Proceedings of the European Conference on {Object-Oriented} Programming}, + publisher = {{Springer-Verlag}}, + author = {Urs H??lzle and Craig Chambers and David Ungar}, + year = {1991}, + pages = {21--38} +}, + + at inproceedings{rigo_representation-based_2004, + address = {Verona, Italy}, + title = {Representation-based just-in-time specialization and the psyco prototype for python}, + isbn = {1-58113-835-0}, + url = {http://portal.acm.org/citation.cfm?id=1014010}, + doi = {10.1145/1014007.1014010}, + abstract = {A powerful application of specialization is to remove interpretative overhead: a language can be implemented with an interpreter, whose performance is then improved by specializing it for a given program source. This approach is only moderately successful with very high level languages, where the operation of each single step can be highly dependent on run-time data and context. In the present paper, the Psyco prototype for the Python language is presented. It introduces two novel techniques. The first is just-in-time specialization, or specialization by need, which introduces the "unlifting" ability for a value to be promoted from run-time to compile-time during specialization -- the inverse of the lift operator of partial evaluation. Its presence gives an unusual and powerful perspective on the specialization process. The second technique is representations, a theory of data-oriented specialization generalizing the traditional specialization domains (i.e. the compile-time/run-time dichotomy).}, + booktitle = {Proceedings of the 2004 {ACM} {SIGPLAN} symposium on Partial evaluation and semantics-based program manipulation}, + publisher = {{ACM}}, + author = {Armin Rigo}, + year = {2004}, + pages = {15--26} +} Added: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 11:26:33 2009 @@ -0,0 +1,630 @@ +\documentclass{acm_proc_article-sp} + +\usepackage{ifthen} +\usepackage{fancyvrb} +\usepackage{color} + +\let\oldcite=\cite + +\renewcommand\cite[1]{\ifthenelse{\equal{#1}{XXX}}{[citation~needed]}{\oldcite{#1}}} + +\begin{document} + +\title{Tracing the Meta-Level: PyPy's JIT Compiler} + +\numberofauthors{2} +\author{ +\alignauthor Carl Friedrich Bolz\\ + \affaddr{Heinrich-Heine-Universit?t D?sseldorf}\\ + \affaddr{Softwaretechnik und Programmiersprachen}\\ + \affaddr{Institut f?r Informatik}\\ + \affaddr{Universit?tsstra{\ss}e 1}\\ + \affaddr{D-40225 D?sseldorf}\\ + \affaddr{Deutschland}\\ + \email{cfbolz at gmx.de} +\alignauthor Armin Rigo\\ + \email{arigo at tunes.org} +} +\maketitle + + +%\category{D.3.4}{Programming Languages}{Processors}[code generation, +%interpreters, run-time environments] +%\category{F.3.2}{Logics and Meanings of Programs}{Semantics of Programming +%Languages}[program analysis] + +\begin{abstract} +In this paper we describe the ongoing research in the PyPy project to write a +JIT compiler that is automatically adapted to various languages, given an +interpreter for that language. This is achieved with the help of a slightly +adapted tracing JIT compiler in combination with some hints by the author of the +interpreter. XXX + +\end{abstract} + +XXX write somewhere that we will be predominantly occupied with bytecode +interpreters +XXX write somewhere that one problem of using tracing JITs for dynamic languages +is that dynamic languages have very complex bytecodes + + +\section{Introduction} + +Dynamic languages, rise in popularity, bla bla XXX + +One of the often-cited drawbacks of dynamic languages is the performance +penalties they impose. Typically they are slower than statically typed languages +\cite{XXX}. Even though there has been a lot of research into improving the +performance of dynamic languages \cite{XXX}, those techniques are not as widely +used as one would expect. Many dynamic language implementations use completely +straightforward bytecode-interpreters without any advanced implementation +techniques like just-in-time compilation. There are a number of reasons for +this. Most of them boil down to the inherent complexities of using compilation. +Interpreters are simple to understand and to implement whereas writing a +just-in-time compiler is an error-prone task that is even made harder by the +dynamic features of a language. + +writing an interpreter has many advantages... XXX + +A recent approach to getting better performance for dynamic languages is that of +tracing JIT compilers. XXX + +The PyPy project is trying to find approaches to generally ease the +implementation of dynamic languages. It started as a Python implementation in +Python, but has now extended its goals to be generally useful for implementing +other dynamic languages as well. The general approach is to implement an +interpreter for the language in a subset of Python. This subset is chosen in +such a way that programs in it can be compiled into various target environments, +such as C/Posix, the CLR or the JVM. The PyPy project is described in more +details in Section \ref{sect:pypy}. + +In this paper we discuss ongoing work in the PyPy project to improve the +performance of interpreters written with the help of the PyPy toolchain. The +approach is that of a tracing JIT compiler. Opposed to the tracing JITs for dynamic +languages that exist so far, PyPy's tracing JIT operates "one level down", +e.g. traces the execution of the interpreter, as opposed to the execution +of the user program. The fact that the program the tracing JIT compiles is +in our case always an interpreter brings its own set of problems. We describe +tracing JITs and their application to interpreters in Section +\ref{sect:tracing}. By this approach we hope to get a JIT compiler that can be +applied to a variety of dynamic languages, given an interpreter for them. The +process is not completely automatic but needs a small number of hints from the +interpreter author, to help the tracing JIT. The details of how the process +integrates into the rest of PyPy will be explained in Section +\ref{sect:implementation}. This work is not finished, but already produces some +promising results, which we will discuss in Section \ref{sect:evaluation}. + + +%- dynamic languages important +%- notoriously difficult to achieve good performance +%- even though the techniques exist since a while, not many implementations +% actually use them +% - hard to get all corner-cases right +% - languages evolve +% - modern dynamic languages are large +% - open source/research communities don't have that many resources +% +%- PyPy project: trying find approaches to ease the implementation of dynamic +%languages +%- explore general ways to improve on the speed of dynamic languages with reduced +%effort +%- approach: write a tracing JIT that is applicable to many different languages, +%by tracing "one level done" +%- needs some hints by the interpreter-writer + slightly different optimizations +%- paper will describe the problems of applying a tracing jit to an interpreter +%- different integration needed than a typical tracing jit + + +\section{The PyPy Project} +\label{sect:pypy} + +The PyPy project\footnote{http://codespeak.net/pypy} was started to implement a +new Python interpreter in Python but has now extended its goals to be an +environment where flexible implementation of dynamic languages can be written. +To implement a dynamic language with PyPy, an interpreter for that language has +to be written in RPython. RPython ("Restricted Python") is a subset of Python +chosen in such a way that type inference can be performed on it. The language +interpreter can then be translated with the help of PyPy into various target +environments, such as C/Posix, the CLR and the JVM. This is done by a component +of PyPy called the \emph{translation toolchain}. + +The central idea of this way to implement VMs is that the interpreter +implementation in RPython should be as free as possible of low-level +implementation details, such as memory management strategy, threading model or +object layout. Instead, these details are inserted into the VM during the +translation process by the translation toolchain. This makes it possible to +change these details later, if that becomes necessary. This is something that is +hard to do with a traditional VM written in a low-level language such as C, +since the low-level details need to be fixed early in the development-process. +XXX is this paragraph really needed? + +In the following we will describe some details of the translation process, since +they are needed in Section \ref{sect:implementation}. The first step is to produce +control flow graphs of all functions of the RPython program. Afterwards, type +inference is performed to gain type information about all the variables in the +flow graphs. Afterwards, the abstraction level of the operations in the graphs +is lowered in a stepwise fashion. At the end of this process, all operations in +the graphs correspond rather directly to a simple operation in C. The variables +are annotated with a C-like type system containing primitive types (like +\texttt{Signed}, \texttt{Bool}, etc.) or pointer types pointing to Structs, +Arrays or Functions. + +XXX example. reuse the one of the tracing jit? + +The translation process usually just turns these graphs into C code so that they +can be compiled into an executable. However, they can also be interpreted in +various ways. This is useful for testing and debugging the translation toolchain +because the produced error messages in case of a crash are a lot more helpful +than what would be produced after compilation to C. These low-level graphs are +also what the tracing JIT takes as input, as we will see later. + + +%- original goal: Python interpreter in Python +%- general way to write flexible VMs for dynamic languages +%- interpreter written in RPython, subset of Python to allow type inference +%- translation toolchain +% - naive forward-propagation type inference +% - lowering of abstractions +% - lltype system, monomorphic C-level operations +% - type system: primitives, pointers to structs and arrays +% - still assumes presence of GC +% - can be interpreted in various ways + +\section{Tracing JIT Compilers} +\label{sect:tracing} + +Tracing JITs are an idea explored by the Dynamo project +\cite{bala_dynamo:transparent_2000} in the context of dynamic optimization of +machine code at runtime. The techniques were then successfully applied to Java +VMs \cite{gal_hotpathvm:effective_2006}. It also turned out that they are a +relatively simple way to implement a JIT compiler for a dynamic language +\cite{XXX}. The technique is now used by both and are now being used by both Mozilla's +TraceMonkey JavaScript VM \cite{XXX} and Adobe's Tamarin ActionScript VM +\cite{XXX}. + +Tracing JITs are built on the following basic assumptions: + +\begin{itemize} + \item programs spend most of their runtime in loops + \item several iterations of the same loop are likely to take similar code paths +\end{itemize} + +The basic approach of a tracing JIT is to only generate machine code for the hot +code paths of commonly executed loops and to interpret the rest of the program. +The code for those common loops however should be highly optimized, including +aggressive inlining. + +The generation of loops works as follows: At first, everything is interpreted. +The interpreter does a bit of lightweight profiling to figure out which loops +are run often. This lightweight profiling is usually done by having a counter on +each backward jump instruction that counts how often this particular backward jump +was executed. Since loops need a backward jump somewhere, this method finds +loops in the user program. + +When a common loop is identified, the interpreter enters a +special mode (called tracing mode). When in tracing mode, the interpreter +records a history (the \emph{trace}) of all the operations it executes, in addition +to actually performing the operations. During tracing, the trace is repeatedly +(XXX make this more precise: when does the check happen?) +checked whether the interpreter is at a position in the program that it had seen +earlier in the trace. If this happens, the trace recorded corresponds to a loop +in the program that the tracing interpreter is running. At this point, this loop +is turned into machine code by taking the trace and making machine code versions +of all the operations in it. The machine code can then be immediately executed, +as it represents exactly the loop that is being interpreted at the moment anyway. + +This process assumes that the path through the loop that was traced is a +"typical" example of possible paths (which is statistically likely). Of course +it is possible that later another path through the loop is taken, therefore the +machine code will contain \emph{guards}, which check that the path is still the same. +If a guard fails during execution of the machine code, the machine code is left +and execution falls back to using interpretation (there are more complex +mechanisms in place to still produce more code for the cases of guard failures, +but they are of no importance for this paper XXX is that true?). + +It is important to understand when the tracer considers a loop in the trace to +be closed. This happens when the \emph{position key} is the same as at an earlier +point. The position key describes the position of the execution of the program, +e.g. usually contains things like the function currently being executed and the +program counter position of the tracing interpreter. The tracing interpreter +does not need to check all the time whether the position key already occurred +earlier, but only at instructions that are able to change the position key +to an earlier value, e.g. a backward branch instruction. Note that this is +already the second place where backward branches are treated specially: During +interpretation they are the place where the profiling is performed and where +tracing is started or already existing assembler code entered; during tracing +they are the place where the check for a closed loop is performed. + +Let's look at a small example. Take the following (slightly contrived) RPython +code: +\begin{verbatim} +def f(a, b): + if b % 46 == 41: + return a - b + else: + return a + b +def strange_sum(n): + result = 0 + while n >= 0: + result = f(result, n) + n -= 1 + return result +\end{verbatim} + +At first those functions will be interpreted, but after a while, profiling shows +that the \texttt{while} loop in \texttt{strange\_sum} is executed often. The +tracing JIT will then start trace the execution of that loop. The trace would +look as follows: +\begin{verbatim} +loop_header(result0, n0) +i0 = int_mod(n0, Const(46)) +i1 = int_eq(i0, Const(41)) +guard_false(i1) +result1 = int_add(result0, n0) +n1 = int_sub(n0, Const(1)) +i2 = int_ge(n1, Const(0)) +guard_true(i2) [result1] +jump(result1, n1) +\end{verbatim} + +XXX add a note about the SSA-ness of the trace + +This trace will then be turned into machine code. Note that the machine code +loop is by itself infinite and can only be left via a guard failure. Also note +\texttt{f} was inlined into the loop and how the common \texttt{else} case was +turned into machine code, while the other one is implemented via a guard +failure. The variables in square brackets after the guards are the state that +the interpreter will get when the guard fails. + +%- general introduction to tracing +%- assumptions +%- mixed-mode execution environment: interpretation, tracing, compilation, +% running native code +%- write why tracing jits are particularly well suited for dynamic languages + +\subsection{Applying a Tracing JIT to an Interpreter} + +XXX \cite{sullivan_dynamic_2003} somewhere + +The tracing JIT of the PyPy project is atypical in that it is not applied to the +user program, but to the interpreter running the user program. In this section +we will explore what problems this brings, and how to solve them (at least +partially). This means that there are two interpreters involved, and we need +terminology to distinguish them. On the one hand, there is the interpreter that +the tracing JIT uses to perform tracing. This we will call the \emph{tracing +interpreter}. On the other hand, there is the interpreter that is running the +users programs, which we will call the \emph{language interpreter}. The program +that the language interpreter executes we will call the \emph{user program} +(from the point of view of a VM author, the "user" is a programmer using the +VM). + +A tracing JIT compiler finds the hot loops of the program it is compiling. In +our case, this program is the language interpreter. The hot loop of the language +interpreter is the bytecode dispatch loop. Usually it is also the only hot loop. +Tracing one iteration of this loop means that the execution of one bytecode was +seen. This means that the resulting machine code will correspond to a loop, that +assumes that this particular bytecode will be executed many times in a row, +which is clearly very unlikely. + +\begin{figure} +\input{code/tlr-paper.py} +\caption{A very simple bytecode interpreter with registers and an accumulator.} +\label{fig:tlr-basic} +\end{figure} + +\begin{figure} +\begin{verbatim} + MOV_A_R 0 # i = a + MOV_A_R 1 # copy of 'a' + + # 4: + MOV_R_A 0 # i-- + DECR_A + MOV_A_R 0 + + MOV_R_A 2 # res += a + ADD_R_TO_A 1 + MOV_A_R 2 + + MOV_R_A 0 # if i!=0: goto 4 + JUMP_IF_A 4 + + MOV_R_A 2 # return res + RETURN_A +\end{verbatim} +\caption{Example bytecode: Compute the square of the accumulator} +\label{fig:square} +\end{figure} + +Let's look at an example. Figure \ref{fig:tlr-basic} shows the code of a very +simple bytecode interpreter with 256 registers and an accumulator. The +\texttt{bytecode} argument is a string of bytes and all register and the +accumulator are integers. A simple program for this interpreter that computes +the square of the accumulator is shown in Figure \ref{fig:square}. If the +tracing interpreter traces the execution of the \texttt{DECR\_A} bytecode, the +trace would look as follows: +\input{code/normal-tracing.txt} + +To improve this situation, the tracing JIT could trace the execution of several +bytecodes, thus effectively unrolling the bytecode dispatch loop. Ideally, the +bytecode loop should be unrolled exactly so much, that the unrolled version +corresponds to a loop on the level of the user program. A loop in the user +program occurs when the program counter of the language interpreter has the +same value many times. This program counter is typically one or several +variables in the language interpreter, for example the bytecode object of the +currently executed function of the user program and the position of the current +bytecode within that. + +Since the tracing JIT cannot know which parts of the language interpreter are +the program counter, the author of the language interpreter needs to mark the +relevant variables of the language interpreter with the help of a \emph{hint}. +The tracing interpreter will then effectively add the values of these variables +to the position key. This means, that the loop will only be considered to be +closed, if these variables that are making up program counter at the language +interpreter level are the same a second time. Such a loop is a loop of the user +program. The program counter of the language interpreter can only be the same a +second time after an instruction in the user program sets it to an earlier +value. This happens only at backward jumps in the language interpreter. That +means that the tracing interpreter needs to check for a closed loop only when it +encounters a backward jump in the language interpreter. Again the tracing JIT +cannot known where the backward branch is located, so it needs to be told with +the help of a hint by the author of the language interpreter. + +The condition for reusing already existing machine code needs to be adapted to +this new situation. In a classical tracing JIT there is at most one piece of +assembler code per loop of the jitted program, which in our case is the language +interpreter. When applying the tracing JIT to the language interpreter as +described so far, \emph{all} pieces of assembler code correspond to the bytecode +dispatch loop of the language interpreter. They correspond to different +unrollings and paths of that loop though. To figure out which of them to use +when trying to enter assembler code again, the program counter of the language +interpreter needs to be checked. If it corresponds to the position key of one of +the pieces of assembler code, then this assembler code can be entered. This +check again only needs to be performed at the backward branches of the language +interpreter. + +There is a similar conceptual problem about the point where tracing is started. +Tracing starts when the tracing interpreter sees one particular loop often +enough. This loop is always going to be the bytecode dispatch loop of the +language interpreter, so the tracing interpreter will start tracing all the +time. This is not sensible. It makes more sense to start tracing only if a +particular loop in the user program would be seen often enough. Thus we +need to change the lightweight profiling to identify the loops of the user +program. Therefore profiling is also done at the backward branches of the +language interpreter, using one counter per seen program counter of the language +interpreter. + +\begin{figure} +\input{code/tlr-paper-full.py} +\caption{Simple bytecode interpreter with hints applied} +\label{fig:tlr-full} +\end{figure} + +Let's look at which hints would need to be applied to the example interpreter +from Figure \ref{fig:tlr-basic}. The basic thing needed to apply hints is a +subclass of \texttt{JitDriver} that lists all the variables of the bytecode +loop. The variables are classified into two groups, red variables and green +variables. The green variables are those that the tracing JIT should consider to +be part of the program counter of the language interpreter. In the case of the +example, the \texttt{pc} variable is obviously part of the program counter. +However, the \texttt{bytecode} variable is also counted as green, since the +\texttt{pc} variable is meaningless without the knowledge of which bytecode +string is currently being interpreted. All other variables are red. + +In addition to the classification of the variables, there are two methods of +\texttt{JitDriver} that need to be called. Both of them get as arguments the +current values of the variables listed in the definition of the driver. The +first one is \texttt{jit\_merge\_point} which needs to be put at the beginning +of the body of the bytecode dispatch loop. The other, more interesting one, is +\texttt{can\_enter\_jit}. This method needs to be called at the end of any +instruction that can set the program counter of the language interpreter to an +earlier value. For the example this is only the \texttt{JUMP\_IF\_A} +instruction, and only if it is actually a backward jump. The place where this +method is called is where the language interpreter performs profiling to decide +when to start tracing. It is also the place where the tracing JIT checks +whether a loop is closed. This is considered to be the case when the values of +the "green" variables are the same as at an earlier call to the +\texttt{can\_enter\_jit} method. + +For the small example the hints look like a lot of work. However, the amount of +hints is essentially constant no matter how large the interpreter is, which +makes it seem less significant for larger interpreters. + +When executing the Square function of Figure \ref{fig:square}, the profiling +will identify the loop in the square function to be hot, and start tracing. It +traces the execution of the interpreter running the loop of the square function +for one iteration, thus unrolling the interpreter loop of the example +interpreter eight times. The resulting trace can be seen in Figure +\ref{fig:trace-no-green-folding}. + +\begin{figure} +\input{code/no-green-folding.txt} +\caption{Trace when executing the Square function of Figure \ref{fig:square}, +with the corresponding bytecodes as comments.} +\label{fig:trace-no-green-folding} +\end{figure} + +XXX summarize at which points the tracing interpreter needed changing +XXX all changes only to the position key and when to enter/leave the tracer! +XXX tracing remains essentially the same + +\subsection{Improving the Result} + +The critical problem of tracing the execution of just one bytecode has been +solved, the loop corresponds exactly to the loop in the square function. +However, the resulting trace is a bit too long. Most of its operations are not +actually doing any computation that is part of the square function. Instead, +they manipulate the data structures of the language interpreter. While this is +to be expected, given that the tracing interpreter looks at the execution of the +language interpreter, it would still be nicer if some of these operations could +be removed. + +The simple insight how to greatly improve the situation is that most of the +operations in the trace are actually concerned with manipulating the +bytecode and the program counter. Those are stored in variables that are part of +the position key (they are "green"), that means that the tracer checks that they +are some fixed value at the beginning of the loop. In the example the check +would be that the \texttt{bytecode} variable is the bytecode string +corresponding to the square function and that the \texttt{pc} variable is +\texttt{4}. Therefore it is possible to constant-fold computations on them away, +as long as the operations are side-effect free. Since strings are immutable in +Python, it is possible to constant-fold the \texttt{strgetitem} operation. The +\texttt{int\_add} operations can be folded anyway. + +With this optimization enabled, the trace looks as in Figure +\ref{fig:trace-full}. Now a lot of the language interpreter is actually gone +from the trace and what is left corresponds very closely to the loop of the +square function. The only vestige of the language interpreter is the fact that +the register list is still used to store the state of the computation. This +could be removed by some other optimization, but is maybe not really all that +bad anyway (in fact we have an experimental optimization that does exactly that, +but it is not finished). + +\begin{figure} +\input{code/full.txt} +\caption{Trace when executing the Square function of Figure \ref{fig:square}, +with the corresponding bytecodes as comments. The constant-folding of operations +on green variables is enabled.} +\label{fig:trace-full} +\end{figure} + + + +%- problem: typical bytecode loops don't follow the general assumption of tracing +%- needs to unroll bytecode loop +% - how often to unroll +% - when to start tracing? +% - unroll exactly so that unrolled loop corresponds to loop of the user +% program +%- how to improve matters: introducing merge keys +%- constant-folding of operations on green things +% - similarities to BTA of partial evaluation + +\section{Implementation Issues} +\label{sect:implementation} + +In this section we will describe some of the practical issues when implementing +the scheme described in the last section in PyPy. In particular we will describe +some of the problems of integrating the various parts with each other. + +The first integration problem is how to \emph{not} integrate the tracing JIT at +all. It should be possible to choose when the interpreter is translated to C +whether the JIT should be built in or not. If the JIT is not enabled, all the +hints that are possibly in the interpreter source are just ignored by the +translation process. In this way, the result of the translation is identical to +as if no hints were present in the interpreter at all. + +If the JIT is enabled, things are more interesting. A classical tracing JIT will +interpret the program it is running until a common loop is identified, at which +point tracing and ultimately assembler generation starts. The tracing JIT in +PyPy is operating on the language interpreter, which is written in RPython. But +RPython programs are translatable to C. This means that interpreting the +language interpreter before a common loop is found is clearly not desirable, +since the overhead of this double-interpretation would be significantly too big +to be practical. + +What is done instead is that the language interpreter keeps running as a C +program, until a common loop in the user program is found. To identify loops the +C version of the language interpreter is generated in such a way that at the +place that corresponds to the \texttt{can\_enter\_jit} hint profiling is +performed using the program counter of the language interpreter. Apart from this +bit of profiling, the language interpreter behaves in just the same way as +without a JIT. + +When a hot loop in the user program is identified, tracing is started. The +tracing interpreter is invoked to start tracing the language interpreter that is +running the user program. Of course the tracing interpreter cannot actually +trace the execution of the C representation of the language interpreter. Instead +it takes the state of the execution of the language interpreter and starts +tracing using a bytecode representation of the language interpreter. That means +there are two "versions" of the language interpreter embedded in the final +executable of the VM: On the one hand it is there as executable machine code, on +the other hand as bytecode for the tracing interpreter. It also means that +tracing is costly as it incurs exactly a double interpretation overhead. + +From then on things proceed like described in Section \ref{sect:tracing}. The +tracing interpreter tries to find a loop in the user program, if it found one it +will produce machine code for that loop and this machine code will be +immediately executed. The machine code is executed until a guard fails. Then the +execution should fall back to normal interpretation by the language interpreter. +This falling back is possibly a complex process, since the guard failure can +have occurred arbitrarily deep in a helper function of the language interpreter, +which would make it hard to rebuild the state of the language interpreter and +let it run from that point (e.g. this would involve building a potentially deep +C stack). Instead the falling back is achieved by a special \emph{fallback +interpreter} which runs the language interpreter and the user program from the +point of the guard failure. The fallback interpreter is essentially a variant of +the tracing interpreter that does not keep a trace. The fallback interpreter +runs until execution reaches a safe point where it is easy to let the C version +of the language interpreter resume its operation. Usually this means that the +fallback interpreter executes at most one bytecode operation of the language +interpreter. After the language interpreter takes over again, the whole process +starts again. + +\subsection{Various Issues} + +This section will hint at some other implementation issues and optimizations +that we have done that are beyond the scope of this paper (and will be subject +of a later publication). + +\textbf{Assembler Backends:} The tracing interpreter uses a well-defined +interface to an assembler backend for code generation. This makes it possible to +easily port the tracing JIT to various architectures (including, we hope, to +virtual machines such as the JVM where backend could generate bytecode at +runtime). + +\textbf{Trace Trees:} This paper ignored the problem of guards that fail in a +large percentage of cases because there are several equally likely paths through +a loop. This of course is not always practicable. Therefore we also start +tracing from guards that failed many times and produce assembler code for that +path, instead of always falling back to interpretation. + +\textbf{Allocation Removal:} A key optimization for making the approach +produce good code for more complex dynamic language is to perform escape +analysis on the loop operation after tracing has been performed. In this way all +objects that are allocated during the loop and don't actually escape the loop do +not need to be allocated on the heap at all but can be exploded into their +respective fields. This is very helpful for dynamic languages where primitive +types are often boxed, as the constant allocation of intermediate results is +very costly. + +\textbf{Optimizing Frame Objects:} One problem with the removal of allocations +is that many dynamic languages are so reflective that they allow the +introspection of the frame object that the interpreter uses to store local +variables (e.g. SmallTalk, Python). This means that intermediate results always +escape because they are stored into the frame object, rendering the allocation +removal optimization ineffective. To remedy this problem we make it possible to +update the frame object lazily only when it is actually accessed from outside of +the code generated by the JIT. + +\section{Evaluation} + +\label{sect:evaluation} +%- benchmarks +% - running example +% - gameboy? + +\section{Related Work} + +% dynamorio stuff +% partial evaluation +% XXX + +\section{Conclusion and Next Steps} + +%\begin{verbatim} +%- next steps: +% - Apply to other things, like smalltalk +%- conclusions +% - advantages + disadvantages in the meta-level approach +% - advantages are that the complex operations that occur in dynamic languages +% are accessible to the tracer +\cite{bolz_back_2008} +\cite{Psyco} + +\bigskip + +\bibliographystyle{abbrv} +\bibliography{paper} + +\end{document} From arigo at codespeak.net Tue Mar 31 13:02:53 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 13:02:53 +0200 (CEST) Subject: [pypy-svn] r63444 - in pypy/branch/pyjitpl5-loop/pypy/jit: backend/llgraph metainterp Message-ID: <20090331110253.F187716846A@codespeak.net> Author: arigo Date: Tue Mar 31 13:02:50 2009 New Revision: 63444 Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py Log: More in-progress stuff... Modified: pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/backend/llgraph/runner.py Tue Mar 31 13:02:50 2009 @@ -83,6 +83,7 @@ back to execute_operations()). """ c = llimpl.compile_start() + loop._compiled_version = c var2index = self._get_loop_args(c, loop) self._compile_branch(c, loop.operations, var2index, rop.JUMP) return c @@ -111,7 +112,7 @@ def _compile_branch(self, c, operations, var2index, expected_end): for op in operations: llimpl.compile_add(c, op.opnum) - if op.descr is not None: + if isinstance(op.descr, Descr): llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type) for x in op.args: if isinstance(x, history.Box): Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/compile.py Tue Mar 31 13:02:50 2009 @@ -103,29 +103,19 @@ def compile_fresh_loop(metainterp, old_loops): history = metainterp.history - old_loop = optimize.optimize_loop(metainterp.options, old_loops, - history, metainterp.cpu) - if old_loop is not None: - return old_loop loop = create_empty_loop(metainterp) loop.inputargs = history.inputargs - loop.specnodes = history.specnodes loop.operations = history.operations loop.operations[-1].jump_target = loop - mark_keys_in_loop(loop, loop.operations) + old_loop = optimize.optimize_loop(metainterp.options, old_loops, + loop, metainterp.cpu) + if old_loop is not None: + return old_loop send_loop_to_backend(metainterp, loop) metainterp.stats.loops.append(loop) old_loops.append(loop) return loop -def mark_keys_in_loop(loop, operations): - for op in operations: - if op.is_guard(): - mark_keys_in_loop(loop, op.suboperations) - op = operations[-1] - if op.opnum == rop.FAIL: - op.key.loop = loop - def send_loop_to_backend(metainterp, loop): metainterp.cpu.compile_loop(loop) metainterp.stats.compiled_count += 1 @@ -138,6 +128,8 @@ #temp = TreeLoop('temp') #temp.operations = metainterp.history.operations #metainterp.stats.view(extraloops=[temp]) + history = metainterp.history + xxx target_loop = optimize.optimize_bridge(metainterp.options, old_loops, metainterp.history, metainterp.cpu) if target_loop is None: Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/history.py Tue Mar 31 13:02:50 2009 @@ -403,11 +403,19 @@ if op.is_guard(): _list_all_operations(result, op.suboperations, omit_fails) + +class ResumeDescr(AbstractDescr): + def __init__(self, guard_op, resume_info, history, history_guard_index): + self.resume_info = resume_info + self.guard_op = guard_op + self.counter = 0 + self.history = history + self.history_guard_index = history_guard_index + # ____________________________________________________________ class RunningMatcher(object): - specnodes = None def __init__(self, cpu): self.cpu = cpu self.inputargs = None Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/optimize.py Tue Mar 31 13:02:50 2009 @@ -192,7 +192,10 @@ if self.virtualized: flags += 'V' return "" % (self.source, flags) -def optimize_loop(options, old_loops, history, cpu=None): +# ____________________________________________________________ + + +def optimize_loop(options, old_loops, loop, cpu=None): if not options.specialize: # for tests only if old_loops: return old_loops[0] @@ -200,7 +203,7 @@ return None # This does "Perfect specialization" as per doc/jitpl5.txt. - perfect_specializer = PerfectSpecializer(history, options, cpu) + perfect_specializer = PerfectSpecializer(loop, options, cpu) perfect_specializer.find_nodes() perfect_specializer.intersect_input_and_output() for old_loop in old_loops: @@ -209,12 +212,26 @@ perfect_specializer.optimize_loop() return None +def optimize_bridge(options, loop, history, cpu=None): + if not options.specialize: # for tests only + return old_loops[0] + + perfect_specializer = PerfectSpecializer(history, options, cpu) + perfect_specializer.find_nodes() + for old_loop in old_loops: + if perfect_specializer.match(old_loop): + perfect_specializer.optimize_loop() + return old_loop + return None # no loop matches + +# ____________________________________________________________ + class PerfectSpecializer(object): _allow_automatic_node_creation = False - def __init__(self, history, options=Options(), cpu=None): - self.history = history + def __init__(self, loop, options=Options(), cpu=None): + self.loop = loop self.options = options self.cpu = cpu self.nodes = {} @@ -274,14 +291,14 @@ def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True - if self.history.inputargs is not None: - for box in self.history.inputargs: + if self.loop.inputargs is not None: + for box in self.loop.inputargs: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) else: self._allow_automatic_node_creation = True # - for op in self.history.operations: + for op in self.loop.operations: #print '| ' + op.repr() opnum = op.opnum if opnum == rop.JUMP: @@ -389,15 +406,15 @@ self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): - end_args = self.history.operations[-1].args - assert len(self.history.inputargs) == len(end_args) + end_args = self.loop.operations[-1].args + assert len(self.loop.inputargs) == len(end_args) memo = {} for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): self.nodes[end_box].escape_if_startbox(memo, self.cpu) for i in range(len(end_args)): - box = self.history.inputargs[i] + box = self.loop.inputargs[i] other_box = end_args[i] if isinstance(other_box, Box): self.nodes[box].add_to_dependency_graph(self.nodes[other_box], @@ -415,11 +432,11 @@ def intersect_input_and_output(self): # Step (3) self.recursively_find_escaping_values() - jump = self.history.operations[-1] + jump = self.loop.operations[-1] assert jump.opnum == rop.JUMP specnodes = [] - for i in range(len(self.history.inputargs)): - enternode = self.nodes[self.history.inputargs[i]] + for i in range(len(self.loop.inputargs)): + enternode = self.nodes[self.loop.inputargs[i]] leavenode = self.getnode(jump.args[i]) specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes @@ -588,13 +605,13 @@ self._allow_automatic_node_creation = False newoperations = [] exception_might_have_happened = False - if self.history.inputargs is not None: + if self.loop.inputargs is not None: # closing a loop - assert len(self.history.inputargs) == len(self.specnodes) + assert len(self.loop.inputargs) == len(self.specnodes) for i in range(len(self.specnodes)): - box = self.history.inputargs[i] + box = self.loop.inputargs[i] self.specnodes[i].mutate_nodes(self.nodes[box]) - newinputargs = self.expanded_version_of(self.history.inputargs, + newinputargs = self.expanded_version_of(self.loop.inputargs, None) else: # making a bridge @@ -604,7 +621,7 @@ assert not node.virtual newinputargs = None # - for op in self.history.operations: + for op in self.loop.operations: opnum = op.opnum if opnum == rop.JUMP: args = self.expanded_version_of(op.args, newoperations) @@ -764,9 +781,9 @@ self.nodes[box] = instnode newoperations.append(op) # - self.history.specnodes = self.specnodes - self.history.inputargs = newinputargs - self.history.operations = newoperations + self.loop.specnodes = self.specnodes + self.loop.inputargs = newinputargs + self.loop.operations = newoperations # def cleanup_field_caches(self, newoperations): # # we need to invalidate everything Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 13:02:50 2009 @@ -651,8 +651,9 @@ if box is not None: extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opnum, extraargs, None) - op = history.ResOperation(rop.FAIL, liveboxes, None) - op.key = ResumeKey(guard_op, resume_info) + resumedescr = history.ResumeDescr(guard_op, resume_info, + self.metainterp.history, len(self.metainterp.history.operations)-1) + op = history.ResOperation(rop.FAIL, liveboxes, None, descr=resumedescr) guard_op.suboperations = [op] self.pc = saved_pc return guard_op @@ -829,7 +830,8 @@ def handle_guard_failure(self, guard_failure): self.initialize_state_from_guard_failure(guard_failure) - key = guard_failure.key + key = guard_failure.descr + assert isinstance(key, history.ResumeDescr) try: if key.guard_op.opnum in (rop.GUARD_NO_EXCEPTION, rop.GUARD_EXCEPTION): @@ -929,16 +931,18 @@ def initialize_state_from_guard_failure(self, guard_failure): # guard failure: rebuild a complete MIFrame stack - if self.state.must_compile_from_failure(guard_failure.key): + resumedescr = guard_failure.descr + assert isinstance(resumedescr, history.ResumeDescr) + if self.state.must_compile_from_failure(resumedescr): self.history = history.History(self.cpu) - suboperations = guard_failure.key.guard_op.suboperations + suboperations = resumedescr.guard_op.suboperations for i in range(len(suboperations)-1): self.history.operations.append(suboperations[i]) else: self.history = history.BlackHole(self.cpu) # the BlackHole is invalid because it doesn't start with # guard_failure.key.guard_op.suboperations, but that's fine - self.rebuild_state_after_failure(guard_failure.key.resume_info, + self.rebuild_state_after_failure(resumedescr.resume_info, guard_failure.args) def handle_exception(self): @@ -991,10 +995,3 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args - -class ResumeKey(object): - def __init__(self, guard_op, resume_info): - self.resume_info = resume_info - self.guard_op = guard_op - self.counter = 0 - # self.loop = ... set in compile.py Modified: pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-loop/pypy/jit/metainterp/resoperation.py Tue Mar 31 13:02:50 2009 @@ -5,9 +5,6 @@ # for 'jump': points to the target loop jump_target = None - # for 'fail' - key = None - # for 'guard_*' suboperations = None @@ -34,7 +31,6 @@ def clone(self): res = ResOperation(self.opnum, self.args, self.result, self.descr) res.jump_target = self.jump_target - res.key = self.key res.vdesc = self.vdesc return res From arigo at codespeak.net Tue Mar 31 14:14:24 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 14:14:24 +0200 (CEST) Subject: [pypy-svn] r63445 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090331121424.2C288168441@codespeak.net> Author: arigo Date: Tue Mar 31 14:14:22 2009 New Revision: 63445 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Log: Print more logs. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 14:14:22 2009 @@ -800,7 +800,7 @@ return resbox execute_and_record._annspecialcase_ = 'specialize:arg(1)' - def interpret(self): + def _interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, # a ContinueRunningNormally, or a GenerateMergePoint exception. if isinstance(self.history, history.BlackHole): @@ -820,6 +820,18 @@ else: debug_print('~~~ LEAVE', text) + def interpret(self): + if we_are_translated(): + self._interpret() + else: + try: + self._interpret() + except: + import sys + if sys.exc_info()[0] is not None: + history.log.info(sys.exc_info()[0].__name__) + raise + def compile_and_run_once(self, *args): orig_boxes = self.initialize_state_from_start(*args) try: @@ -858,7 +870,8 @@ box1 = original_boxes[i] box2 = live_arg_boxes[i] if not box1.equals(box2): - # not a valid loop + if not we_are_translated(): + history.log.info('not a valid loop at all') raise self.ContinueRunningNormally(live_arg_boxes) self.history.inputargs = original_boxes[num_green_args:] greenkey = original_boxes[:num_green_args] @@ -866,6 +879,8 @@ self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) loop = compile_new_loop(self, old_loops) if not loop: + if not we_are_translated(): + history.log.info('compile_new_loop() returned None') raise self.ContinueRunningNormally(live_arg_boxes) if not we_are_translated(): loop._call_history = self._debug_history @@ -879,10 +894,14 @@ old_loops = self.compiled_merge_points[greenkey] except KeyError: target_loop = None + if not we_are_translated(): + history.log.info('no loop seen so far with this green key') else: self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) target_loop = compile_new_bridge(self, old_loops, key) + if not we_are_translated() and target_loop is None: + history.log.info('compile_new_bridge() returned None') if target_loop is None: raise self.ContinueRunningNormally(live_arg_boxes) if not we_are_translated(): From arigo at codespeak.net Tue Mar 31 14:26:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 14:26:46 +0200 (CEST) Subject: [pypy-svn] r63446 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090331122646.042A5168418@codespeak.net> Author: arigo Date: Tue Mar 31 14:26:46 2009 New Revision: 63446 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Log: Another piece of information. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 14:26:46 2009 @@ -833,6 +833,8 @@ raise def compile_and_run_once(self, *args): + if not we_are_translated(): + history.log.info('Switching from interpreter to compiler') orig_boxes = self.initialize_state_from_start(*args) try: self.interpret() From igorto at codespeak.net Tue Mar 31 14:48:20 2009 From: igorto at codespeak.net (igorto at codespeak.net) Date: Tue, 31 Mar 2009 14:48:20 +0200 (CEST) Subject: [pypy-svn] r63447 - pypy/branch/igorto Message-ID: <20090331124820.C1087168444@codespeak.net> Author: igorto Date: Tue Mar 31 14:48:18 2009 New Revision: 63447 Added: pypy/branch/igorto/ - copied from r63446, pypy/trunk/ Log: create new branch From antocuni at codespeak.net Tue Mar 31 15:25:24 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 31 Mar 2009 15:25:24 +0200 (CEST) Subject: [pypy-svn] r63448 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331132524.D4F0216847A@codespeak.net> Author: antocuni Date: Tue Mar 31 15:25:22 2009 New Revision: 63448 Modified: pypy/extradoc/talk/icooolps2009/paper.bib pypy/extradoc/talk/icooolps2009/paper.tex Log: finished the review of the paper until section 3.1 (excluded) Modified: pypy/extradoc/talk/icooolps2009/paper.bib ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.bib (original) +++ pypy/extradoc/talk/icooolps2009/paper.bib Tue Mar 31 15:25:22 2009 @@ -158,3 +158,15 @@ year = {2004}, pages = {15--26} } + + at InProceedings{AACM-DLS07, + Author = {Ancona, D. and Ancona, M. and Cuni, A and Matsakis, N.}, + Title = {R{P}ython: a {S}tep {T}owards {R}econciling + {D}ynamically and {S}tatically {T}yped {OO} {L}anguages}, + BookTitle = {O{OPSLA} 2007 {P}roceedings and {C}ompanion, {DLS}'07: + {P}roceedings of the 2007 {S}ymposium on {D}ynamic + {L}anguages}, + Pages = {53--64}, + Publisher = {ACM}, + year = 2007 +} Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 15:25:22 2009 @@ -3,6 +3,26 @@ \usepackage{ifthen} \usepackage{fancyvrb} \usepackage{color} +\usepackage{ulem} + +\newboolean{showcomments} +\setboolean{showcomments}{true} +\ifthenelse{\boolean{showcomments}} + {\newcommand{\nb}[2]{ + \fbox{\bfseries\sffamily\scriptsize#1} + {\sf\small$\blacktriangleright$\textit{#2}$\blacktriangleleft$} + } + \newcommand{\version}{\emph{\scriptsize$-$Id: main.tex 19055 2008-06-05 11:20:31Z cfbolz $-$}} + } + {\newcommand{\nb}[2]{} + \newcommand{\version}{} + } + +\newcommand\cfbolz[1]{\nb{CFB}{#1}} +\newcommand\anto[1]{\nb{ANTO}{#1}} +\newcommand\arigo[1]{\nb{AR}{#1}} +\newcommand{\commentout}[1]{} + \let\oldcite=\cite @@ -12,7 +32,7 @@ \title{Tracing the Meta-Level: PyPy's JIT Compiler} -\numberofauthors{2} +\numberofauthors{3} \author{ \alignauthor Carl Friedrich Bolz\\ \affaddr{Heinrich-Heine-Universit?t D?sseldorf}\\ @@ -22,6 +42,11 @@ \affaddr{D-40225 D?sseldorf}\\ \affaddr{Deutschland}\\ \email{cfbolz at gmx.de} +\alignauthor Antonio Cuni\\ + \affaddr{University of Genova}\\ + \affaddr{DISI}\\ + \affaddr{Italy}\\ + \email{cuni at disi.unige.it} \alignauthor Armin Rigo\\ \email{arigo at tunes.org} } @@ -75,7 +100,7 @@ other dynamic languages as well. The general approach is to implement an interpreter for the language in a subset of Python. This subset is chosen in such a way that programs in it can be compiled into various target environments, -such as C/Posix, the CLR or the JVM. The PyPy project is described in more +such as C/Posix, the CLI or the JVM. The PyPy project is described in more details in Section \ref{sect:pypy}. In this paper we discuss ongoing work in the PyPy project to improve the @@ -122,12 +147,17 @@ new Python interpreter in Python but has now extended its goals to be an environment where flexible implementation of dynamic languages can be written. To implement a dynamic language with PyPy, an interpreter for that language has -to be written in RPython. RPython ("Restricted Python") is a subset of Python +to be written in RPython \cite{AACM-DLS07}. RPython ("Restricted Python") is a subset of Python chosen in such a way that type inference can be performed on it. The language interpreter can then be translated with the help of PyPy into various target -environments, such as C/Posix, the CLR and the JVM. This is done by a component +environments, such as C/Posix, the CLI and the JVM. This is done by a component of PyPy called the \emph{translation toolchain}. + +\anto{XXX: are the following paragraphs really needed? I don't think this + details are needed in Section \ref{sect:implementation}. I would say + something much shorter, see below.} + The central idea of this way to implement VMs is that the interpreter implementation in RPython should be as free as possible of low-level implementation details, such as memory management strategy, threading model or @@ -158,6 +188,15 @@ than what would be produced after compilation to C. These low-level graphs are also what the tracing JIT takes as input, as we will see later. +\anto{By writing VMs in a high-level language, we keep the implementation of + the language free of low-level details such as memory management strategy, + threading model or object layout. These features are automatically added + during the translation process which consists in a series of steps, each + step transforming the representation of the program produced by the previous + one until we get the final executable. As we will see later, this internal + low-level representation of the program is also used as an input for the + tracing JIT.} + %- original goal: Python interpreter in Python %- general way to write flexible VMs for dynamic languages @@ -194,15 +233,16 @@ The code for those common loops however should be highly optimized, including aggressive inlining. -The generation of loops works as follows: At first, everything is interpreted. +\sout{The generation of loops works as follows: at first, everything is interpreted.} +\anto{At first, when the program starts, everything is interpreted.} The interpreter does a bit of lightweight profiling to figure out which loops are run often. This lightweight profiling is usually done by having a counter on each backward jump instruction that counts how often this particular backward jump was executed. Since loops need a backward jump somewhere, this method finds loops in the user program. -When a common loop is identified, the interpreter enters a -special mode (called tracing mode). When in tracing mode, the interpreter +When a \sout{common}\anto{hot} loop is identified, the interpreter enters a +special mode, called \emph{tracing mode}. When in tracing mode, the interpreter records a history (the \emph{trace}) of all the operations it executes, in addition to actually performing the operations. During tracing, the trace is repeatedly (XXX make this more precise: when does the check happen?) @@ -213,6 +253,12 @@ of all the operations in it. The machine code can then be immediately executed, as it represents exactly the loop that is being interpreted at the moment anyway. +\anto{XXX I think it's worth spending one more paragraph to explain what a + trace really is, i.e. that it's a list of \textbf{sequential} operations, + intermixed to guards which guarantee that this particular sequence is still + valid. At the moment, the definition of trace is not given explicitly and + it's mixed with the details of how the JIT work} + This process assumes that the path through the loop that was traced is a "typical" example of possible paths (which is statistically likely). Of course it is possible that later another path through the loop is taken, therefore the @@ -230,7 +276,7 @@ does not need to check all the time whether the position key already occurred earlier, but only at instructions that are able to change the position key to an earlier value, e.g. a backward branch instruction. Note that this is -already the second place where backward branches are treated specially: During +already the second place where backward branches are treated specially: during interpretation they are the place where the profiling is performed and where tracing is started or already existing assembler code entered; during tracing they are the place where the check for a closed loop is performed. From cfbolz at codespeak.net Tue Mar 31 16:15:28 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 31 Mar 2009 16:15:28 +0200 (CEST) Subject: [pypy-svn] r63449 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331141528.6B19B168471@codespeak.net> Author: cfbolz Date: Tue Mar 31 16:15:25 2009 New Revision: 63449 Modified: pypy/extradoc/talk/icooolps2009/paper.tex Log: accepted most of anto's changes Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 16:15:25 2009 @@ -153,49 +153,14 @@ environments, such as C/Posix, the CLI and the JVM. This is done by a component of PyPy called the \emph{translation toolchain}. - -\anto{XXX: are the following paragraphs really needed? I don't think this - details are needed in Section \ref{sect:implementation}. I would say - something much shorter, see below.} - -The central idea of this way to implement VMs is that the interpreter -implementation in RPython should be as free as possible of low-level -implementation details, such as memory management strategy, threading model or -object layout. Instead, these details are inserted into the VM during the -translation process by the translation toolchain. This makes it possible to -change these details later, if that becomes necessary. This is something that is -hard to do with a traditional VM written in a low-level language such as C, -since the low-level details need to be fixed early in the development-process. -XXX is this paragraph really needed? - -In the following we will describe some details of the translation process, since -they are needed in Section \ref{sect:implementation}. The first step is to produce -control flow graphs of all functions of the RPython program. Afterwards, type -inference is performed to gain type information about all the variables in the -flow graphs. Afterwards, the abstraction level of the operations in the graphs -is lowered in a stepwise fashion. At the end of this process, all operations in -the graphs correspond rather directly to a simple operation in C. The variables -are annotated with a C-like type system containing primitive types (like -\texttt{Signed}, \texttt{Bool}, etc.) or pointer types pointing to Structs, -Arrays or Functions. - -XXX example. reuse the one of the tracing jit? - -The translation process usually just turns these graphs into C code so that they -can be compiled into an executable. However, they can also be interpreted in -various ways. This is useful for testing and debugging the translation toolchain -because the produced error messages in case of a crash are a lot more helpful -than what would be produced after compilation to C. These low-level graphs are -also what the tracing JIT takes as input, as we will see later. - -\anto{By writing VMs in a high-level language, we keep the implementation of - the language free of low-level details such as memory management strategy, - threading model or object layout. These features are automatically added - during the translation process which consists in a series of steps, each - step transforming the representation of the program produced by the previous - one until we get the final executable. As we will see later, this internal - low-level representation of the program is also used as an input for the - tracing JIT.} +By writing VMs in a high-level language, we keep the implementation of the +language free of low-level details such as memory management strategy, +threading model or object layout. These features are automatically added +during the translation process which consists in a series of steps, each step +transforming the representation of the program produced by the previous one +until we get the final executable. As we will see later, this internal +low-level representation of the program is also used as an input for the +tracing JIT. %- original goal: Python interpreter in Python @@ -233,15 +198,14 @@ The code for those common loops however should be highly optimized, including aggressive inlining. -\sout{The generation of loops works as follows: at first, everything is interpreted.} -\anto{At first, when the program starts, everything is interpreted.} +At first, when the program starts, everything is interpreted. The interpreter does a bit of lightweight profiling to figure out which loops are run often. This lightweight profiling is usually done by having a counter on each backward jump instruction that counts how often this particular backward jump was executed. Since loops need a backward jump somewhere, this method finds loops in the user program. -When a \sout{common}\anto{hot} loop is identified, the interpreter enters a +When a hot loop is identified, the interpreter enters a special mode, called \emph{tracing mode}. When in tracing mode, the interpreter records a history (the \emph{trace}) of all the operations it executes, in addition to actually performing the operations. During tracing, the trace is repeatedly From antocuni at codespeak.net Tue Mar 31 16:36:21 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 31 Mar 2009 16:36:21 +0200 (CEST) Subject: [pypy-svn] r63450 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331143621.CCFDF168411@codespeak.net> Author: antocuni Date: Tue Mar 31 16:36:21 2009 New Revision: 63450 Modified: pypy/extradoc/talk/icooolps2009/paper.tex Log: more comments Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 16:36:21 2009 @@ -23,6 +23,7 @@ \newcommand\arigo[1]{\nb{AR}{#1}} \newcommand{\commentout}[1]{} +\normalem \let\oldcite=\cite @@ -308,13 +309,25 @@ (from the point of view of a VM author, the "user" is a programmer using the VM). -A tracing JIT compiler finds the hot loops of the program it is compiling. In +\anto{I find this para a bit confusing, but I don't really know how to improve + it. I try a rewriting, feel free to revert} + +\sout{A tracing JIT compiler finds the hot loops of the program it is compiling. In our case, this program is the language interpreter. The hot loop of the language interpreter is the bytecode dispatch loop. Usually it is also the only hot loop. -Tracing one iteration of this loop means that the execution of one bytecode was +Tracing one iteration of this loop means that the execution of one opcode was seen. This means that the resulting machine code will correspond to a loop, that -assumes that this particular bytecode will be executed many times in a row, -which is clearly very unlikely. +assumes that this particular opcode will be executed many times in a row, +which is clearly very unlikely.} + +\anto{Similarly, we need to distinguish two kind of loops: \emph{interpreter + loops} are loops \textbf{inside} the language interpreter (e.g., the + bytecode dispatch loop). \emph{User loops} are loops in the user program.} + +\anto{To improve the performances of the user programs, we need to find and + compile traces that correspond to user loops. The strategy described in + section \ref{sect:tracing} does not work well, as it only detects + interpreter loops, and in particular the bytecode dispatch one.} \begin{figure} \input{code/tlr-paper.py} @@ -351,13 +364,20 @@ \texttt{bytecode} argument is a string of bytes and all register and the accumulator are integers. A simple program for this interpreter that computes the square of the accumulator is shown in Figure \ref{fig:square}. If the -tracing interpreter traces the execution of the \texttt{DECR\_A} bytecode, the +tracing interpreter traces the execution of the \texttt{DECR\_A} opcode (whose integer value is 7), the trace would look as follows: \input{code/normal-tracing.txt} +\anto{ Because of the guard on \texttt{opcode0}, the code compiled from this + trace will be useful only when executing a \texttt{DECR\_A}. For all the + other operations the guard will fail, making the whole system probably + slower than without JIT.} + +% YYY: (anto) I reviewd until here + To improve this situation, the tracing JIT could trace the execution of several -bytecodes, thus effectively unrolling the bytecode dispatch loop. Ideally, the -bytecode loop should be unrolled exactly so much, that the unrolled version +opcodes, thus effectively unrolling the bytecode dispatch loop. Ideally, the +bytecode dispatch loop should be unrolled exactly so much, that the unrolled version corresponds to a loop on the level of the user program. A loop in the user program occurs when the program counter of the language interpreter has the same value many times. This program counter is typically one or several @@ -460,7 +480,7 @@ \subsection{Improving the Result} -The critical problem of tracing the execution of just one bytecode has been +The critical problem of tracing the execution of just one opcode has been solved, the loop corresponds exactly to the loop in the square function. However, the resulting trace is a bit too long. Most of its operations are not actually doing any computation that is part of the square function. Instead, @@ -493,7 +513,7 @@ \begin{figure} \input{code/full.txt} \caption{Trace when executing the Square function of Figure \ref{fig:square}, -with the corresponding bytecodes as comments. The constant-folding of operations +with the corresponding opcodes as comments. The constant-folding of operations on green variables is enabled.} \label{fig:trace-full} \end{figure} From cfbolz at codespeak.net Tue Mar 31 17:01:42 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 31 Mar 2009 17:01:42 +0200 (CEST) Subject: [pypy-svn] r63451 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331150142.268D616849C@codespeak.net> Author: cfbolz Date: Tue Mar 31 17:01:40 2009 New Revision: 63451 Modified: pypy/extradoc/talk/icooolps2009/paper.tex Log: Accepting one of Anto's changes, rejecting the rewrite: The problem with the rewrite was that it jumped to the conclusion of where the text gets to several paragraphs later. Instead, tried to rewrite it slightly to make it more clear. Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 17:01:40 2009 @@ -309,25 +309,18 @@ (from the point of view of a VM author, the "user" is a programmer using the VM). -\anto{I find this para a bit confusing, but I don't really know how to improve - it. I try a rewriting, feel free to revert} +Similarly, we need to distinguish loops at two different levels: +\emph{interpreter loops} are loops \emph{inside} the language interpreter. On +the other hand, \emph{user loops} are loops in the user program. -\sout{A tracing JIT compiler finds the hot loops of the program it is compiling. In +A tracing JIT compiler finds the hot loops of the program it is compiling. In our case, this program is the language interpreter. The hot loop of the language -interpreter is the bytecode dispatch loop. Usually it is also the only hot loop. -Tracing one iteration of this loop means that the execution of one opcode was -seen. This means that the resulting machine code will correspond to a loop, that -assumes that this particular opcode will be executed many times in a row, -which is clearly very unlikely.} - -\anto{Similarly, we need to distinguish two kind of loops: \emph{interpreter - loops} are loops \textbf{inside} the language interpreter (e.g., the - bytecode dispatch loop). \emph{User loops} are loops in the user program.} - -\anto{To improve the performances of the user programs, we need to find and - compile traces that correspond to user loops. The strategy described in - section \ref{sect:tracing} does not work well, as it only detects - interpreter loops, and in particular the bytecode dispatch one.} +interpreter is its bytecode dispatch loop. Usually that is is also the only hot +loop of the language interpreter. Tracing one iteration of this loop means that +the recorded trace corresponds to execution of one opcode. This means that the +assumption that the tracing JIT makes -- that several iterations of a hot loop +take the same or similar code paths -- is just wrong in this case. It is very +unlikely that the same particular opcode is executed many times in a row. \begin{figure} \input{code/tlr-paper.py} @@ -368,10 +361,10 @@ trace would look as follows: \input{code/normal-tracing.txt} -\anto{ Because of the guard on \texttt{opcode0}, the code compiled from this - trace will be useful only when executing a \texttt{DECR\_A}. For all the - other operations the guard will fail, making the whole system probably - slower than without JIT.} +Because of the guard on \texttt{opcode0}, the code compiled from this trace will +be useful only when executing a long series of \texttt{DECR\_A} opcodes. For all +the other operations the guard will fail, which will mean that performance is +probably not improved at all. % YYY: (anto) I reviewd until here From cfbolz at codespeak.net Tue Mar 31 17:06:43 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 31 Mar 2009 17:06:43 +0200 (CEST) Subject: [pypy-svn] r63452 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331150643.B44DF16849C@codespeak.net> Author: cfbolz Date: Tue Mar 31 17:06:40 2009 New Revision: 63452 Modified: pypy/extradoc/talk/icooolps2009/paper.tex Log: made this into a figure too Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 17:06:40 2009 @@ -357,15 +357,19 @@ \texttt{bytecode} argument is a string of bytes and all register and the accumulator are integers. A simple program for this interpreter that computes the square of the accumulator is shown in Figure \ref{fig:square}. If the -tracing interpreter traces the execution of the \texttt{DECR\_A} opcode (whose integer value is 7), the -trace would look as follows: -\input{code/normal-tracing.txt} - +tracing interpreter traces the execution of the \texttt{DECR\_A} opcode (whose +integer value is 7), the trace would look as in Figure \ref{fig:trace-normal}. Because of the guard on \texttt{opcode0}, the code compiled from this trace will be useful only when executing a long series of \texttt{DECR\_A} opcodes. For all the other operations the guard will fail, which will mean that performance is probably not improved at all. +\begin{figure} +\input{code/normal-tracing.txt} +\caption{Trace when executing the \texttt{DECR\_A} opcode} +\label{fig:trace-normal} +\end{figure} + % YYY: (anto) I reviewd until here To improve this situation, the tracing JIT could trace the execution of several From arigo at codespeak.net Tue Mar 31 17:44:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 17:44:49 +0200 (CEST) Subject: [pypy-svn] r63453 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090331154449.31BD51683F4@codespeak.net> Author: arigo Date: Tue Mar 31 17:44:47 2009 New Revision: 63453 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py Log: This is a partial revert of r63074. Instead of making the liveboxes list as compact as possible for each of the true and false cases, generate a single livebox list for both cases. This is needed for the following checkin. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py Tue Mar 31 17:44:47 2009 @@ -263,9 +263,6 @@ def make_bytecode_block(self, block): if block.exits == (): - # note: the same label might be generated multiple times, but a - # jump to this label is free to pick whichever target so it's fine - self.emit(label(block)) if len(block.inputargs) == 1: # return from function returnvar, = block.inputargs @@ -322,16 +319,19 @@ linkfalse, linktrue = block.exits if linkfalse.llexitcase == True: linkfalse, linktrue = linktrue, linkfalse - truelist = self.get_renaming_list(linktrue.args) - falselist = self.get_renaming_list(linkfalse.args) self.emit("goto_if_not", - self.var_position(block.exitswitch), - tlabel(linkfalse.target)) - self.emit(len(truelist), *truelist) - self.emit(len(falselist), *falselist) + tlabel(linkfalse), + self.var_position(block.exitswitch)) + self.minimize_variables(argument_only=True, exitswitch=False) + truerenaming = self.insert_renaming(linktrue.args) + falserenaming = self.insert_renaming(linkfalse.args) + # true path: + self.emit(*truerenaming) self.make_bytecode_block(linktrue.target) - if linkfalse.target not in self.seen_blocks: - self.make_bytecode_block(linkfalse.target) + # false path: + self.emit(label(linkfalse)) + self.emit(*falserenaming) + self.make_bytecode_block(linkfalse.target) else: self.minimize_variables() switches = [link for link in block.exits @@ -426,11 +426,12 @@ else: return ["make_new_vars_%d" % len(list)] + list - def minimize_variables(self): + def minimize_variables(self, argument_only=False, exitswitch=True): if self.dont_minimize_variables: + assert not argument_only return block, index = self.current_position - allvars = self.vars_alive_through_op(block, index) + allvars = self.vars_alive_through_op(block, index, exitswitch) seen = {} # {position: unique Variable} without Voids unique = {} # {Variable: unique Variable} without Voids for v in allvars: @@ -441,7 +442,12 @@ vars = seen.items() vars.sort() vars = [v1 for pos, v1 in vars] - self.emit(*self.insert_renaming(vars)) + if argument_only: + # only generate the list of vars as an arg in a complex operation + renaming_list = self.get_renaming_list(vars) + self.emit(len(renaming_list), *renaming_list) + else: + self.emit(*self.insert_renaming(vars)) self.free_vars = 0 self.var_positions.clear() for v1 in vars: @@ -449,7 +455,7 @@ for v, v1 in unique.items(): self.var_positions[v] = self.var_positions[v1] - def vars_alive_through_op(self, block, index): + def vars_alive_through_op(self, block, index, include_exitswitch=True): """Returns the list of variables that are really used by or after the operation at 'index'. """ @@ -468,7 +474,8 @@ for op in block.operations[index:]: for v in op.args: see(v) - see(block.exitswitch) + if include_exitswitch: + see(block.exitswitch) for link in block.exits: for v in link.args: if v not in (link.last_exception, link.last_exc_value): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 17:44:47 2009 @@ -176,6 +176,11 @@ count = self.load_int() return [self.load_const_arg() for i in range(count)] + def ignore_varargs(self): + count = self.load_int() + for i in range(count): + self.load_int() + def getvarenv(self, i): return self.env[i] @@ -279,25 +284,27 @@ def opimpl_goto(self, target): self.pc = target - @arguments("box", "jumptarget", "varargs", "varargs") - def opimpl_goto_if_not(self, box, target, truelist, falselist): + @arguments("orgpc", "jumptarget", "box", "varargs") + def opimpl_goto_if_not(self, pc, target, box, livelist): switchcase = box.getint() if switchcase: - currentpc = self.pc - currentenv = truelist - targetpc = target - targetenv = falselist opnum = rop.GUARD_TRUE else: - currentpc = target - currentenv = falselist - targetpc = self.pc - targetenv = truelist + self.pc = target opnum = rop.GUARD_FALSE - self.env = targetenv - self.generate_guard(targetpc, opnum, box) - self.pc = currentpc - self.env = currentenv + self.env = livelist + self.generate_guard(pc, opnum, box) + + def follow_jump(self): + self.pc += 1 # past the bytecode for 'goto_if_not' + target = self.load_3byte() # load the 'target' argument + self.pc = target # jump + + def dont_follow_jump(self): + self.pc += 1 # past the bytecode for 'goto_if_not' + self.load_3byte() # past the 'target' argument + self.load_int() # past the 'box' argument + self.ignore_varargs() # past the 'livelist' argument @arguments("orgpc", "box", "constargs", "jumptargets") def opimpl_switch(self, pc, valuebox, constargs, jumptargets): @@ -847,9 +854,7 @@ self.initialize_state_from_guard_failure(guard_failure) key = guard_failure.key try: - if key.guard_op.opnum in (rop.GUARD_NO_EXCEPTION, - rop.GUARD_EXCEPTION): - self.handle_exception() + self.prepare_resume_from_failure(key.guard_op.opnum) self.interpret() assert False, "should always raise" except GenerateMergePoint, gmp: @@ -866,6 +871,14 @@ gmp.argboxes[num_green_args:]) return (loop, residual_args) + def prepare_resume_from_failure(self, opnum): + if opnum == rop.GUARD_TRUE: # a goto_if_not that fails only now + self.framestack[-1].follow_jump() + elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops failing + self.framestack[-1].dont_follow_jump() + elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION: + self.handle_exception() + def compile(self, original_boxes, live_arg_boxes): num_green_args = self.num_green_args for i in range(num_green_args): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py Tue Mar 31 17:44:47 2009 @@ -152,8 +152,9 @@ for op in get_stats().loops[0]._all_operations(): if op.getopname() == 'fail': liveboxes = op.args - assert len(liveboxes) == 1 - assert isinstance(liveboxes[0], history.BoxInt) + assert len(liveboxes) == 3 + for box in liveboxes: + assert isinstance(box, history.BoxInt) found += 1 assert found == 1 From cfbolz at codespeak.net Tue Mar 31 17:57:46 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 31 Mar 2009 17:57:46 +0200 (CEST) Subject: [pypy-svn] r63454 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331155746.5A0161684B9@codespeak.net> Author: cfbolz Date: Tue Mar 31 17:57:45 2009 New Revision: 63454 Modified: pypy/extradoc/talk/icooolps2009/paper.tex Log: fix an XXX Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 17:57:45 2009 @@ -68,8 +68,6 @@ \end{abstract} -XXX write somewhere that we will be predominantly occupied with bytecode -interpreters XXX write somewhere that one problem of using tracing JITs for dynamic languages is that dynamic languages have very complex bytecodes @@ -304,10 +302,11 @@ terminology to distinguish them. On the one hand, there is the interpreter that the tracing JIT uses to perform tracing. This we will call the \emph{tracing interpreter}. On the other hand, there is the interpreter that is running the -users programs, which we will call the \emph{language interpreter}. The program -that the language interpreter executes we will call the \emph{user program} -(from the point of view of a VM author, the "user" is a programmer using the -VM). +users programs, which we will call the \emph{language interpreter}. In the +following, we will assume that the language interpreter is bytecode-based. The +program that the language interpreter executes we will call the \emph{user +program} (from the point of view of a VM author, the "user" is a programmer +using the VM). Similarly, we need to distinguish loops at two different levels: \emph{interpreter loops} are loops \emph{inside} the language interpreter. On From cfbolz at codespeak.net Tue Mar 31 18:03:53 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 31 Mar 2009 18:03:53 +0200 (CEST) Subject: [pypy-svn] r63455 - pypy/extradoc/talk/icooolps2009 Message-ID: <20090331160353.CAA5A16845E@codespeak.net> Author: cfbolz Date: Tue Mar 31 18:03:48 2009 New Revision: 63455 Modified: pypy/extradoc/talk/icooolps2009/paper.tex Log: kill XXX Modified: pypy/extradoc/talk/icooolps2009/paper.tex ============================================================================== --- pypy/extradoc/talk/icooolps2009/paper.tex (original) +++ pypy/extradoc/talk/icooolps2009/paper.tex Tue Mar 31 18:03:48 2009 @@ -229,7 +229,7 @@ If a guard fails during execution of the machine code, the machine code is left and execution falls back to using interpretation (there are more complex mechanisms in place to still produce more code for the cases of guard failures, -but they are of no importance for this paper XXX is that true?). +but they are of no importance for this paper). It is important to understand when the tracer considers a loop in the trace to be closed. This happens when the \emph{position key} is the same as at an earlier From arigo at codespeak.net Tue Mar 31 18:46:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 18:46:34 +0200 (CEST) Subject: [pypy-svn] r63456 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp Message-ID: <20090331164634.8BDFF168411@codespeak.net> Author: arigo Date: Tue Mar 31 18:46:31 2009 New Revision: 63456 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Log: Intermediate check-in: see comments in compile.compile_fresh_bridge(). Basically this adds the case described in loop.txt when compiling a bridge and it fails (typically because there is no loop that it can go to). Now instead of failing, the bridge is completed with operations from the old unoptimized loop, and the new (artifical) loop is compiled. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py Tue Mar 31 18:46:31 2009 @@ -96,7 +96,7 @@ def _compile_branch(self, c, operations, var2index): for op in operations: llimpl.compile_add(c, op.opnum) - if op.descr is not None: + if isinstance(op.descr, Descr): llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type) for x in op.args: if isinstance(x, history.Box): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 31 18:46:31 2009 @@ -5,7 +5,7 @@ from pypy.conftest import option from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.history import TreeLoop, log, Box +from pypy.jit.metainterp.history import TreeLoop, log, Box, History from pypy.jit.metainterp import optimize @@ -14,11 +14,7 @@ to the first operation. """ if we_are_translated(): - try: - loop = compile_fresh_loop(metainterp, old_loops) - return loop - except optimize.CancelInefficientLoop: - return None + return compile_fresh_loop(metainterp, old_loops) else: return _compile_new_loop_1(metainterp, old_loops) @@ -27,12 +23,7 @@ to some existing place. """ if we_are_translated(): - try: - target_loop = compile_fresh_bridge(metainterp, old_loops, - resumekey) - return target_loop - except optimize.CancelInefficientLoop: - return None + return compile_fresh_bridge(metainterp, old_loops, resumekey) else: return _compile_new_bridge_1(metainterp, old_loops, resumekey) @@ -42,40 +33,30 @@ # the following is not translatable def _compile_new_loop_1(metainterp, old_loops): + old_loops_1 = old_loops[:] try: - old_loops_1 = old_loops[:] - try: - loop = compile_fresh_loop(metainterp, old_loops) - except Exception, exc: - show_loop(metainterp, error=exc) - raise + loop = compile_fresh_loop(metainterp, old_loops) + except Exception, exc: + show_loop(metainterp, error=exc) + raise + else: + if loop in old_loops_1: + log.info("reusing loop at %r" % (loop,)) else: - if loop in old_loops_1: - log.info("reusing loop at %r" % (loop,)) - else: - show_loop(metainterp, loop) - except optimize.CancelInefficientLoop: - return None + show_loop(metainterp, loop) loop.check_consistency() return loop def _compile_new_bridge_1(metainterp, old_loops, resumekey): try: - try: - target_loop = compile_fresh_bridge(metainterp, old_loops, - resumekey) - except Exception, exc: - show_loop(metainterp, error=exc) - raise - else: - if target_loop is None: - log.info("compile_fresh_bridge() returned None") - else: - show_loop(metainterp, target_loop) - except optimize.CancelInefficientLoop: - return None - if target_loop is not None: - target_loop.check_consistency() + target_loop = compile_fresh_bridge(metainterp, old_loops, + resumekey) + except Exception, exc: + show_loop(metainterp, error=exc) + raise + else: + show_loop(metainterp, target_loop) + target_loop.check_consistency() return target_loop def show_loop(metainterp, loop=None, error=None): @@ -88,9 +69,10 @@ else: errmsg = None if loop is None: - metainterp.stats.view(errmsg=errmsg) + extraloops = [] else: - loop.show(errmsg=errmsg) + extraloops = [loop] + metainterp.stats.view(errmsg=errmsg, extraloops=extraloops) def create_empty_loop(metainterp): if we_are_translated(): @@ -103,37 +85,28 @@ def compile_fresh_loop(metainterp, old_loops): history = metainterp.history - old_loop = optimize.optimize_loop(metainterp.options, old_loops, - history, metainterp.cpu) - if old_loop is not None: - return old_loop loop = create_empty_loop(metainterp) loop.inputargs = history.inputargs - loop.specnodes = history.specnodes loop.operations = history.operations loop.operations[-1].jump_target = loop - mark_keys_in_loop(loop, loop.operations) + old_loop = optimize.optimize_loop(metainterp.options, old_loops, + loop, metainterp.cpu) + if old_loop is not None: + return old_loop + history.source_link = loop send_loop_to_backend(metainterp, loop, True) metainterp.stats.loops.append(loop) old_loops.append(loop) return loop -def mark_keys_in_loop(loop, operations): - for op in operations: - if op.is_guard(): - mark_keys_in_loop(loop, op.suboperations) - op = operations[-1] - if op.opnum == rop.FAIL: - op.key.loop = loop - def send_loop_to_backend(metainterp, loop, is_loop): metainterp.cpu.compile_operations(loop) metainterp.stats.compiled_count += 1 if not we_are_translated(): if is_loop: - log.info("compiling new loop") + log.info("compiled new loop") else: - log.info("compiling new bridge") + log.info("compiled new bridge") # ____________________________________________________________ @@ -141,18 +114,74 @@ pass def compile_fresh_bridge(metainterp, old_loops, resumekey): - #temp = TreeLoop('temp') - #temp.operations = metainterp.history.operations - #metainterp.stats.view(extraloops=[temp]) - target_loop = optimize.optimize_bridge(metainterp.options, old_loops, - metainterp.history, metainterp.cpu) - if target_loop is None: - return None - source_loop = resumekey.loop - guard_op = resumekey.guard_op - guard_op.suboperations = metainterp.history.operations - op = guard_op.suboperations[-1] - op.jump_target = target_loop - mark_keys_in_loop(source_loop, guard_op.suboperations) - send_loop_to_backend(metainterp, source_loop, False) - return target_loop + # The history contains new operations to attach as the code for the + # failure of 'resumekey.guard_op'. First, we find the TreeLoop object + # that contains this guard operation. + source_loop = resumekey.history.source_link + while not isinstance(source_loop, TreeLoop): + source_loop = source_loop.source_link + # Attempt to use optimize_bridge(). This may return None in case + # it does not work -- i.e. none of the existing old_loops match. + temploop = create_empty_loop(metainterp) + temploop.operations = metainterp.history.operations + if len(old_loops) > 0: + target_loop = optimize.optimize_bridge(metainterp.options, old_loops, + temploop, metainterp.cpu) + else: + target_loop = None + # Did it work? + if target_loop is not None: + # Yes, we managed to create just a bridge. Attach the new operations + # to the existing source_loop and recompile the whole thing. + metainterp.history.source_link = resumekey.history + metainterp.history.source_guard_index = resumekey.history_guard_index + guard_op = resumekey.guard_op + if guard_op.jump_target is not None: # should always be the case + guard_op = guard_op.jump_target + guard_op.suboperations = temploop.operations + op = guard_op.suboperations[-1] + op.jump_target = target_loop + send_loop_to_backend(metainterp, source_loop, False) + return target_loop + else: + # No. In this case, we prepend to the history the unoptimized + # operations coming from the loop, in order to make a (fake) complete + # unoptimized trace. Then we can just compile this loop normally. + if not we_are_translated(): + log.info("completing the bridge into a stand-alone loop") + metainterp.history.operations = [] + append_full_operations(metainterp.history, + resumekey.history, + resumekey.history_guard_index) + metainterp.history.operations.extend(temploop.operations) + return compile_fresh_loop(metainterp, old_loops) + + +def append_full_operations(history, sourcehistory, guard_index): + prev = sourcehistory.source_link + if isinstance(prev, History): + append_full_operations(history, prev, sourcehistory.source_guard_index) + else: + assert history.inputargs is None + assert sourcehistory.inputargs is not None + history.inputargs = sourcehistory.inputargs + history.operations.extend(sourcehistory.operations[:guard_index]) + op = inverse_guard(sourcehistory.operations[guard_index]) + history.operations.append(op) + +def inverse_guard(guard_op): + suboperations = guard_op.suboperations + assert guard_op.is_guard() + if guard_op.opnum == rop.GUARD_TRUE: + guard_op = ResOperation(rop.GUARD_FALSE, guard_op.args, None) + elif guard_op.opnum == rop.GUARD_FALSE: + guard_op = ResOperation(rop.GUARD_TRUE, guard_op.args, None) + else: + # XXX other guards have no inverse so far + raise InverseTheOtherGuardsPlease(op) + # + guard_op.suboperations = suboperations + return guard_op + +class InverseTheOtherGuardsPlease(Exception): + pass Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py Tue Mar 31 18:46:31 2009 @@ -12,12 +12,12 @@ def get_display_text(self): return None -def display_loops(loops, errmsg=None): - graphs = loops[:] - for graph in graphs: +def display_loops(loops, errmsg=None, highlight_loops=()): + graphs = [(loop, loop in highlight_loops) for loop in loops] + for graph, highlight in graphs: for op in graph.get_operations(): if op.is_guard(): - graphs.append(SubGraph(op.suboperations)) + graphs.append((SubGraph(op.suboperations), highlight)) graphpage = ResOpGraphPage(graphs, errmsg) graphpage.display() @@ -26,8 +26,8 @@ def compute(self, graphs, errmsg=None): resopgen = ResOpGen() - for graph in graphs: - resopgen.add_graph(graph) + for graph, highlight in graphs: + resopgen.add_graph(graph, highlight) if errmsg: resopgen.set_errmsg(errmsg) self.source = resopgen.getsource() @@ -40,6 +40,7 @@ def __init__(self): self.graphs = [] + self.highlight_graphs = {} self.block_starters = {} # {graphindex: {set-of-operation-indices}} self.all_operations = {} self.errmsg = None @@ -50,9 +51,11 @@ def mark_starter(self, graphindex, opindex): self.block_starters[graphindex][opindex] = True - def add_graph(self, graph): + def add_graph(self, graph, highlight=False): graphindex = len(self.graphs) self.graphs.append(graph) + if highlight: + self.highlight_graphs[graph] = True for i, op in enumerate(graph.get_operations()): self.all_operations[op] = graphindex, i @@ -105,8 +108,12 @@ self.dotgen.emit('subgraph cluster%d {' % graphindex) label = graph.get_display_text() if label is not None: + if self.highlight_graphs.get(graph): + fillcolor = '#f084c2' + else: + fillcolor = '#84f0c2' self.dotgen.emit_node(graphname, shape="octagon", - label=label, fillcolor='#f084c2') + label=label, fillcolor=fillcolor) self.pendingedges.append((graphname, self.op_name(graphindex, 0), {})) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Tue Mar 31 18:46:31 2009 @@ -328,7 +328,10 @@ # of operations. Each branch ends in a jump which can go either to # the top of the same loop, or to another TreeLoop. -class TreeLoop(object): +class Base(object): + """Common base class for TreeLoop and History.""" + +class TreeLoop(Base): inputargs = None specnodes = None operations = None @@ -403,11 +406,19 @@ if op.is_guard(): _list_all_operations(result, op.suboperations, omit_fails) + +class ResumeDescr(AbstractDescr): + def __init__(self, guard_op, resume_info, history, history_guard_index): + self.resume_info = resume_info + self.guard_op = guard_op + self.counter = 0 + self.history = history + self.history_guard_index = history_guard_index + # ____________________________________________________________ -class RunningMatcher(object): - specnodes = None +class RunningMatcher(Base): def __init__(self, cpu): self.cpu = cpu self.inputargs = None @@ -491,7 +502,7 @@ if loop in loops: loops.remove(loop) loops.append(loop) - display_loops(loops, errmsg) + display_loops(loops, errmsg, extraloops) class CrashInJIT(Exception): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Tue Mar 31 18:46:31 2009 @@ -26,8 +26,8 @@ assert isinstance(other, FixedClass) return True -class CancelInefficientLoop(Exception): - pass +#class CancelInefficientLoop(Exception): +# pass def av_eq(self, other): return self.sort_key() == other.sort_key() @@ -119,7 +119,8 @@ return NotSpecNode() if self.cls: if not self.cls.source.equals(other.cls.source): - raise CancelInefficientLoop + #raise CancelInefficientLoop + return NotSpecNode() known_class = self.cls.source else: known_class = other.cls.source @@ -194,7 +195,7 @@ if self.virtualized: flags += 'V' return "" % (self.source, flags) -def optimize_loop(options, old_loops, history, cpu=None): +def optimize_loop(options, old_loops, loop, cpu=None): if not options.specialize: # for tests only if old_loops: return old_loops[0] @@ -202,7 +203,7 @@ return None # This does "Perfect specialization" as per doc/jitpl5.txt. - perfect_specializer = PerfectSpecializer(history, options, cpu) + perfect_specializer = PerfectSpecializer(loop, options, cpu) perfect_specializer.find_nodes() perfect_specializer.intersect_input_and_output() for old_loop in old_loops: @@ -211,11 +212,11 @@ perfect_specializer.optimize_loop() return None -def optimize_bridge(options, old_loops, history, cpu=None): +def optimize_bridge(options, old_loops, loop, cpu=None): if not options.specialize: # for tests only return old_loops[0] - perfect_specializer = PerfectSpecializer(history, options, cpu) + perfect_specializer = PerfectSpecializer(loop, options, cpu) perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop): @@ -233,8 +234,8 @@ class PerfectSpecializer(object): _allow_automatic_node_creation = False - def __init__(self, history, options=Options(), cpu=None): - self.history = history + def __init__(self, loop, options=Options(), cpu=None): + self.loop = loop self.options = options self.cpu = cpu self.nodes = {} @@ -294,14 +295,14 @@ def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True - if self.history.inputargs is not None: - for box in self.history.inputargs: + if self.loop.inputargs is not None: + for box in self.loop.inputargs: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) else: self._allow_automatic_node_creation = True # - for op in self.history.operations: + for op in self.loop.operations: #print '| ' + op.repr() opnum = op.opnum if opnum == rop.JUMP: @@ -409,15 +410,15 @@ self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): - end_args = self.history.operations[-1].args - assert len(self.history.inputargs) == len(end_args) + end_args = self.loop.operations[-1].args + assert len(self.loop.inputargs) == len(end_args) memo = {} for i in range(len(end_args)): end_box = end_args[i] if isinstance(end_box, Box): self.nodes[end_box].escape_if_startbox(memo, self.cpu) for i in range(len(end_args)): - box = self.history.inputargs[i] + box = self.loop.inputargs[i] other_box = end_args[i] if isinstance(other_box, Box): self.nodes[box].add_to_dependency_graph(self.nodes[other_box], @@ -435,11 +436,11 @@ def intersect_input_and_output(self): # Step (3) self.recursively_find_escaping_values() - jump = self.history.operations[-1] + jump = self.loop.operations[-1] assert jump.opnum == rop.JUMP specnodes = [] - for i in range(len(self.history.inputargs)): - enternode = self.nodes[self.history.inputargs[i]] + for i in range(len(self.loop.inputargs)): + enternode = self.nodes[self.loop.inputargs[i]] leavenode = self.getnode(jump.args[i]) specnodes.append(enternode.intersect(leavenode, self.nodes)) self.specnodes = specnodes @@ -554,10 +555,13 @@ # rebuild_ops.append(op1) # # end of code for dirtyfields support + op_fail = op_fail.clone() op_fail.args = unoptboxes rebuild_ops.append(op_fail) - op.suboperations = rebuild_ops - return op + op1 = op.clone() + op1.suboperations = rebuild_ops + op.jump_target = op1 + return op1 def new_arguments(self, op): newboxes = [] @@ -607,18 +611,18 @@ self._allow_automatic_node_creation = False newoperations = [] exception_might_have_happened = False - if self.history.inputargs is not None: + if self.loop.inputargs is not None: # closing a loop - assert len(self.history.inputargs) == len(self.specnodes) + assert len(self.loop.inputargs) == len(self.specnodes) for i in range(len(self.specnodes)): - box = self.history.inputargs[i] + box = self.loop.inputargs[i] self.specnodes[i].mutate_nodes(self.nodes[box]) - newinputargs = self.expanded_version_of(self.history.inputargs) + newinputargs = self.expanded_version_of(self.loop.inputargs) else: # making a bridge newinputargs = None # - for op in self.history.operations: + for op in self.loop.operations: opnum = op.opnum if opnum == rop.JUMP: args = self.expanded_version_of(op.args) @@ -626,6 +630,7 @@ if arg in self.nodes: assert not self.nodes[arg].virtual #self.cleanup_field_caches(newoperations) + op = op.clone() op.args = args newoperations.append(op) break @@ -750,6 +755,7 @@ self.nodes[box] = instnode continue # default handling of arguments and return value + op = op.clone() op.args = self.new_arguments(op) if op.is_always_pure(): for box in op.args: @@ -776,9 +782,9 @@ self.nodes[box] = instnode newoperations.append(op) # - self.history.specnodes = self.specnodes - self.history.inputargs = newinputargs - self.history.operations = newoperations + self.loop.specnodes = self.specnodes + self.loop.inputargs = newinputargs + self.loop.operations = newoperations # def cleanup_field_caches(self, newoperations): # # we need to invalidate everything @@ -811,7 +817,7 @@ return True def match(self, old_loop): - jump_op = self.history.operations[-1] + jump_op = self.loop.operations[-1] assert jump_op.opnum == rop.JUMP assert len(old_loop.specnodes) == len(jump_op.args) for i in range(len(old_loop.specnodes)): @@ -822,7 +828,7 @@ return True def adapt_for_match(self, old_loop): - jump_op = self.history.operations[-1] + jump_op = self.loop.operations[-1] assert jump_op.opnum == rop.JUMP self.specnodes = old_loop.specnodes all_offsets = [] Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 18:46:31 2009 @@ -294,6 +294,9 @@ opnum = rop.GUARD_FALSE self.env = livelist self.generate_guard(pc, opnum, box) + # note about handling self.env explicitly here: it is done in + # such a way that the 'box' on which we generate the guard is + # typically not included in the livelist. def follow_jump(self): self.pc += 1 # past the bytecode for 'goto_if_not' @@ -660,8 +663,9 @@ else: moreargs = [] guard_op = self.metainterp.history.record(opnum, moreargs, None) - op = history.ResOperation(rop.FAIL, liveboxes, None) - op.key = ResumeKey(guard_op, resume_info) + resumedescr = history.ResumeDescr(guard_op, resume_info, + self.metainterp.history, len(self.metainterp.history.operations)-1) + op = history.ResOperation(rop.FAIL, liveboxes, None, descr=resumedescr) guard_op.suboperations = [op] self.pc = saved_pc return guard_op @@ -775,7 +779,6 @@ self.stats.history = self.history def delete_history(self): - # XXX call me again later self.history = None self.framestack = None @@ -852,7 +855,8 @@ def handle_guard_failure(self, guard_failure): self.initialize_state_from_guard_failure(guard_failure) - key = guard_failure.key + key = guard_failure.descr + assert isinstance(key, history.ResumeDescr) try: self.prepare_resume_from_failure(key.guard_op.opnum) self.interpret() @@ -866,6 +870,7 @@ return self.designate_target_loop(gmp, target_loop) def designate_target_loop(self, gmp, loop): + self.delete_history() num_green_args = self.num_green_args residual_args = self.get_residual_args(loop, gmp.argboxes[num_green_args:]) @@ -893,10 +898,7 @@ old_loops = self.compiled_merge_points.setdefault(greenkey, []) self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) loop = compile_new_loop(self, old_loops) - if not loop: - if not we_are_translated(): - history.log.info('compile_new_loop() returned None') - raise self.ContinueRunningNormally(live_arg_boxes) + assert loop is not None if not we_are_translated(): loop._call_history = self._debug_history self.debug_history = [] @@ -908,17 +910,11 @@ try: old_loops = self.compiled_merge_points[greenkey] except KeyError: - target_loop = None - if not we_are_translated(): - history.log.info('no loop seen so far with this green key') - else: - self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], - None) - target_loop = compile_new_bridge(self, old_loops, key) - if not we_are_translated() and target_loop is None: - history.log.info('compile_new_bridge() returned None') - if target_loop is None: - raise self.ContinueRunningNormally(live_arg_boxes) + old_loops = [] + self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], + None) + target_loop = compile_new_bridge(self, old_loops, key) + assert target_loop is not None if not we_are_translated(): #bridge._call_history = self._debug_history self.debug_history = [] @@ -969,16 +965,18 @@ def initialize_state_from_guard_failure(self, guard_failure): # guard failure: rebuild a complete MIFrame stack - if self.state.must_compile_from_failure(guard_failure.key): + resumedescr = guard_failure.descr + assert isinstance(resumedescr, history.ResumeDescr) + if self.state.must_compile_from_failure(resumedescr): self.history = history.History(self.cpu) - suboperations = guard_failure.key.guard_op.suboperations + suboperations = resumedescr.guard_op.suboperations for i in range(len(suboperations)-1): self.history.operations.append(suboperations[i]) else: self.history = history.BlackHole(self.cpu) # the BlackHole is invalid because it doesn't start with # guard_failure.key.guard_op.suboperations, but that's fine - self.rebuild_state_after_failure(guard_failure.key.resume_info, + self.rebuild_state_after_failure(resumedescr.resume_info, guard_failure.args) def handle_exception(self): @@ -1031,10 +1029,3 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args - -class ResumeKey(object): - def __init__(self, guard_op, resume_info): - self.resume_info = resume_info - self.guard_op = guard_op - self.counter = 0 - # self.loop = ... set in compile.py Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Tue Mar 31 18:46:31 2009 @@ -2,12 +2,10 @@ class ResOperation(object): """The central ResOperation class, representing one operation.""" - # for 'jump': points to the target loop + # for 'jump': points to the target loop; + # for 'guard_*': points from the unoptimized to the optimized guard (uh) jump_target = None - # for 'fail' - key = None - # for 'guard_*' suboperations = None @@ -32,13 +30,9 @@ self.descr = descr def clone(self): - "NOT_RPYTHON" # for tests only res = ResOperation(self.opnum, self.args, self.result, self.descr) res.jump_target = self.jump_target - res.key = self.key res.vdesc = self.vdesc - if self.suboperations is not None: - res.suboperations = [op.clone() for op in self.suboperations] return res def __repr__(self): From arigo at codespeak.net Tue Mar 31 18:53:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 18:53:30 +0200 (CEST) Subject: [pypy-svn] r63457 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test Message-ID: <20090331165330.BCB9B16841C@codespeak.net> Author: arigo Date: Tue Mar 31 18:53:29 2009 New Revision: 63457 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Log: Fix some tests. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Tue Mar 31 18:53:29 2009 @@ -433,7 +433,7 @@ assert res == 5 * 10 * 3 def test_outer_and_inner_loop(self): - py.test.skip("fix me") + #py.test.skip("fix me") jitdriver = JitDriver(greens = ['p', 'code'], reds = ['i', 'j', 'total']) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_optimize.py Tue Mar 31 18:53:29 2009 @@ -8,9 +8,9 @@ from pypy.jit.metainterp import resoperation from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, - ConstAddr, History) + ConstAddr, TreeLoop) from pypy.jit.metainterp.optimize import (PerfectSpecializer, - CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, + VirtualInstanceSpecNode, FixedClassSpecNode, NotSpecNode) cpu = runner.CPU(None) @@ -35,10 +35,10 @@ # ____________________________________________________________ def Loop(inputargs, operations): - history = History(cpu) - history.inputargs = inputargs[:] - history.operations = [op.clone() for op in operations] - return history + loop = TreeLoop("test") + loop.inputargs = inputargs + loop.operations = operations + return loop class Any(object): def __eq__(self, other): @@ -141,8 +141,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [A.sum, A.v] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [A.sum, A.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), ResOperation('jump', [A.sum2, A.v2], None), @@ -189,8 +189,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [B.sum, B.n1] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [B.sum, B.n1] + equaloplists(spec.loop.operations, [ # guard_class is gone ResOperation('escape', [B.n1], None), ResOperation('getfield_gc', [B.n1], B.v, B.ofs_value), @@ -244,8 +244,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [C.sum, C.n1] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [C.sum, C.n1] + equaloplists(spec.loop.operations, [ # guard_class is gone ResOperation('escape', [C.n1], None), # <== escaping ResOperation('getfield_gc', [C.n1], C.v, C.ofs_value), @@ -276,6 +276,7 @@ ] def test_D_intersect_input_and_output(): + py.test.skip("nowadays, this compiles, just without making a virtual") spec = PerfectSpecializer(Loop(D.inputargs, D.ops)) spec.find_nodes() py.test.raises(CancelInefficientLoop, spec.intersect_input_and_output) @@ -303,15 +304,15 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [E.sum, E.v] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [E.sum, E.v] + equaloplists(spec.loop.operations, [ # guard_class is gone ResOperation('int_sub', [E.v, ConstInt(1)], E.v2), ResOperation('int_add', [E.sum, E.v], E.sum2), ResOperation('guard_true', [E.v2], None), ResOperation('jump', [E.sum2, E.v2], None), ]) - guard_op = spec.history.operations[-2] + guard_op = spec.loop.operations[-2] assert guard_op.getopname() == 'guard_true' _, n2 = guard_op.suboperations[-1].args equaloplists(guard_op.suboperations, [ @@ -326,7 +327,7 @@ ## spec.find_nodes() ## spec.intersect_input_and_output() ## spec.optimize_loop() -## guard_op = spec.history.operations[-2] +## guard_op = spec.loop.operations[-2] ## v_sum_b = BoxInt(13) ## v_v_b = BoxInt(14) ## history = History(cpu) @@ -383,8 +384,8 @@ spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped spec.optimize_loop() - assert spec.history.inputargs == [F.sum, F.v, F.n3] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [F.sum, F.v, F.n3] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [F.v, ConstInt(1)], F.v2), ResOperation('int_add', [F.sum, F.v], F.sum2), ResOperation('oononnull', [F.n3], F.vbool3), @@ -415,7 +416,7 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - equaloplists(spec.history.operations, F2.ops) + equaloplists(spec.loop.operations, F2.ops) # ____________________________________________________________ @@ -445,15 +446,15 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [G.sum, G.v] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [G.sum, G.v] + equaloplists(spec.loop.operations, [ # guard_class is gone ResOperation('int_sub', [G.v, ConstInt(1)], G.v2), ResOperation('int_add', [G.sum, G.v], G.sum2), ResOperation('guard_true', [G.v2], None), ResOperation('jump', [G.sum2, ConstInt(124)], None), ]) - guard_op = spec.history.operations[-2] + guard_op = spec.loop.operations[-2] assert guard_op.getopname() == 'guard_true' _, n2 = guard_op.suboperations[-1].args equaloplists(guard_op.suboperations, [ @@ -579,9 +580,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.history.operations[-1].args[-1] - assert spec.history.inputargs == [K0.sum, K0.n1, K0.v] - equaloplists(spec.history.operations, [ + v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [K0.sum, K0.n1, K0.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [K0.v, ConstInt(1)], K0.v2), ResOperation('int_add', [K0.sum, K0.v], K0.sum2), ResOperation('int_add', [K0.sum2, K0.v], K0.sum3), @@ -614,9 +615,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.history.operations[-1].args[-1] - assert spec.history.inputargs == [K1.sum, K1.n1, K1.v] - equaloplists(spec.history.operations, [ + v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [K1.sum, K1.n1, K1.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [K1.v, ConstInt(1)], K1.v2), ResOperation('int_add', [K1.sum, K1.v], K1.sum2), ResOperation('int_add', [K1.sum2, K1.sum], K1.sum3), @@ -648,8 +649,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [K.sum, K.n1, K.v] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [K.sum, K.n1, K.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [K.v, ConstInt(1)], K.v2), ResOperation('int_add', [K.sum, K.v], K.sum2), ResOperation('int_add', [K.sum2, K.v], K.sum3), @@ -680,8 +681,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [L.sum, L.n1, L.v] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [L.sum, L.n1, L.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [L.v, ConstInt(1)], L.v2), ResOperation('int_add', [L.sum, L.v], L.sum2), ResOperation('escape', [L.n1], None), @@ -712,9 +713,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.history.operations[-1].args[-1] - assert spec.history.inputargs == [M.sum, M.n1, M.v] - equaloplists(spec.history.operations, [ + v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [M.sum, M.n1, M.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [M.v, ConstInt(1)], M.v2), ResOperation('int_add', [M.sum, M.v], M.sum2), ResOperation('escape', [M.n1], None), @@ -744,9 +745,9 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - v4 = spec.history.operations[-1].args[-1] - assert spec.history.inputargs == [N.sum, N.n1, N.v] - equaloplists(spec.history.operations, [ + v4 = spec.loop.operations[-1].args[-1] + assert spec.loop.inputargs == [N.sum, N.n1, N.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [N.v, ConstInt(1)], N.v2), ResOperation('int_add', [N.sum, N.v], N.sum2), ResOperation('escape', [N.n1], None), @@ -773,8 +774,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [] + equaloplists(spec.loop.operations, [ ResOperation('escape', [], O1.n1), # only the first guard_class is left ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu)], @@ -803,8 +804,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [] + equaloplists(spec.loop.operations, [ ResOperation('escape', [], O2.n1), ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu)], None), @@ -835,8 +836,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [] + equaloplists(spec.loop.operations, [ ResOperation('escape', [], O3.n1), ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu)], None), @@ -874,4 +875,4 @@ # If it does, then aliasing is not correctly detected. # It is ok to reorder just the 'getfield_gc[n1], n2' operation, # but the three remaining getfields/setfields *must* be in that order. - equaloplists(spec.history.operations, P.ops) + equaloplists(spec.loop.operations, P.ops) Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_vable_optimize.py Tue Mar 31 18:53:29 2009 @@ -120,8 +120,8 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert spec.history.inputargs == [A.sum, A.fr, A.v] - equaloplists(spec.history.operations, [ + assert spec.loop.inputargs == [A.sum, A.fr, A.v] + equaloplists(spec.loop.operations, [ ResOperation('int_sub', [A.v, ConstInt(1)], A.v2), ResOperation('int_add', [A.sum, A.v], A.sum2), ResOperation('jump', [A.sum2, A.fr, A.v2], None), From arigo at codespeak.net Tue Mar 31 18:56:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 18:56:22 +0200 (CEST) Subject: [pypy-svn] r63458 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090331165622.4371216841C@codespeak.net> Author: arigo Date: Tue Mar 31 18:56:21 2009 New Revision: 63458 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Log: Fix for r63422. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 18:56:21 2009 @@ -661,7 +661,7 @@ if box is not None: moreargs = [box] + extraargs else: - moreargs = [] + moreargs = list(extraargs) guard_op = self.metainterp.history.record(opnum, moreargs, None) resumedescr = history.ResumeDescr(guard_op, resume_info, self.metainterp.history, len(self.metainterp.history.operations)-1) From arigo at codespeak.net Tue Mar 31 19:53:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 19:53:41 +0200 (CEST) Subject: [pypy-svn] r63459 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test Message-ID: <20090331175341.49DF7168478@codespeak.net> Author: arigo Date: Tue Mar 31 19:53:39 2009 New Revision: 63459 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Log: Fix. The problem was that 'old_loops' in compile_fresh_bridge() is not the same 'old_loops' that must be passed to compile_fresh_loop(). Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 31 19:53:39 2009 @@ -9,14 +9,14 @@ from pypy.jit.metainterp import optimize -def compile_new_loop(metainterp, old_loops): +def compile_new_loop(metainterp, old_loops, greenkey): """Try to compile a new loop by closing the current history back to the first operation. """ if we_are_translated(): - return compile_fresh_loop(metainterp, old_loops) + return compile_fresh_loop(metainterp, old_loops, greenkey) else: - return _compile_new_loop_1(metainterp, old_loops) + return _compile_new_loop_1(metainterp, old_loops, greenkey) def compile_new_bridge(metainterp, old_loops, resumekey): """Try to compile a new bridge leading from the beginning of the history @@ -32,10 +32,10 @@ # the following is not translatable -def _compile_new_loop_1(metainterp, old_loops): +def _compile_new_loop_1(metainterp, old_loops, greenkey): old_loops_1 = old_loops[:] try: - loop = compile_fresh_loop(metainterp, old_loops) + loop = compile_fresh_loop(metainterp, old_loops, greenkey) except Exception, exc: show_loop(metainterp, error=exc) raise @@ -83,9 +83,10 @@ # ____________________________________________________________ -def compile_fresh_loop(metainterp, old_loops): +def compile_fresh_loop(metainterp, old_loops, greenkey): history = metainterp.history loop = create_empty_loop(metainterp) + loop.greenkey = greenkey loop.inputargs = history.inputargs loop.operations = history.operations loop.operations[-1].jump_target = loop @@ -110,25 +111,23 @@ # ____________________________________________________________ -def update_loop(loop, spec): - pass - -def compile_fresh_bridge(metainterp, old_loops, resumekey): - # The history contains new operations to attach as the code for the - # failure of 'resumekey.guard_op'. First, we find the TreeLoop object - # that contains this guard operation. +def find_source_loop(resumekey): + # Find the TreeLoop object that contains this guard operation. source_loop = resumekey.history.source_link while not isinstance(source_loop, TreeLoop): source_loop = source_loop.source_link + return source_loop + +def compile_fresh_bridge(metainterp, old_loops, resumekey): + # The history contains new operations to attach as the code for the + # failure of 'resumekey.guard_op'. + # # Attempt to use optimize_bridge(). This may return None in case # it does not work -- i.e. none of the existing old_loops match. temploop = create_empty_loop(metainterp) temploop.operations = metainterp.history.operations - if len(old_loops) > 0: - target_loop = optimize.optimize_bridge(metainterp.options, old_loops, - temploop, metainterp.cpu) - else: - target_loop = None + target_loop = optimize.optimize_bridge(metainterp.options, old_loops, + temploop, metainterp.cpu) # Did it work? if target_loop is not None: # Yes, we managed to create just a bridge. Attach the new operations @@ -141,33 +140,41 @@ guard_op.suboperations = temploop.operations op = guard_op.suboperations[-1] op.jump_target = target_loop + source_loop = find_source_loop(resumekey) send_loop_to_backend(metainterp, source_loop, False) return target_loop else: - # No. In this case, we prepend to the history the unoptimized - # operations coming from the loop, in order to make a (fake) complete - # unoptimized trace. Then we can just compile this loop normally. - if not we_are_translated(): - log.info("completing the bridge into a stand-alone loop") - metainterp.history.operations = [] - append_full_operations(metainterp.history, - resumekey.history, - resumekey.history_guard_index) - metainterp.history.operations.extend(temploop.operations) - return compile_fresh_loop(metainterp, old_loops) + return None # No. prepare_loop_from_bridge() will be used. +def prepare_loop_from_bridge(metainterp, resumekey): + # To handle this case, we prepend to the history the unoptimized + # operations coming from the loop, in order to make a (fake) complete + # unoptimized trace. (Then we will just compile this loop normally.) + if not we_are_translated(): + log.info("completing the bridge into a stand-alone loop") + operations = metainterp.history.operations + metainterp.history.operations = [] + greenkey = append_full_operations(metainterp.history, + resumekey.history, + resumekey.history_guard_index) + metainterp.history.operations.extend(operations) + return greenkey + def append_full_operations(history, sourcehistory, guard_index): prev = sourcehistory.source_link if isinstance(prev, History): - append_full_operations(history, prev, sourcehistory.source_guard_index) + result = append_full_operations(history, prev, + sourcehistory.source_guard_index) else: assert history.inputargs is None assert sourcehistory.inputargs is not None history.inputargs = sourcehistory.inputargs + result = prev.greenkey history.operations.extend(sourcehistory.operations[:guard_index]) op = inverse_guard(sourcehistory.operations[guard_index]) history.operations.append(op) + return result def inverse_guard(guard_op): suboperations = guard_op.suboperations Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Tue Mar 31 19:53:39 2009 @@ -12,6 +12,7 @@ BoxInt, BoxPtr, Options) from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge +from pypy.jit.metainterp.compile import prepare_loop_from_bridge from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) from pypy.jit.metainterp import codewriter, optimize, executor @@ -865,7 +866,7 @@ try: target_loop = self.compile_bridge(key, gmp.argboxes) except self.ContinueRunningNormally: - guard_failure.key.counter = 0 + key.counter = 0 raise return self.designate_target_loop(gmp, target_loop) @@ -897,7 +898,7 @@ greenkey = original_boxes[:num_green_args] old_loops = self.compiled_merge_points.setdefault(greenkey, []) self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) - loop = compile_new_loop(self, old_loops) + loop = compile_new_loop(self, old_loops, greenkey) assert loop is not None if not we_are_translated(): loop._call_history = self._debug_history @@ -907,18 +908,22 @@ def compile_bridge(self, key, live_arg_boxes): num_green_args = self.num_green_args greenkey = live_arg_boxes[:num_green_args] + self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) try: old_loops = self.compiled_merge_points[greenkey] except KeyError: - old_loops = [] - self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], - None) - target_loop = compile_new_bridge(self, old_loops, key) - assert target_loop is not None - if not we_are_translated(): - #bridge._call_history = self._debug_history - self.debug_history = [] - return target_loop + pass + else: + target_loop = compile_new_bridge(self, old_loops, key) + if target_loop is not None: + return target_loop + # Failed to compile it as a bridge. Turn it into a complete loop. + greenkey = prepare_loop_from_bridge(self, key) + original_boxes = greenkey + self.history.inputargs + return self.compile(original_boxes, live_arg_boxes) + #if not we_are_translated(): + # bridge._call_history = self._debug_history + # self.debug_history = [] def get_residual_args(self, loop, args): if loop.specnodes is None: # it is None only for tests Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py Tue Mar 31 19:53:39 2009 @@ -466,4 +466,4 @@ res = self.meta_interp(interpret, [1]) assert res == interpret(1) # XXX it's unsure how many loops should be there - self.check_loop_count(3) + self.check_loop_count(2) From arigo at codespeak.net Tue Mar 31 19:56:24 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 19:56:24 +0200 (CEST) Subject: [pypy-svn] r63460 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090331175624.42D8E168480@codespeak.net> Author: arigo Date: Tue Mar 31 19:56:23 2009 New Revision: 63460 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Log: Remove this hack and put this in its own attribute. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Tue Mar 31 19:56:23 2009 @@ -135,8 +135,8 @@ metainterp.history.source_link = resumekey.history metainterp.history.source_guard_index = resumekey.history_guard_index guard_op = resumekey.guard_op - if guard_op.jump_target is not None: # should always be the case - guard_op = guard_op.jump_target + if guard_op.optimized is not None: # should always be the case + guard_op = guard_op.optimized guard_op.suboperations = temploop.operations op = guard_op.suboperations[-1] op.jump_target = target_loop Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Tue Mar 31 19:56:23 2009 @@ -560,7 +560,7 @@ rebuild_ops.append(op_fail) op1 = op.clone() op1.suboperations = rebuild_ops - op.jump_target = op1 + op.optimized = op1 return op1 def new_arguments(self, op): Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Tue Mar 31 19:56:23 2009 @@ -3,11 +3,11 @@ """The central ResOperation class, representing one operation.""" # for 'jump': points to the target loop; - # for 'guard_*': points from the unoptimized to the optimized guard (uh) jump_target = None # for 'guard_*' suboperations = None + optimized = None # for 'guard_nonvirtualizable' vdesc = None From arigo at codespeak.net Tue Mar 31 20:32:15 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 20:32:15 +0200 (CEST) Subject: [pypy-svn] r63463 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp Message-ID: <20090331183215.77406168418@codespeak.net> Author: arigo Date: Tue Mar 31 20:32:13 2009 New Revision: 63463 Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/TODO Log: Update TODO. Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/TODO ============================================================================== --- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/TODO (original) +++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/TODO Tue Mar 31 20:32:13 2009 @@ -1,12 +1,6 @@ -* Optimization: bridges from interpreter to compiled code - -* Virtual lists - -* Virtualizables +* do something about not seeing a loop at all; maybe disable + temporarily(?) recognizing foreign can_enter_jit() -* RPython - -* X86 backend +* Optimization: bridges from interpreter to compiled code -* PyPy! From arigo at codespeak.net Tue Mar 31 20:34:25 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 31 Mar 2009 20:34:25 +0200 (CEST) Subject: [pypy-svn] r63464 - pypy/branch/pyjitpl5-loop Message-ID: <20090331183425.4E072168418@codespeak.net> Author: arigo Date: Tue Mar 31 20:34:24 2009 New Revision: 63464 Removed: pypy/branch/pyjitpl5-loop/ Log: Remove this branch, considered as a dead-end.